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 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); }
@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; } }
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 boolean process(Set<? extends TypeElement> annotations, RoundEnvironment env) { for (TypeElement annotationType : annotations) { if (supportedAnnotationTypes.contains(annotationType.getQualifiedName().toString())) { for (Element element : env.getElementsAnnotatedWith(annotationType)) { if (element.getKind() == ElementKind.CLASS) { TypeElement typeElement = (TypeElement) element; try { getFileWriter(typeElement).writeJava(); } catch (IOException e) { utils.getMessager().printMessage(Kind.ERROR, "Unable to write model file", element); } } else { utils.getMessager() .printMessage(Kind.ERROR, "Unexpected element type " + element.getKind(), element); } } } else { utils.getMessager().printMessage(Kind.WARNING, "Skipping unsupported annotation received by processor: " + annotationType); } } return true; }
String[] nameAndPriority = pluginName.split(":"); if (nameAndPriority.length != 2) { utils.getMessager().printMessage(Diagnostic.Kind.WARNING, "Error parsing plugin and priority " + pluginName + ", plugin will be ignored"); } else { priority = PluginPriority.valueOf(priorityString.toUpperCase()); } catch (IllegalArgumentException e) { utils.getMessager().printMessage(Diagnostic.Kind.WARNING, "Unrecognized priority string " + priorityString + " for plugin " + pluginName + ", defaulting to 'normal'. Should be " + "one of '" + PluginPriority.HIGH + "', " + "'" + PluginPriority.NORMAL + "', or '" + addPlugin((Class<? extends Plugin>) pluginClass, priority); } else { utils.getMessager().printMessage(Diagnostic.Kind.WARNING, "Plugin " + pluginName + " is not a subclass of Plugin"); utils.getMessager().printMessage(Diagnostic.Kind.WARNING, "Unable to instantiate plugin " + pluginName + ", reason: " + e);
@Override protected PropertyGenerator getPropertyGenerator(VariableElement field, DeclaredTypeName fieldType) { // We know it's a JSONProperty, so extract the type arg List<? extends TypeName> typeArgs = fieldType.getTypeArgs(); if (typeArgs != null && typeArgs.size() == 1 && typeArgs.get(0) instanceof DeclaredTypeName) { return new JSONPropertyGenerator(modelSpec, field, (DeclaredTypeName) typeArgs.get(0), utils); } utils.getMessager().printMessage(Diagnostic.Kind.WARNING, "JSONProperty must use a declared type argument; it cannot be raw or use a generic type argument", field); return new JSONPropertyGenerator(modelSpec, field, fieldType, utils); } }
@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 boolean processVariableElement(VariableElement field, DeclaredTypeName fieldType) { if (field.getAnnotation(Deprecated.class) != null) { return false; } if (field.getAnnotation(ColumnSpec.class) != null) { utils.getMessager().printMessage(Diagnostic.Kind.WARNING, "ColumnSpec is ignored outside of table models", field); } return super.processVariableElement(field, fieldType); }
utils.getMessager().printMessage(Diagnostic.Kind.WARNING, "Model spec objects should never be instantiated, so non-static methods are meaningless. " + "Did you mean to make this a static method?", e); staticModelMethods.add(e); } else if (!modifiers.contains(Modifier.PRIVATE)) { utils.getMessager().printMessage(Diagnostic.Kind.WARNING, "This method will not be added to the model definition. " + "Did you mean to annotate this method with @ModelMethod?", e);
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); }
toReturn.append(" DEFAULT ").append(columnDefaultValue); } else { utils.getMessager().printMessage(Kind.WARNING, "Duplicate default value definitions", field); utils.getMessager().printMessage(Kind.WARNING, "Duplicate primary key definition in column constraints." + " Use the @PrimaryKey annotation instead of declaring the constraint in ColumnSpec.");
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); 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 "
/** * Log an error to this model spec. * * This is generally intended for logging things like validation errors. Such errors do not stop the code * generation process (as logging an error using Messager and Kind.ERROR would), but instead generate * temporary code in the model class that will be picked up by a subsequent annotation processor and logged as * errors in a later round of annotation processing. This mechanism is designed to work around the fact that * logging Kind.ERROR messages during early rounds of annotation processing may suppress those errors, because * failing early during annotation processing can lead to a large number of "symbol not found" errors, which in * turn mask other validation errors. * <p> * If {@link PluginEnvironment#OPTIONS_USE_STANDARD_ERROR_LOGGING} is passed as an option to the code generator, * this SquiDB workaround is disabled and this method will log an error using a standard printMessage() call with * Kind.ERROR. * * @param message the error message to be logged * @param element the specific inner element in the model spec that is causing this error (e.g. a field or method), * or null for a general error */ public void logError(String message, Element element) { if (pluginEnvironment.hasSquidbOption(PluginEnvironment.OPTIONS_USE_STANDARD_ERROR_LOGGING)) { utils.getMessager().printMessage(Diagnostic.Kind.ERROR, message, element); } else { boolean isRootElement = element == null || element.equals(getModelSpecElement()); loggedErrors.add(new ErrorInfo(getModelSpecName(), isRootElement ? "" : element.getSimpleName().toString(), message)); } }
DEFAULT_ROWID_PROPERTY_NAME, utils); } else { utils.getMessager().printMessage(Kind.WARNING, "Model class " + modelSpec.getGeneratedClassName() + " is currently generating an integer primary key ID property to act as an alias to the table's " + "rowid. Future versions of SquiDB will remove this default property for the sake of better "
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 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); }
@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 boolean processVariableElement(VariableElement field, DeclaredTypeName fieldType) { if (field.getAnnotation(Deprecated.class) != null) { return false; } if (field.getAnnotation(ColumnSpec.class) != null) { utils.getMessager().printMessage(Diagnostic.Kind.WARNING, "ColumnSpec is ignored outside of table models", field); } return super.processVariableElement(field, fieldType); }
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); }