private void logSingleError(AnnotationValue singleErrorAnnotation) { AnnotationMirror singleErrorMirror = (AnnotationMirror) singleErrorAnnotation.getValue(); TypeMirror errorClass = utils.getTypeMirrorsFromAnnotationValue( utils.getAnnotationValueFromMirror(singleErrorMirror, "specClass")).get(0); String errorMessage = utils.getValuesFromAnnotationValue( utils.getAnnotationValueFromMirror(singleErrorMirror, "message"), String.class).get(0); List<String> errorElementValues = utils.getValuesFromAnnotationValue( utils.getAnnotationValueFromMirror(singleErrorMirror, "element"), String.class); String errorElementName = AptUtils.isEmpty(errorElementValues) ? null : errorElementValues.get(0); Element errorElement = findErrorElement(errorClass, errorElementName); utils.getMessager().printMessage(Diagnostic.Kind.ERROR, errorMessage, errorElement); }
@Override public synchronized void init(ProcessingEnvironment processingEnv) { super.init(processingEnv); this.utils = new AptUtils(processingEnv); }
@Override public void addRequiredImports(Set<DeclaredTypeName> imports) { utils.accumulateImportsFromElements(imports, modelMethods); utils.accumulateImportsFromElements(imports, staticModelMethods); }
private void reportUnsupportedOptions() { Set<String> unsupportedOptions = new HashSet<>(squidbOptions); unsupportedOptions.removeAll(SQUIDB_SUPPORTED_OPTIONS); if (AptUtils.isEmpty(unsupportedOptions)) { return; } StringBuilder sb = new StringBuilder(); for (String option : unsupportedOptions) { if (sb.length() > 0) { sb.append(SEPARATOR); } sb.append(option); } String message = String.format(UNSUPPORTED_OPTIONS_WARNING, sb); utils.getMessager().printMessage(Diagnostic.Kind.WARNING, message); }
private void parseInterfaces() { TypeElement modelSpecElement = modelSpec.getModelSpecElement(); if (modelSpecElement.getAnnotation(Implements.class) != null) { List<DeclaredTypeName> typeNames = utils.getTypeNamesFromAnnotationValue( utils.getAnnotationValue(modelSpecElement, Implements.class, "interfaceClasses")); if (!AptUtils.isEmpty(typeNames)) { interfaces.addAll(typeNames); .getAnnotationValue(modelSpecElement, Implements.class, "interfaceDefinitions"); List<AnnotationMirror> interfaceSpecs = utils.getValuesFromAnnotationValue(value, AnnotationMirror.class); AnnotationValue interfaceClassValue = utils.getAnnotationValueFromMirror(spec, "interfaceClass"); List<DeclaredTypeName> interfaceClassList = utils.getTypeNamesFromAnnotationValue(interfaceClassValue); if (!AptUtils.isEmpty(interfaceClassList)) { DeclaredTypeName interfaceClass = interfaceClassList.get(0); .getAnnotationValueFromMirror(spec, "interfaceTypeArgs"); List<DeclaredTypeName> typeArgs = utils.getTypeNamesFromAnnotationValue(interfaceTypeArgsValue); if (AptUtils.isEmpty(typeArgs)) { List<String> typeArgNames = utils.getValuesFromAnnotationValue( utils.getAnnotationValueFromMirror(spec, "interfaceTypeArgNames"), String.class); for (String typeArgName : typeArgNames) { typeArgs.add(new DeclaredTypeName(typeArgName));
private Set<String> parseOptions() { Set<String> result = new HashSet<>(); String optionsString = envOptions.get(OPTIONS_KEY); if (!AptUtils.isEmpty(optionsString)) { String[] allOptions = optionsString.split(SEPARATOR); Collections.addAll(result, allOptions); } return result; }
private void accumulatePlugins(List<Plugin> accumulator, List<Class<? extends Plugin>> pluginList, ModelSpec<?> modelSpec) { for (Class<? extends Plugin> plugin : pluginList) { try { accumulator.add(plugin.getConstructor(ModelSpec.class, PluginEnvironment.class) .newInstance(modelSpec, this)); } catch (Exception e) { utils.getMessager().printMessage(Diagnostic.Kind.WARNING, "Unable to instantiate plugin " + plugin + ", reason: " + e); } } } }
private void processVariableElements() { for (Element e : modelSpecElement.getEnclosedElements()) { if (e instanceof VariableElement && e.getAnnotation(Ignore.class) == null) { TypeName typeName = utils.getTypeNameFromTypeMirror(e.asType()); if (!(typeName instanceof DeclaredTypeName)) { utils.getMessager().printMessage(Diagnostic.Kind.WARNING, "Element type " + typeName + " is not a concrete type, will be ignored", e); } else if (!pluginBundle.processVariableElement((VariableElement) e, (DeclaredTypeName) typeName)) { // Deprecated things are generally ignored by plugins, so don't warn about them // private static final fields are generally internal model spec constants, so don't warn about them if (e.getAnnotation(Deprecated.class) == null && !e.getModifiers().containsAll(TypeConstants.PRIVATE_STATIC_FINAL)) { utils.getMessager().printMessage(Diagnostic.Kind.WARNING, "No plugin found to handle field", e); } } } } }
@Override public void beforeEmitClassDeclaration(JavaFileWriter writer) throws IOException { String generatedJavadoc = " This class was generated from the model spec at " + "{@link " + modelSpec.getModelSpecName() + "}"; String elementJavadoc = utils.getElements().getDocComment(modelSpec.getModelSpecElement()); if (!AptUtils.isEmpty(elementJavadoc)) { generatedJavadoc = (generatedJavadoc + "\n <br/>\n" + elementJavadoc); } writer.writeJavadoc(generatedJavadoc); writer.writeComment("Generated code -- do not modify!"); }
private void emitModelMethod(JavaFileWriter writer, ExecutableElement e, Modifier... modifiers) throws IOException { MethodDeclarationParameters params = utils.methodDeclarationParamsFromExecutableElement(e, modifiers); ModelMethod methodAnnotation = e.getAnnotation(ModelMethod.class); List<Object> arguments = new ArrayList<>(); if (methodAnnotation != null) { String name = methodAnnotation.name(); if (!AptUtils.isEmpty(name)) { params.setMethodName(name); } params.getArgumentTypes().remove(0); params.getArgumentNames().remove(0); arguments.add(0, "this"); } arguments.addAll(params.getArgumentNames()); Expression methodCall = Expressions.staticMethod(modelSpec.getModelSpecName(), e.getSimpleName().toString(), arguments); if (!CoreTypes.VOID.equals(params.getReturnType())) { methodCall = methodCall.returnExpr(); } JavadocPlugin.writeJavadocFromElement(pluginEnv, writer, e); writer.beginMethodDefinition(params) .writeStatement(methodCall) .finishMethodDefinition(); }
private void writeConstantField(JavaFileWriter writer, DeclaredTypeName containingClassName, VariableElement constant) throws IOException { JavadocPlugin.writeJavadocFromElement(pluginEnv, writer, constant); writer.writeFieldDeclaration( utils.getTypeNameFromTypeMirror(constant.asType()), constant.getSimpleName().toString(), Expressions.staticReference(containingClassName, constant.getSimpleName().toString()), TypeConstants.PUBLIC_STATIC_FINAL); } }
@SuppressWarnings("unchecked") private void logErrors(Element element) { AnnotationValue errorsArrayValue = utils.getAnnotationValue(element, ModelGenErrors.class, "value"); List<? extends AnnotationValue> errorsList = (List<? extends AnnotationValue>) errorsArrayValue.getValue(); for (AnnotationValue error : errorsList) { logSingleError(error); } }
/** * Helper method that other plugins can use to copy javadocs from an Element */ public static void writeJavadocFromElement(PluginEnvironment pluginEnv, JavaFileWriter writer, Element element) throws IOException { if (!pluginEnv.hasSquidbOption(PluginEnvironment.OPTIONS_DISABLE_JAVADOC_COPYING)) { writer.writeJavadoc(pluginEnv.getUtils().getElements().getDocComment(element)); } } }
@Override public void addRequiredImports(Set<DeclaredTypeName> imports) { utils.accumulateImportsFromTypeNames(imports, interfaces); }
private void parseInterfaces() { TypeElement modelSpecElement = modelSpec.getModelSpecElement(); if (modelSpecElement.getAnnotation(Implements.class) != null) { List<DeclaredTypeName> typeNames = utils.getTypeNamesFromAnnotationValue( utils.getAnnotationValue(modelSpecElement, Implements.class, "interfaceClasses")); if (!AptUtils.isEmpty(typeNames)) { interfaces.addAll(typeNames); .getAnnotationValue(modelSpecElement, Implements.class, "interfaceDefinitions"); List<AnnotationMirror> interfaceSpecs = utils.getValuesFromAnnotationValue(value, AnnotationMirror.class); AnnotationValue interfaceClassValue = utils.getAnnotationValueFromMirror(spec, "interfaceClass"); List<DeclaredTypeName> interfaceClassList = utils.getTypeNamesFromAnnotationValue(interfaceClassValue); if (!AptUtils.isEmpty(interfaceClassList)) { DeclaredTypeName interfaceClass = interfaceClassList.get(0); .getAnnotationValueFromMirror(spec, "interfaceTypeArgs"); List<DeclaredTypeName> typeArgs = utils.getTypeNamesFromAnnotationValue(interfaceTypeArgsValue); if (AptUtils.isEmpty(typeArgs)) { List<String> typeArgNames = utils.getValuesFromAnnotationValue( utils.getAnnotationValueFromMirror(spec, "interfaceTypeArgNames"), String.class); for (String typeArgName : typeArgNames) { typeArgs.add(new DeclaredTypeName(typeArgName));
String trimmedIdentifier = identifier == null ? null : identifier.trim(); if (trimmedIdentifier != null && !trimmedIdentifier.equals(identifier)) { aptUtils.getMessager().printMessage(Diagnostic.Kind.WARNING, type + " name '" + identifier + "' has " + "excess whitespace that should be trimmed", element); if (AptUtils.isEmpty(identifier)) { modelSpec.logError(type + " name cannot be null or empty", element); return false; return false; } else { aptUtils.getMessager().printMessage(Diagnostic.Kind.WARNING, type + " name '" + identifier + "' is a " + "SQLite keyword. It may be allowed as an identifier but it is recommended you choose a " + "non-keyword name instead", element); aptUtils.getMessager().printMessage(Diagnostic.Kind.WARNING, type + " name '" + identifier + "' contains " + "characters that may not be fully supported by SquiDB or SQLite in some cases. It is strongly " + "recommended your identifiers only contain alphanumeric characters, underscores ('_'), and "
private void initializePluginsFromEnvironment() { String pluginsString = envOptions.get(PLUGINS_KEY); if (!AptUtils.isEmpty(pluginsString)) { String[] allPlugins = pluginsString.split(SEPARATOR); for (String plugin : allPlugins) { processPlugin(plugin); } } }
@Override protected PropertyGenerator getPropertyGenerator(VariableElement field, DeclaredTypeName fieldType) { // We know it's an EnumProperty, so extract the type arg List<? extends TypeName> typeArgs = fieldType.getTypeArgs(); if (typeArgs != null && typeArgs.size() == 1 && typeArgs.get(0) instanceof DeclaredTypeName) { return new EnumPropertyGenerator(modelSpec, field, utils, (DeclaredTypeName) typeArgs.get(0)); } utils.getMessager().printMessage(Kind.WARNING, "EnumProperty must use a declared type argument; it cannot be raw or use a generic type argument", field); return null; } }
@Override public void afterProcessVariableElements() { // Look for additional constants in @Constant annotated inner classes List<? extends Element> elements = modelSpec.getModelSpecElement().getEnclosedElements(); for (Element element : elements) { if (element instanceof TypeElement && element.getAnnotation(Constants.class) != null) { if (!element.getModifiers().containsAll(Arrays.asList(Modifier.PUBLIC, Modifier.STATIC))) { utils.getMessager().printMessage(Diagnostic.Kind.WARNING, "@Constants annotated class is not " + "public static, will be ignored", element); continue; } TypeElement constantClass = (TypeElement) element; List<VariableElement> constantList = new ArrayList<>(); innerClassConstants.put(constantClass.getSimpleName().toString(), constantList); for (Element e : constantClass.getEnclosedElements()) { if (e instanceof VariableElement && e.getAnnotation(Ignore.class) == null) { TypeName typeName = utils.getTypeNameFromTypeMirror(e.asType()); if (!(typeName instanceof DeclaredTypeName)) { utils.getMessager().printMessage(Diagnostic.Kind.WARNING, "Element type " + typeName + " is not a concrete type, will be ignored", e); } else { processVariableElement((VariableElement) e, constantList); } } } } } }
@Override public void beforeEmitClassDeclaration(JavaFileWriter writer) throws IOException { String generatedJavadoc = " This class was generated from the model spec at " + "{@link " + modelSpec.getModelSpecName() + "}"; String elementJavadoc = utils.getElements().getDocComment(modelSpec.getModelSpecElement()); if (!AptUtils.isEmpty(elementJavadoc)) { generatedJavadoc = (generatedJavadoc + "\n <br/>\n" + elementJavadoc); } writer.writeJavadoc(generatedJavadoc); writer.writeComment("Generated code -- do not modify!"); }