1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 | package Torello.JDUInternal.Annotations.EntityAnnotations.Processor; import Torello.Java.StrSource; import Torello.Java.StringParse; import Torello.Java.Additional.EffectivelyFinal; import Torello.JavaDoc.LinkJavaSource; import Torello.JavaDoc.hidden.LJSRepeatable; import Torello.JDUInternal.Annotations.HELPER; import javax.annotation.processing.Messager; import javax.lang.model.element.Element; import javax.lang.model.element.ExecutableElement; import javax.lang.model.element.AnnotationMirror; import javax.lang.model.element.AnnotationValue; import javax.tools.Diagnostic; import java.util.List; // @LinkJavaSource Annotation: // // EXPORTS: // // public String handle(); // public String typeName() default ""; // public Entity entity(); // public String name(); // public byte paramCount() default -1; // public String[] paramNames() default { }; // public String[] paramTypesJOW() default { }; // // // The following files are relatedf to this Annotation-Mirror Data-Class: // // * Torello.JavaDoc.LinkJavaSource // For the actual annotation definition. // This is the actual @interface for the @LinkJavaSource Annotation // // * package Torello.JDUInternal.Features.LINK_JAVA_SOURCE // This package does the "vast majority" of the work that is needed process a User's // Annotation-Placement. The classes in the packages in this class look for, and load, all // of the External '.java'-Files which have been specified by the programmer's annotation // uses. These classes also perform the Source-Code HiLiting, and save the output to the // appropriate packge's '[pkg-javadoc]/ljs-hilite-files/' directory. They finally, also, // generate the appropriate "HREF=..." so that an appropriate '<A HREF...>' link may be // inserted // // * Torello.JDUInternal.Annotations.EntityAnnotations.Mirror.LJSMirror // The Data-Contents of Annotation that has been placed by the User on the Entity // (Entity: Method, Field, Constructor, Enum-Constant, Annotation-Element) // // * Torello.JDUInternal.Annotations.EntityAnnotations.Processor.LinkJSourceProcessor // The Annotation-Processor that is invoked by 'javac' when compiling a class that uses the // @LinkJavaSource Annotation. public class LinkJSourceProcessor { // This is used by the Error-Message Printer private static final String LJS_NAME = LinkJavaSource.class.getSimpleName(); public static boolean process( Element ciet, AnnotationMirror am, javax.annotation.processing.Messager messager ) { EffectivelyFinal<Boolean> errors = new EffectivelyFinal<>(false); EffectivelyFinal<Boolean> name = new EffectivelyFinal<>(false), paramNames = new EffectivelyFinal<>(false), paramTypesJOW = new EffectivelyFinal<>(false), paramCount = new EffectivelyFinal<>(false); am.getElementValues().forEach((ExecutableElement ee, AnnotationValue av) -> { // Understanding the 'terminology' in Annotations and Annotation-Processor's is half of // the work in using it. final Object val = av.getValue(); switch (ee.toString()) { case "handle()" : errors.f |= checkIdentifierAE(messager, ciet, "handle()", (String) val); break; case "typeName()" : errors.f |= checkTypeStr(messager, ciet, (String) val); break; case "entity()" : break; case "name()" : name.f = true; errors.f |= checkIdentifierAE(messager, ciet, "name()", (String) val); break; case "paramCount()": paramCount.f = true; errors.f |= checkParamCount(messager, ciet, (Byte) val); break; case "paramNames()": paramNames.f = true; errors.f |= checkParamList(messager, ciet, "paramNames()", (List) val); break; case "paramTypesJOW()": paramTypesJOW.f = true; errors.f |= checkParamList(messager, ciet, "paramTypesJOW()", (List) val); break; default: // This should be UNREACHABLE-CODE. The Java-Compiler, itself, should do the // complaining that the user supplied an Annotation-Element name that is not // among those listed above. Unless 'javac' changes, this cannot execute. throw new InternalError( "There was an annotation parameter whose name wasn't recognized: " + ee.toString() + "\n" + "The only parameter's that may be passed to @LinkJavaSource:\n" + "'handle()', 'typeName()', 'entity()', 'name()', 'paramCount()', " + "'paramNames()' and 'paramTypesJOW()'" ); } }); return errors.f; } // ******************************************************************************************** // ******************************************************************************************** // Checks both the "name()" and "handle()" Annotation-Elements // ******************************************************************************************** // ******************************************************************************************** private static boolean checkIdentifierAE( javax.annotation.processing.Messager messager, Element ciet, String aeName, String aeValAsStr ) { if (StrSource.isValidJavaIdentifier(aeValAsStr)) return true; // NOTE: Torello.JDUInternal.Messager **DOES NOT** ALLOW '\t' messager.printMessage( Diagnostic.Kind.ERROR, HELPER.LOCATION(ciet, LJS_NAME) + "\tString Annotation-Parameter '" + aeName + "' was passed " + "[" + aeValAsStr + "]\n" + "\tHowever, this is not a valid Java-Identifier." ); return false; } // ******************************************************************************************** // ******************************************************************************************** // Checks the "typeName()" Annotation-Elements // ******************************************************************************************** // ******************************************************************************************** private static boolean checkTypeStr (javax.annotation.processing.Messager messager, Element ciet, String aeValAsStr) { if (! StrSource.isJavaTypeStr(aeValAsStr)) { messager.printMessage( Diagnostic.Kind.ERROR, HELPER.LOCATION(ciet, LJS_NAME) + // NOTE: Torello.JDUInternal.Messager **DOES NOT** ALLOW '\t' "\tString Annotation-Parameter 'typeName()' was passed " + "[" + aeValAsStr + "]\n" + "\tHowever, this is not a valid Java Type-Name." ); return false; } return true; } // ******************************************************************************************** // ******************************************************************************************** // Check "paramCount()" // ******************************************************************************************** // ******************************************************************************************** private static boolean checkParamCount (javax.annotation.processing.Messager messager, Element ciet, byte paramCount) { if (paramCount < 0) { // NOTE: Torello.JDUInternal.Messager **DOES NOT** ALLOW '\t' messager.printMessage( Diagnostic.Kind.ERROR, HELPER.LOCATION(ciet, LJS_NAME) + "\t'paramCount' was passed a negative number: [" + paramCount + "]" ); return false; } return true; } // ******************************************************************************************** // ******************************************************************************************** // Check the "paramNames()" and "paramTypes()" Annotation-Elements // ******************************************************************************************** // ******************************************************************************************** @SuppressWarnings("rawtypes") private static boolean checkParamList( javax.annotation.processing.Messager messager, Element ciet, String aeName, List aeValList ) { String aeValAsStr; for (Object val : aeValList) if (! StrSource.isValidJavaIdentifier (aeValAsStr = StringParse.ifQuotesStripQuotes(val.toString())) ) { messager.printMessage( Diagnostic.Kind.ERROR, HELPER.LOCATION(ciet, LJS_NAME) + // NOTE: Torello.JDUInternal.Messager **DOES NOT** ALLOW '\t' "\tString Annotation-Parameter '" + aeName + "' was passed " + "String[]-Array Element [" + aeValAsStr + "]\n" + "\tHowever, this is not a valid Java-Identifier." ); return false; } return true; } } |