001package Torello.JavaDoc.Annotations; 002 003import Torello.Java.StrSource; 004import Torello.Java.StringParse; 005 006import Torello.Java.Additional.EffectivelyFinal; 007 008import Torello.JavaDoc.Annotations.hidden.LJSRepeatable; 009 010import javax.annotation.processing.Messager; 011 012import javax.lang.model.element.Element; 013import javax.lang.model.element.ExecutableElement; 014import javax.lang.model.element.AnnotationMirror; 015import javax.lang.model.element.AnnotationValue; 016 017import javax.tools.Diagnostic; 018 019import java.util.List; 020 021// EXPORTS: 022// 023// public String handle(); 024// public String typeName() default ""; 025// public Entity entity(); 026// public String name(); 027// public byte paramCount() default -1; 028// public String[] paramNames() default { }; 029// public String[] paramTypesJOW() default { }; 030// 031// 032// The following files are relatedf to this Annotation-Mirror Data-Class: 033// 034// * Torello.JavaDoc.LinkJavaSource 035// For the actual annotation definition. 036// This is the actual @interface for the @LinkJavaSource Annotation 037// 038// * package Torello.JDUInternal.Features.LINK_JAVA_SOURCE 039// This package does the "vast majority" of the work that is needed process a User's 040// Annotation-Placement. The classes in the packages in this class look for, and load, all 041// of the External '.java'-Files which have been specified by the programmer's annotation 042// uses. These classes also perform the Source-Code HiLiting, and save the output to the 043// appropriate packge's '[pkg-javadoc]/ljs-hilite-files/' directory. They finally, also, 044// generate the appropriate "HREF=..." so that an appropriate '<A HREF...>' link may be 045// inserted 046 047 048@Torello.JavaDoc.Annotations.JDHeaderBackgroundImg(EmbedTagFileID="ANNOT_PROC_JDHBI") 049public class LJSProcessor 050{ 051 private LJSProcessor() { } 052 053 // This is used by the Error-Message Printer 054 private static final String LJS_NAME = LinkJavaSource.class.getSimpleName(); 055 056 static boolean process( 057 Element ciet, 058 AnnotationMirror am, 059 javax.annotation.processing.Messager messager 060 ) 061 { 062 EffectivelyFinal<Boolean> errors = new EffectivelyFinal<>(false); 063 064 EffectivelyFinal<Boolean> 065 name = new EffectivelyFinal<>(false), 066 paramNames = new EffectivelyFinal<>(false), 067 paramTypesJOW = new EffectivelyFinal<>(false), 068 paramCount = new EffectivelyFinal<>(false); 069 070 am.getElementValues().forEach((ExecutableElement ee, AnnotationValue av) -> 071 { 072 // Understanding the 'terminology' in Annotations and Annotation-Processor's is half of 073 // the work in using it. 074 075 final Object val = av.getValue(); 076 077 switch (ee.toString()) 078 { 079 case "handle()" : 080 errors.f |= checkIdentifierAE(messager, ciet, "handle()", (String) val); 081 break; 082 083 case "typeName()" : 084 errors.f |= checkTypeStr(messager, ciet, (String) val); 085 break; 086 087 case "entity()" : 088 break; 089 090 case "name()" : 091 name.f = true; 092 errors.f |= checkIdentifierAE(messager, ciet, "name()", (String) val); 093 break; 094 095 case "paramCount()": 096 paramCount.f = true; 097 errors.f |= checkParamCount(messager, ciet, (Byte) val); 098 break; 099 100 case "paramNames()": 101 paramNames.f = true; 102 errors.f |= checkParamList(messager, ciet, "paramNames()", (List) val); 103 break; 104 105 case "paramTypesJOW()": 106 paramTypesJOW.f = true; 107 errors.f |= checkParamList(messager, ciet, "paramTypesJOW()", (List) val); 108 break; 109 110 default: 111 112 // This should be UNREACHABLE-CODE. The Java-Compiler, itself, should do the 113 // complaining that the user supplied an Annotation-Element name that is not 114 // among those listed above. Unless 'javac' changes, this cannot execute. 115 116 throw new InternalError( 117 "There was an annotation parameter whose name wasn't recognized: " + 118 ee.toString() + "\n" + 119 "The only parameter's that may be passed to @LinkJavaSource:\n" + 120 "'handle()', 'typeName()', 'entity()', 'name()', 'paramCount()', " + 121 "'paramNames()' and 'paramTypesJOW()'" 122 ); 123 } 124 }); 125 126 return errors.f; 127 } 128 129 130 // ******************************************************************************************** 131 // ******************************************************************************************** 132 // Checks both the "name()" and "handle()" Annotation-Elements 133 // ******************************************************************************************** 134 // ******************************************************************************************** 135 136 137 private static boolean checkIdentifierAE( 138 javax.annotation.processing.Messager messager, 139 Element ciet, 140 String aeName, 141 String aeValAsStr 142 ) 143 { 144 if (StrSource.isValidJavaIdentifier(aeValAsStr)) return true; 145 146 // NOTE: Torello.JDUInternal.Messager **DOES NOT** ALLOW '\t' 147 messager.printMessage( 148 Diagnostic.Kind.ERROR, 149 HELPER.LOCATION(ciet, LJS_NAME) + 150 "\tString Annotation-Parameter '" + aeName + "' was passed " + 151 "[" + aeValAsStr + "]\n" + 152 "\tHowever, this is not a valid Java-Identifier." 153 ); 154 155 return false; 156 } 157 158 159 // ******************************************************************************************** 160 // ******************************************************************************************** 161 // Checks the "typeName()" Annotation-Elements 162 // ******************************************************************************************** 163 // ******************************************************************************************** 164 165 166 private static boolean checkTypeStr 167 (javax.annotation.processing.Messager messager, Element ciet, String aeValAsStr) 168 { 169 if (! StrSource.isJavaTypeStr(aeValAsStr)) 170 { 171 messager.printMessage( 172 Diagnostic.Kind.ERROR, 173 HELPER.LOCATION(ciet, LJS_NAME) + 174 175 // NOTE: Torello.JDUInternal.Messager **DOES NOT** ALLOW '\t' 176 "\tString Annotation-Parameter 'typeName()' was passed " + 177 "[" + aeValAsStr + "]\n" + 178 "\tHowever, this is not a valid Java Type-Name." 179 ); 180 181 return false; 182 } 183 184 return true; 185 } 186 187 188 // ******************************************************************************************** 189 // ******************************************************************************************** 190 // Check "paramCount()" 191 // ******************************************************************************************** 192 // ******************************************************************************************** 193 194 195 private static boolean checkParamCount 196 (javax.annotation.processing.Messager messager, Element ciet, byte paramCount) 197 { 198 if (paramCount < 0) 199 { 200 // NOTE: Torello.JDUInternal.Messager **DOES NOT** ALLOW '\t' 201 messager.printMessage( 202 Diagnostic.Kind.ERROR, 203 HELPER.LOCATION(ciet, LJS_NAME) + 204 "\t'paramCount' was passed a negative number: [" + paramCount + "]" 205 ); 206 207 return false; 208 } 209 210 return true; 211 } 212 213 214 // ******************************************************************************************** 215 // ******************************************************************************************** 216 // Check the "paramNames()" and "paramTypes()" Annotation-Elements 217 // ******************************************************************************************** 218 // ******************************************************************************************** 219 220 221 @SuppressWarnings("rawtypes") 222 private static boolean checkParamList( 223 javax.annotation.processing.Messager messager, 224 Element ciet, 225 String aeName, 226 List aeValList 227 ) 228 { 229 String aeValAsStr; 230 231 for (Object val : aeValList) 232 233 if (! StrSource.isValidJavaIdentifier 234 (aeValAsStr = StringParse.ifQuotesStripQuotes(val.toString())) 235 ) 236 { 237 messager.printMessage( 238 Diagnostic.Kind.ERROR, 239 HELPER.LOCATION(ciet, LJS_NAME) + 240 241 // NOTE: Torello.JDUInternal.Messager **DOES NOT** ALLOW '\t' 242 "\tString Annotation-Parameter '" + aeName + "' was passed " + 243 "String[]-Array Element [" + aeValAsStr + "]\n" + 244 "\tHowever, this is not a valid Java-Identifier." 245 ); 246 247 return false; 248 } 249 250 return true; 251 } 252}