1 /* 2 * Copyright (c) 2021, 2024, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package java.lang.reflect; 27 28 import java.util.Collections; 29 import java.util.Objects; 30 import java.util.Map; 31 import java.util.Set; 32 import java.util.function.Function; 33 import static java.util.Map.entry; 34 35 /** 36 * Represents a JVM access or module-related flag on a runtime member, 37 * such as a {@linkplain Class class}, {@linkplain Field field}, or 38 * {@linkplain Executable method}. 39 * 40 * <P>JVM access and module-related flags are related to, but distinct 41 * from Java language {@linkplain Modifier modifiers}. Some modifiers 42 * and access flags have a one-to-one correspondence, such as {@code 43 * public}. In other cases, some language-level modifiers do 44 * <em>not</em> have an access flag, such as {@code sealed} (JVMS 45 * {@jvms 4.7.31}) and some access flags have no corresponding 46 * modifier, such as {@linkplain #SYNTHETIC synthetic}. 47 * 48 * <p>The values for the constants representing the access and module 49 * flags are taken from sections of <cite>The Java Virtual Machine 50 * Specification</cite> including {@jvms 4.1} (class access and 51 * property modifiers), {@jvms 4.5} (field access and property flags), 52 * {@jvms 4.6} (method access and property flags), {@jvms 4.7.6} 53 * (nested class access and property flags), {@jvms 4.7.24} (method 54 * parameters), and {@jvms 4.7.25} (module flags and requires, 55 * exports, and opens flags). 56 * 57 * <p>The {@linkplain #mask() mask} values for the different access 58 * flags are <em>not</em> distinct. Flags are defined for different 59 * kinds of JVM structures and the same bit position has different 60 * meanings in different contexts. For example, {@code 0x0000_0040} 61 * indicates a {@link #VOLATILE volatile} field but a {@linkplain 62 * #BRIDGE bridge method}; {@code 0x0000_0080} indicates a {@link 63 * #TRANSIENT transient} field but a {@linkplain #VARARGS variable 64 * arity (varargs)} method. 65 * 66 * @implSpec 67 * The access flag constants are ordered by non-decreasing mask 68 * value; that is the mask value of a constant is greater than or 69 * equal to the mask value of an immediate neighbor to its (syntactic) 70 * left. If new constants are added, this property will be 71 * maintained. That implies new constants will not necessarily be 72 * added at the end of the existing list. 73 * 74 * @apiNote 75 * The JVM class file format has a {@linkplain ClassFileFormatVersion new version} defined for each new 76 * {@linkplain Runtime.Version#feature() feature release}. A new class 77 * file version may define new access flags or retire old ones. {@code 78 * AccessFlag} is intended to model the set of access flags across 79 * class file format versions. The range of versions an access flag is 80 * recognized is not explicitly indicated in this API. See the current 81 * <cite>The Java Virtual Machine Specification</cite> for 82 * details. Unless otherwise indicated, access flags can be assumed to 83 * be recognized in the {@linkplain Runtime#version() current 84 * version}. 85 * 86 * @see java.lang.reflect.Modifier 87 * @see java.lang.module.ModuleDescriptor.Modifier 88 * @see java.lang.module.ModuleDescriptor.Requires.Modifier 89 * @see java.lang.module.ModuleDescriptor.Exports.Modifier 90 * @see java.lang.module.ModuleDescriptor.Opens.Modifier 91 * @see java.compiler/javax.lang.model.element.Modifier 92 * @since 20 93 */ 94 @SuppressWarnings("doclint:reference") // cross-module link 95 public enum AccessFlag { 96 // Note to maintainers: anonymous class instances are used rather 97 // than lambdas to initialize the functions used for the 98 // cffvToLocations field to avoid using lambdas too early in JDK 99 // initialization. 100 101 /** 102 * The access flag {@code ACC_PUBLIC}, corresponding to the source 103 * modifier {@link Modifier#PUBLIC public}, with a mask value of 104 * <code>{@value "0x%04x" Modifier#PUBLIC}</code>. 105 */ 106 PUBLIC(Modifier.PUBLIC, true, 107 Location.SET_PUBLIC_1, 108 new Function<ClassFileFormatVersion, Set<Location>>() { 109 @Override 110 public Set<Location> apply(ClassFileFormatVersion cffv) { 111 return (cffv == ClassFileFormatVersion.RELEASE_0) ? 112 Location.SET_CLASS_FIELD_METHOD: 113 Location.SET_PUBLIC_1; 114 } 115 }), 116 117 /** 118 * The access flag {@code ACC_PRIVATE}, corresponding to the 119 * source modifier {@link Modifier#PRIVATE private}, with a mask 120 * value of <code>{@value "0x%04x" Modifier#PRIVATE}</code>. 121 */ 122 PRIVATE(Modifier.PRIVATE, true, Location.SET_FIELD_METHOD_INNER_CLASS, 123 new Function<ClassFileFormatVersion, Set<Location>>() { 124 @Override 125 public Set<Location> apply(ClassFileFormatVersion cffv) { 126 return (cffv == ClassFileFormatVersion.RELEASE_0) ? 127 Location.SET_FIELD_METHOD: 128 Location.SET_FIELD_METHOD_INNER_CLASS; 129 } 130 }), 131 132 /** 133 * The access flag {@code ACC_PROTECTED}, corresponding to the 134 * source modifier {@link Modifier#PROTECTED protected}, with a mask 135 * value of <code>{@value "0x%04x" Modifier#PROTECTED}</code>. 136 */ 137 PROTECTED(Modifier.PROTECTED, true, Location.SET_FIELD_METHOD_INNER_CLASS, 138 new Function<ClassFileFormatVersion, Set<Location>>() { 139 @Override 140 public Set<Location> apply(ClassFileFormatVersion cffv) { 141 return (cffv == ClassFileFormatVersion.RELEASE_0) ? 142 Location.SET_FIELD_METHOD: 143 Location.SET_FIELD_METHOD_INNER_CLASS; 144 } 145 }), 146 147 /** 148 * The access flag {@code ACC_STATIC}, corresponding to the source 149 * modifier {@link Modifier#STATIC static}, with a mask value of 150 * <code>{@value "0x%04x" Modifier#STATIC}</code>. 151 */ 152 STATIC(Modifier.STATIC, true, Location.SET_FIELD_METHOD_INNER_CLASS, 153 new Function<ClassFileFormatVersion, Set<Location>>() { 154 @Override 155 public Set<Location> apply(ClassFileFormatVersion cffv) { 156 return (cffv == ClassFileFormatVersion.RELEASE_0) ? 157 Location.SET_FIELD_METHOD: 158 Location.SET_FIELD_METHOD_INNER_CLASS;} 159 }), 160 161 /** 162 * The access flag {@code ACC_FINAL}, corresponding to the source 163 * modifier {@link Modifier#FINAL final}, with a mask 164 * value of <code>{@value "0x%04x" Modifier#FINAL}</code>. 165 */ 166 FINAL(Modifier.FINAL, true, 167 Location.SET_FINAL_8, 168 new Function<ClassFileFormatVersion, Set<Location>>() { 169 @Override 170 public Set<Location> apply(ClassFileFormatVersion cffv) { 171 if (cffv.compareTo(ClassFileFormatVersion.RELEASE_8) >= 0) { 172 return Location.SET_FINAL_8; 173 } else { 174 return (cffv == ClassFileFormatVersion.RELEASE_0) ? 175 Location.SET_CLASS_FIELD_METHOD : 176 Location.SET_CLASS_FIELD_METHOD_INNER_CLASS; 177 } 178 } 179 }), 180 181 /** 182 * The access flag {@code ACC_SUPER} with a mask value of {@code 183 * 0x0020}. 184 * 185 * @apiNote 186 * In Java SE 8 and above, the JVM treats the {@code ACC_SUPER} 187 * flag as set in every class file (JVMS {@jvms 4.1}). 188 */ 189 SUPER(0x0000_0020, false, Location.SET_CLASS, null), 190 191 /** 192 * The module flag {@code ACC_OPEN} with a mask value of {@code 193 * 0x0020}. 194 * @see java.lang.module.ModuleDescriptor#isOpen 195 */ 196 OPEN(0x0000_0020, false, Location.SET_MODULE, 197 new Function<ClassFileFormatVersion, Set<Location>>() { 198 @Override 199 public Set<Location> apply(ClassFileFormatVersion cffv) { 200 return (cffv.compareTo(ClassFileFormatVersion.RELEASE_9) >= 0 ) ? 201 Location.SET_MODULE: 202 Location.EMPTY_SET;} 203 }), 204 205 /** 206 * The module requires flag {@code ACC_TRANSITIVE} with a mask 207 * value of {@code 0x0020}. 208 * @see java.lang.module.ModuleDescriptor.Requires.Modifier#TRANSITIVE 209 */ 210 TRANSITIVE(0x0000_0020, false, Location.SET_MODULE_REQUIRES, 211 new Function<ClassFileFormatVersion, Set<Location>>() { 212 @Override 213 public Set<Location> apply(ClassFileFormatVersion cffv) { 214 return (cffv.compareTo(ClassFileFormatVersion.RELEASE_9) >= 0 ) ? 215 Location.SET_MODULE_REQUIRES: 216 Location.EMPTY_SET;} 217 }), 218 219 /** 220 * The access flag {@code ACC_SYNCHRONIZED}, corresponding to the 221 * source modifier {@link Modifier#SYNCHRONIZED synchronized}, with 222 * a mask value of <code>{@value "0x%04x" Modifier#SYNCHRONIZED}</code>. 223 */ 224 SYNCHRONIZED(Modifier.SYNCHRONIZED, true, Location.SET_METHOD, null), 225 226 /** 227 * The module requires flag {@code ACC_STATIC_PHASE} with a mask 228 * value of {@code 0x0040}. 229 * @see java.lang.module.ModuleDescriptor.Requires.Modifier#STATIC 230 */ 231 STATIC_PHASE(0x0000_0040, false, Location.SET_MODULE_REQUIRES, 232 new Function<ClassFileFormatVersion, Set<Location>>() { 233 @Override 234 public Set<Location> apply(ClassFileFormatVersion cffv) { 235 return (cffv.compareTo(ClassFileFormatVersion.RELEASE_9) >= 0 ) ? 236 Location.SET_MODULE_REQUIRES: 237 Location.EMPTY_SET;} 238 }), 239 240 /** 241 * The access flag {@code ACC_VOLATILE}, corresponding to the 242 * source modifier {@link Modifier#VOLATILE volatile}, with a mask 243 * value of <code>{@value "0x%04x" Modifier#VOLATILE}</code>. 244 */ 245 VOLATILE(Modifier.VOLATILE, true, Location.SET_FIELD, null), 246 247 /** 248 * The access flag {@code ACC_BRIDGE} with a mask value of 249 * <code>{@value "0x%04x" Modifier#BRIDGE}</code> 250 * @see Method#isBridge() 251 */ 252 BRIDGE(Modifier.BRIDGE, false, Location.SET_METHOD, 253 new Function<ClassFileFormatVersion, Set<Location>>() { 254 @Override 255 public Set<Location> apply(ClassFileFormatVersion cffv) { 256 return (cffv.compareTo(ClassFileFormatVersion.RELEASE_5) >= 0 ) ? 257 Location.SET_METHOD: 258 Location.EMPTY_SET;} 259 }), 260 261 /** 262 * The access flag {@code ACC_TRANSIENT}, corresponding to the 263 * source modifier {@link Modifier#TRANSIENT transient}, with a 264 * mask value of <code>{@value "0x%04x" Modifier#TRANSIENT}</code>. 265 */ 266 TRANSIENT(Modifier.TRANSIENT, true, Location.SET_FIELD, null), 267 268 /** 269 * The access flag {@code ACC_VARARGS} with a mask value of 270 <code>{@value "0x%04x" Modifier#VARARGS}</code>. 271 * @see Executable#isVarArgs() 272 */ 273 VARARGS(Modifier.VARARGS, false, Location.SET_METHOD, 274 new Function<ClassFileFormatVersion, Set<Location>>() { 275 @Override 276 public Set<Location> apply(ClassFileFormatVersion cffv) { 277 return (cffv.compareTo(ClassFileFormatVersion.RELEASE_5) >= 0 ) ? 278 Location.SET_METHOD: 279 Location.EMPTY_SET;} 280 }), 281 282 /** 283 * The access flag {@code ACC_NATIVE}, corresponding to the source 284 * modifier {@link Modifier#NATIVE native}, with a mask value of 285 * <code>{@value "0x%04x" Modifier#NATIVE}</code>. 286 */ 287 NATIVE(Modifier.NATIVE, true, Location.SET_METHOD, null), 288 289 /** 290 * The access flag {@code ACC_INTERFACE} with a mask value of 291 * {@code 0x0200}. 292 * @see Class#isInterface() 293 */ 294 INTERFACE(Modifier.INTERFACE, false, Location.SET_CLASS_INNER_CLASS, 295 new Function<ClassFileFormatVersion, Set<Location>>() { 296 @Override 297 public Set<Location> apply(ClassFileFormatVersion cffv) { 298 return (cffv.compareTo(ClassFileFormatVersion.RELEASE_0) == 0 ) ? 299 Location.SET_CLASS: 300 Location.SET_CLASS_INNER_CLASS;} 301 }), 302 303 /** 304 * The access flag {@code ACC_ABSTRACT}, corresponding to the 305 * source modifier {@link Modifier#ABSTRACT abstract}, with a mask 306 * value of <code>{@value "0x%04x" Modifier#ABSTRACT}</code>. 307 */ 308 ABSTRACT(Modifier.ABSTRACT, true, 309 Location.SET_CLASS_METHOD_INNER_CLASS, 310 new Function<ClassFileFormatVersion, Set<Location>>() { 311 @Override 312 public Set<Location> apply(ClassFileFormatVersion cffv) { 313 return (cffv.compareTo(ClassFileFormatVersion.RELEASE_0) == 0 ) ? 314 Location.SET_CLASS_METHOD: 315 Location.SET_CLASS_METHOD_INNER_CLASS;} 316 }), 317 318 /** 319 * The access flag {@code ACC_STRICT}, corresponding to the source 320 * modifier {@link Modifier#STRICT strictfp}, with a mask value of 321 * <code>{@value "0x%04x" Modifier#STRICT}</code>. 322 * 323 * @apiNote 324 * The {@code ACC_STRICT} access flag is defined for class file 325 * major versions 46 through 60, inclusive (JVMS {@jvms 4.6}), 326 * corresponding to Java SE 1.2 through 16. 327 */ 328 STRICT(Modifier.STRICT, true, Location.EMPTY_SET, 329 new Function<ClassFileFormatVersion, Set<Location>>() { 330 @Override 331 public Set<Location> apply(ClassFileFormatVersion cffv) { 332 return (cffv.compareTo(ClassFileFormatVersion.RELEASE_2) >= 0 && 333 cffv.compareTo(ClassFileFormatVersion.RELEASE_16) <= 0) ? 334 Location.SET_METHOD: 335 Location.EMPTY_SET;} 336 }), 337 338 /** 339 * The access flag {@code ACC_SYNTHETIC} with a mask value of 340 * <code>{@value "0x%04x" Modifier#SYNTHETIC}</code>. 341 * @see Class#isSynthetic() 342 * @see Executable#isSynthetic() 343 * @see java.lang.module.ModuleDescriptor.Modifier#SYNTHETIC 344 */ 345 SYNTHETIC(Modifier.SYNTHETIC, false, Location.SET_SYNTHETIC_9, 346 new Function<ClassFileFormatVersion, Set<Location>>() { 347 @Override 348 public Set<Location> apply(ClassFileFormatVersion cffv) { 349 if (cffv.compareTo(ClassFileFormatVersion.RELEASE_9) >= 0 ) 350 return Location.SET_SYNTHETIC_9; 351 else { 352 return 353 switch(cffv) { 354 case RELEASE_7 -> Location.SET_SYNTHETIC_7; 355 case RELEASE_8 -> Location.SET_SYNTHETIC_8; 356 default -> Location.EMPTY_SET; 357 }; 358 } 359 } 360 }), 361 362 /** 363 * The access flag {@code ACC_ANNOTATION} with a mask value of 364 * <code>{@value "0x%04x" Modifier#ANNOTATION}</code>. 365 * @see Class#isAnnotation() 366 */ 367 ANNOTATION(Modifier.ANNOTATION, false, Location.SET_CLASS_INNER_CLASS, 368 new Function<ClassFileFormatVersion, Set<Location>>() { 369 @Override 370 public Set<Location> apply(ClassFileFormatVersion cffv) { 371 return (cffv.compareTo(ClassFileFormatVersion.RELEASE_5) >= 0 ) ? 372 Location.SET_CLASS_INNER_CLASS: 373 Location.EMPTY_SET;} 374 }), 375 376 /** 377 * The access flag {@code ACC_ENUM} with a mask value of 378 * <code>{@value "0x%04x" Modifier#ENUM}</code>. 379 * @see Class#isEnum() 380 */ 381 ENUM(Modifier.ENUM, false, Location.SET_CLASS_FIELD_INNER_CLASS, 382 new Function<ClassFileFormatVersion, Set<Location>>() { 383 @Override 384 public Set<Location> apply(ClassFileFormatVersion cffv) { 385 return (cffv.compareTo(ClassFileFormatVersion.RELEASE_5) >= 0 ) ? 386 Location.SET_CLASS_FIELD_INNER_CLASS: 387 Location.EMPTY_SET;} 388 }), 389 390 /** 391 * The access flag {@code ACC_MANDATED} with a mask value of 392 * <code>{@value "0x%04x" Modifier#MANDATED}</code>. 393 */ 394 MANDATED(Modifier.MANDATED, false, Location.SET_MANDATED_9, 395 new Function<ClassFileFormatVersion, Set<Location>>() { 396 @Override 397 public Set<Location> apply(ClassFileFormatVersion cffv) { 398 if (cffv.compareTo(ClassFileFormatVersion.RELEASE_9) >= 0 ) { 399 return Location.SET_MANDATED_9; 400 } else { 401 return (cffv == ClassFileFormatVersion.RELEASE_8) ? 402 Location.SET_METHOD_PARAM: 403 Location.EMPTY_SET; 404 } 405 } 406 }), 407 408 /** 409 * The access flag {@code ACC_MODULE} with a mask value of {@code 410 * 0x8000}. 411 */ 412 MODULE(0x0000_8000, false, Location.SET_CLASS, 413 new Function<ClassFileFormatVersion, Set<Location>>() { 414 @Override 415 public Set<Location> apply(ClassFileFormatVersion cffv) { 416 return (cffv.compareTo(ClassFileFormatVersion.RELEASE_9) >= 0 ) ? 417 Location.SET_CLASS: 418 Location.EMPTY_SET;} 419 }) 420 ; 421 422 // May want to override toString for a different enum constant -> 423 // name mapping. 424 425 private final int mask; 426 private final boolean sourceModifier; 427 428 // Intentionally using Set rather than EnumSet since EnumSet is 429 // mutable. 430 private final Set<Location> locations; 431 // Lambda to implement locations(ClassFileFormatVersion cffv) 432 private final Function<ClassFileFormatVersion, Set<Location>> cffvToLocations; 433 434 private AccessFlag(int mask, 435 boolean sourceModifier, 436 Set<Location> locations, 437 Function<ClassFileFormatVersion, Set<Location>> cffvToLocations) { 438 this.mask = mask; 439 this.sourceModifier = sourceModifier; 440 this.locations = locations; 441 this.cffvToLocations = cffvToLocations; 442 } 443 444 /** 445 * {@return the corresponding integer mask for the access flag} 446 */ 447 public int mask() { 448 return mask; 449 } 450 451 /** 452 * {@return whether or not the flag has a directly corresponding 453 * modifier in the Java programming language} 454 */ 455 public boolean sourceModifier() { 456 return sourceModifier; 457 } 458 459 /** 460 * {@return kinds of constructs the flag can be applied to in the 461 * latest class file format version} 462 */ 463 public Set<Location> locations() { 464 return locations; 465 } 466 467 /** 468 * {@return kinds of constructs the flag can be applied to in the 469 * given class file format version} 470 * @param cffv the class file format version to use 471 * @throws NullPointerException if the parameter is {@code null} 472 */ 473 public Set<Location> locations(ClassFileFormatVersion cffv) { 474 Objects.requireNonNull(cffv); 475 if (cffvToLocations == null) { 476 return locations; 477 } else { 478 return cffvToLocations.apply(cffv); 479 } 480 } 481 482 /** 483 * {@return an unmodifiable set of access flags for the given mask value 484 * appropriate for the location in question} 485 * 486 * @param mask bit mask of access flags 487 * @param location context to interpret mask value 488 * @throws IllegalArgumentException if the mask contains bit 489 * positions not support for the location in question 490 */ 491 public static Set<AccessFlag> maskToAccessFlags(int mask, Location location) { 492 Set<AccessFlag> result = java.util.EnumSet.noneOf(AccessFlag.class); 493 for (var accessFlag : LocationToFlags.locationToFlags.get(location)) { 494 int accessMask = accessFlag.mask(); 495 if ((mask & accessMask) != 0) { 496 result.add(accessFlag); 497 mask = mask & ~accessMask; 498 } 499 } 500 if (mask != 0) { 501 throw new IllegalArgumentException("Unmatched bit position 0x" + 502 Integer.toHexString(mask) + 503 " for location " + location); 504 } 505 return Collections.unmodifiableSet(result); 506 } 507 508 /** 509 * A location within a class file where flags can be applied. 510 * 511 * Note that since these locations represent class file structures 512 * rather than language structures many language structures, such 513 * as constructors and interfaces, are <em>not</em> present. 514 * @since 20 515 */ 516 public enum Location { 517 /** 518 * Class location. 519 * @jvms 4.1 The ClassFile Structure 520 */ 521 CLASS, 522 523 /** 524 * Field location. 525 * @jvms 4.5 Fields 526 */ 527 FIELD, 528 529 /** 530 * Method location. 531 * @jvms 4.6 Methods 532 */ 533 METHOD, 534 535 /** 536 * Inner class location. 537 * @jvms 4.7.6 The InnerClasses Attribute 538 */ 539 INNER_CLASS, 540 541 /** 542 * Method parameter location. 543 * @jvms 4.7.24 The MethodParameters Attribute 544 */ 545 METHOD_PARAMETER, 546 547 /** 548 * Module location 549 * @jvms 4.7.25 The Module Attribute 550 */ 551 MODULE, 552 553 /** 554 * Module requires location 555 * @jvms 4.7.25 The Module Attribute 556 */ 557 MODULE_REQUIRES, 558 559 /** 560 * Module exports location 561 * @jvms 4.7.25 The Module Attribute 562 */ 563 MODULE_EXPORTS, 564 565 /** 566 * Module opens location 567 * @jvms 4.7.25 The Module Attribute 568 */ 569 MODULE_OPENS; 570 571 // Repeated sets of locations used by AccessFlag constants 572 private static final Set<Location> EMPTY_SET = Set.of(); 573 private static final Set<Location> SET_MODULE = Set.of(MODULE); 574 private static final Set<Location> SET_CLASS_METHOD_INNER_CLASS = 575 Set.of(CLASS, METHOD, INNER_CLASS); 576 private static final Set<Location> SET_CLASS_FIELD_METHOD = 577 Set.of(CLASS, FIELD, METHOD); 578 private static final Set<Location> SET_CLASS_FIELD_INNER_CLASS = 579 Set.of(CLASS, FIELD, INNER_CLASS); 580 private static final Set<Location> SET_CLASS_FIELD_METHOD_INNER_CLASS = 581 Set.of(CLASS, FIELD, METHOD, INNER_CLASS); 582 private static final Set<Location> SET_CLASS_METHOD = 583 Set.of(CLASS, METHOD); 584 private static final Set<Location> SET_FIELD_METHOD = 585 Set.of(FIELD, METHOD); 586 private static final Set<Location> SET_FIELD_METHOD_INNER_CLASS = 587 Set.of(FIELD, METHOD, INNER_CLASS); 588 private static final Set<Location> SET_METHOD = Set.of(METHOD); 589 private static final Set<Location> SET_METHOD_PARAM = Set.of(METHOD_PARAMETER); 590 private static final Set<Location> SET_FIELD = Set.of(FIELD); 591 private static final Set<Location> SET_CLASS = Set.of(CLASS); 592 private static final Set<Location> SET_CLASS_INNER_CLASS = 593 Set.of(CLASS, INNER_CLASS); 594 private static final Set<Location> SET_MODULE_REQUIRES = 595 Set.of(MODULE_REQUIRES); 596 private static final Set<Location> SET_PUBLIC_1 = 597 Set.of(CLASS, FIELD, METHOD, INNER_CLASS); 598 private static final Set<Location> SET_FINAL_8 = 599 Set.of(CLASS, FIELD, METHOD, 600 INNER_CLASS, /* added in 1.1 */ 601 METHOD_PARAMETER); /* added in 8 */ 602 private static final Set<Location> SET_SYNTHETIC_7 = 603 Set.of(CLASS, FIELD, METHOD, 604 INNER_CLASS); 605 private static final Set<Location> SET_SYNTHETIC_8 = 606 Set.of(CLASS, FIELD, METHOD, 607 INNER_CLASS, METHOD_PARAMETER); 608 private static final Set<Location> SET_SYNTHETIC_9 = 609 // Added as an access flag in 7 610 Set.of(CLASS, FIELD, METHOD, 611 INNER_CLASS, 612 METHOD_PARAMETER, // Added in 8 613 // Module-related items added in 9 614 MODULE, MODULE_REQUIRES, 615 MODULE_EXPORTS, MODULE_OPENS); 616 private static final Set<Location> SET_MANDATED_9 = 617 Set.of(METHOD_PARAMETER, // From 8 618 // Starting in 9 619 MODULE, MODULE_REQUIRES, 620 MODULE_EXPORTS, MODULE_OPENS); 621 } 622 623 private static class LocationToFlags { 624 private static Map<Location, Set<AccessFlag>> locationToFlags = 625 Map.ofEntries(entry(Location.CLASS, 626 Set.of(PUBLIC, FINAL, SUPER, 627 INTERFACE, ABSTRACT, 628 SYNTHETIC, ANNOTATION, 629 ENUM, AccessFlag.MODULE)), 630 entry(Location.FIELD, 631 Set.of(PUBLIC, PRIVATE, PROTECTED, 632 STATIC, FINAL, VOLATILE, 633 TRANSIENT, SYNTHETIC, ENUM)), 634 entry(Location.METHOD, 635 Set.of(PUBLIC, PRIVATE, PROTECTED, 636 STATIC, FINAL, SYNCHRONIZED, 637 BRIDGE, VARARGS, NATIVE, 638 ABSTRACT, STRICT, SYNTHETIC)), 639 entry(Location.INNER_CLASS, 640 Set.of(PUBLIC, PRIVATE, PROTECTED, 641 STATIC, FINAL, INTERFACE, ABSTRACT, 642 SYNTHETIC, ANNOTATION, ENUM)), 643 entry(Location.METHOD_PARAMETER, 644 Set.of(FINAL, SYNTHETIC, MANDATED)), 645 entry(Location.MODULE, 646 Set.of(OPEN, SYNTHETIC, MANDATED)), 647 entry(Location.MODULE_REQUIRES, 648 Set.of(TRANSITIVE, STATIC_PHASE, SYNTHETIC, MANDATED)), 649 entry(Location.MODULE_EXPORTS, 650 Set.of(SYNTHETIC, MANDATED)), 651 entry(Location.MODULE_OPENS, 652 Set.of(SYNTHETIC, MANDATED))); 653 } 654 }