63 */ 64 protected ProcessingEnvironment processingEnv; 65 private boolean initialized = false; 66 67 /** 68 * Constructor for subclasses to call. 69 */ 70 protected AbstractProcessor() {} 71 72 /** 73 * If the processor class is annotated with {@link 74 * SupportedOptions}, return an unmodifiable set with the same set 75 * of strings as the annotation. If the class is not so 76 * annotated, an empty set is returned. 77 * 78 * @return the options recognized by this processor, or an empty 79 * set if none 80 */ 81 public Set<String> getSupportedOptions() { 82 SupportedOptions so = this.getClass().getAnnotation(SupportedOptions.class); 83 if (so == null) 84 return Collections.emptySet(); 85 else 86 return arrayToSet(so.value(), false); 87 } 88 89 /** 90 * If the processor class is annotated with {@link 91 * SupportedAnnotationTypes}, return an unmodifiable set with the 92 * same set of strings as the annotation. If the class is not so 93 * annotated, an empty set is returned. 94 * 95 * If the {@linkplain ProcessingEnvironment#getSourceVersion source 96 * version} does not support modules, in other words if it is less 97 * than or equal to {@link SourceVersion#RELEASE_8 RELEASE_8}, 98 * then any leading {@linkplain Processor#getSupportedAnnotationTypes 99 * module prefixes} are stripped from the names. 100 * 101 * @return the names of the annotation types supported by this 102 * processor, or an empty set if none 103 */ 104 public Set<String> getSupportedAnnotationTypes() { 105 SupportedAnnotationTypes sat = this.getClass().getAnnotation(SupportedAnnotationTypes.class); 106 boolean initialized = isInitialized(); 107 if (sat == null) { 108 if (initialized) 109 processingEnv.getMessager().printMessage(Diagnostic.Kind.WARNING, 110 "No SupportedAnnotationTypes annotation " + 111 "found on " + this.getClass().getName() + 112 ", returning an empty set."); 113 return Collections.emptySet(); 114 } else { 115 boolean stripModulePrefixes = 116 initialized && 117 processingEnv.getSourceVersion().compareTo(SourceVersion.RELEASE_8) <= 0; 118 return arrayToSet(sat.value(), stripModulePrefixes); 119 } 120 } 121 122 /** 123 * If the processor class is annotated with {@link 124 * SupportedSourceVersion}, return the source version in the 125 * annotation. If the class is not so annotated, {@link 126 * SourceVersion#RELEASE_6} is returned. 127 * 128 * @return the latest source version supported by this processor 129 */ 130 public SourceVersion getSupportedSourceVersion() { 131 SupportedSourceVersion ssv = this.getClass().getAnnotation(SupportedSourceVersion.class); 132 SourceVersion sv = null; 133 if (ssv == null) { 134 sv = SourceVersion.RELEASE_6; 135 if (isInitialized()) 136 processingEnv.getMessager().printMessage(Diagnostic.Kind.WARNING, 137 "No SupportedSourceVersion annotation " + 138 "found on " + this.getClass().getName() + 178 * @param userText {@inheritDoc} 179 */ 180 public Iterable<? extends Completion> getCompletions(Element element, 181 AnnotationMirror annotation, 182 ExecutableElement member, 183 String userText) { 184 return Collections.emptyList(); 185 } 186 187 /** 188 * Returns {@code true} if this object has been {@linkplain #init 189 * initialized}, {@code false} otherwise. 190 * 191 * @return {@code true} if this object has been initialized, 192 * {@code false} otherwise. 193 */ 194 protected synchronized boolean isInitialized() { 195 return initialized; 196 } 197 198 private static Set<String> arrayToSet(String[] array, 199 boolean stripModulePrefixes) { 200 assert array != null; 201 Set<String> set = new HashSet<>(array.length); 202 for (String s : array) { 203 if (stripModulePrefixes) { 204 int index = s.indexOf('/'); 205 if (index != -1) 206 s = s.substring(index + 1); 207 } 208 set.add(s); 209 } 210 return Collections.unmodifiableSet(set); 211 } 212 } | 63 */ 64 protected ProcessingEnvironment processingEnv; 65 private boolean initialized = false; 66 67 /** 68 * Constructor for subclasses to call. 69 */ 70 protected AbstractProcessor() {} 71 72 /** 73 * If the processor class is annotated with {@link 74 * SupportedOptions}, return an unmodifiable set with the same set 75 * of strings as the annotation. If the class is not so 76 * annotated, an empty set is returned. 77 * 78 * @return the options recognized by this processor, or an empty 79 * set if none 80 */ 81 public Set<String> getSupportedOptions() { 82 SupportedOptions so = this.getClass().getAnnotation(SupportedOptions.class); 83 return (so == null) ? 84 Set.of() : 85 arrayToSet(so.value(), false, "option value", "@SupportedOptions"); 86 } 87 88 /** 89 * If the processor class is annotated with {@link 90 * SupportedAnnotationTypes}, return an unmodifiable set with the 91 * same set of strings as the annotation. If the class is not so 92 * annotated, an empty set is returned. 93 * 94 * If the {@linkplain ProcessingEnvironment#getSourceVersion source 95 * version} does not support modules, in other words if it is less 96 * than or equal to {@link SourceVersion#RELEASE_8 RELEASE_8}, 97 * then any leading {@linkplain Processor#getSupportedAnnotationTypes 98 * module prefixes} are stripped from the names. 99 * 100 * @return the names of the annotation types supported by this 101 * processor, or an empty set if none 102 */ 103 public Set<String> getSupportedAnnotationTypes() { 104 SupportedAnnotationTypes sat = this.getClass().getAnnotation(SupportedAnnotationTypes.class); 105 boolean initialized = isInitialized(); 106 if (sat == null) { 107 if (initialized) 108 processingEnv.getMessager().printMessage(Diagnostic.Kind.WARNING, 109 "No SupportedAnnotationTypes annotation " + 110 "found on " + this.getClass().getName() + 111 ", returning an empty set."); 112 return Set.of(); 113 } else { 114 boolean stripModulePrefixes = 115 initialized && 116 processingEnv.getSourceVersion().compareTo(SourceVersion.RELEASE_8) <= 0; 117 return arrayToSet(sat.value(),stripModulePrefixes, 118 "annotation type", "@SupportedAnnotationTypes"); 119 } 120 } 121 122 /** 123 * If the processor class is annotated with {@link 124 * SupportedSourceVersion}, return the source version in the 125 * annotation. If the class is not so annotated, {@link 126 * SourceVersion#RELEASE_6} is returned. 127 * 128 * @return the latest source version supported by this processor 129 */ 130 public SourceVersion getSupportedSourceVersion() { 131 SupportedSourceVersion ssv = this.getClass().getAnnotation(SupportedSourceVersion.class); 132 SourceVersion sv = null; 133 if (ssv == null) { 134 sv = SourceVersion.RELEASE_6; 135 if (isInitialized()) 136 processingEnv.getMessager().printMessage(Diagnostic.Kind.WARNING, 137 "No SupportedSourceVersion annotation " + 138 "found on " + this.getClass().getName() + 178 * @param userText {@inheritDoc} 179 */ 180 public Iterable<? extends Completion> getCompletions(Element element, 181 AnnotationMirror annotation, 182 ExecutableElement member, 183 String userText) { 184 return Collections.emptyList(); 185 } 186 187 /** 188 * Returns {@code true} if this object has been {@linkplain #init 189 * initialized}, {@code false} otherwise. 190 * 191 * @return {@code true} if this object has been initialized, 192 * {@code false} otherwise. 193 */ 194 protected synchronized boolean isInitialized() { 195 return initialized; 196 } 197 198 private Set<String> arrayToSet(String[] array, 199 boolean stripModulePrefixes, 200 String contentType, 201 String annotationName) { 202 assert array != null; 203 Set<String> set = new HashSet<>(); 204 for (String s : array) { 205 if (stripModulePrefixes) { 206 int index = s.indexOf('/'); 207 if (index != -1) 208 s = s.substring(index + 1); 209 } 210 boolean added = set.add(s); 211 if (!added && initialized) { 212 processingEnv.getMessager().printMessage(Diagnostic.Kind.WARNING, 213 "Duplicate " + contentType + 214 " ``" + s + "'' for processor " + 215 this.getClass().getName() + 216 " in its " + annotationName + 217 "annotation."); 218 } 219 } 220 return Collections.unmodifiableSet(set); 221 } 222 } |