private MethodSpec generateRegisterComponents(Set<String> libraryGlideModuleClassNames, Set<String> excludedGlideModuleClassNames) { MethodSpec.Builder registerComponents = MethodSpec.methodBuilder("registerComponents") .addModifiers(Modifier.PUBLIC) .addAnnotation(Override.class) .addParameter(ClassName.get("android.content", "Context"), "context") .addParameter(ClassName.get("com.bumptech.glide", "Registry"), "registry"); for (String glideModule : libraryGlideModuleClassNames) { if (excludedGlideModuleClassNames.contains(glideModule)) { continue; } ClassName moduleClassName = ClassName.bestGuess(glideModule); registerComponents.addStatement( "new $T().registerComponents(context, registry)", moduleClassName); } // Order matters here. The AppGlideModule must be called last. registerComponents.addStatement("appGlideModule.registerComponents(context, registry)"); return registerComponents.build(); }
private MethodSpec generateConstructor(ClassName appGlideModule, Set<String> libraryGlideModuleClassNames, Set<String> excludedGlideModuleClassNames) { MethodSpec.Builder constructorBuilder = MethodSpec.constructorBuilder(); constructorBuilder.addStatement("appGlideModule = new $T()", appGlideModule); ClassName androidLogName = ClassName.get("android.util", "Log"); // Add some log lines to indicate to developers which modules where discovered. constructorBuilder.beginControlFlow("if ($T.isLoggable($S, $T.DEBUG))", androidLogName, GLIDE_LOG_TAG, androidLogName); constructorBuilder.addStatement("$T.d($S, $S)", androidLogName, GLIDE_LOG_TAG, "Discovered AppGlideModule from annotation: " + appGlideModule); // Excluded GlideModule classes from the manifest are logged in Glide's singleton. for (String glideModule : libraryGlideModuleClassNames) { ClassName moduleClassName = ClassName.bestGuess(glideModule); if (excludedGlideModuleClassNames.contains(glideModule)) { constructorBuilder.addStatement("$T.d($S, $S)", androidLogName, GLIDE_LOG_TAG, "AppGlideModule excludes LibraryGlideModule from annotation: " + moduleClassName); } else { constructorBuilder.addStatement("$T.d($S, $S)", androidLogName, GLIDE_LOG_TAG, "Discovered LibraryGlideModule from annotation: " + moduleClassName); } } constructorBuilder.endControlFlow(); return constructorBuilder.build(); }
private MethodSpec generateRegisterComponents(Set<String> libraryGlideModuleClassNames, Set<String> excludedGlideModuleClassNames) { MethodSpec.Builder registerComponents = MethodSpec.methodBuilder("registerComponents") .addModifiers(Modifier.PUBLIC) .addAnnotation(Override.class) .addParameter(ClassName.get("android.content", "Context"), "context") .addParameter(ClassName.get("com.bumptech.glide", "Glide"), "glide") .addParameter(ClassName.get("com.bumptech.glide", "Registry"), "registry"); for (String glideModule : libraryGlideModuleClassNames) { if (excludedGlideModuleClassNames.contains(glideModule)) { continue; } ClassName moduleClassName = ClassName.bestGuess(glideModule); registerComponents.addStatement( "new $T().registerComponents(context, glide, registry)", moduleClassName); } // Order matters here. The AppGlideModule must be called last. registerComponents.addStatement("appGlideModule.registerComponents(context, glide, registry)"); return registerComponents.build(); }
@Override public TypeSpec poetSpec() { Builder enumBuilder = createEnumBuilder(className) .addField(String.class, VALUE, Modifier.PRIVATE, Modifier.FINAL) .addMethod(toStringBuilder().addStatement("return $T.valueOf($N)", String.class, VALUE).build()) .addMethod(fromValueSpec()) .addMethod(knownValuesSpec()) .addMethod(createConstructor()); addDeprecated(enumBuilder::addAnnotation, shape); addJavadoc(enumBuilder::addJavadoc, shape); shape.getEnums().forEach( e -> enumBuilder.addEnumConstant(e.getName(), TypeSpec.anonymousClassBuilder("$S", e.getValue()).build()) ); enumBuilder.addEnumConstant(UNKNOWN_TO_SDK_VERSION, TypeSpec.anonymousClassBuilder("null").build()); return enumBuilder.build(); }
/** * genera i metodi di test per clazz * * @param classTestBuilder * @param clazz * @param prop * @param mongo */ private void addClassMethodsToBuilder(Builder classTestBuilder, Class<?> clazz) { int count = 0; String appName = PropertiesUtils.getRequiredProperty(prop, PropertiesUtils.APP_NAME); List<Document> methodInfo; for (Method method : clazz.getDeclaredMethods()) { Document methodInputs = null, methodOutput = null; if (java.lang.reflect.Modifier.isPublic(method.getModifiers())) { LOG.info("app: " + appName + " - method: " + method); count++; methodInfo = mongo.find(appName, method.toString()); for (Document doc : methodInfo) { LOG.debug("document: " + doc); if (doc.containsKey("argsBefore")) { methodInputs = doc; } else { methodOutput = doc; } } MethodSpec methodSpec = getMethodSpec(count, method, clazz, methodInputs, methodOutput); classTestBuilder.addMethod(methodSpec); } } classTestBuilder.addMethod(getDeserializeMethod(clazz)); }
/** * genera il metodo di test per method di clazz * * @param count * @param method * @param clazz * @param infoFromMongoDb * @param methodOutput * @return */ private MethodSpec getMethodSpec(int count, Method method, Class<?> clazz, Document methodInputs, Document methodOutput) { String result = getAssignmentOfMethodResult(method); String expected = getExpectedResultAsBooleanAssert(method, methodOutput); MethodSpec.Builder methodBuilder = MethodSpec.methodBuilder(method.getName() + count + TEST); /* * for non spring test */ String invokerName = getInvokerName(method, clazz, methodInputs, methodBuilder); String params = getParams(method, methodBuilder, methodInputs); AnnotationSpec.Builder annSpecBuilder = AnnotationSpec.builder(Test.class); addExpectedExceptionIfAny(methodInputs, annSpecBuilder); AnnotationSpec annTestSpec = annSpecBuilder.build(); methodBuilder.addAnnotation(annTestSpec) .addStatement(result + invokerName + ".$N(" + params + ")", method.getName()) .addModifiers(Modifier.PUBLIC); methodBuilder.addStatement("$L.assertTrue(" + expected + ")", Assert.class.getName()); methodBuilder.addJavadoc("\n"); return methodBuilder.build(); }
/** * inizializza l'object under test * * @param clazz * @param methodBuilder * @param method * @param methodInputs */ private void newInstance(Class<?> clazz, MethodSpec.Builder methodBuilder, Method method, Document methodInputs) { // TODO here we need to evaluate combination between constructors and // setter to see if it is possible to instantiate the object properly, // otherwise direct deserialization must be done // methodBuilder.addStatement(new // StringBuilder(clazz.getSimpleName()).append(" ") // .append(getInstanceVariableName(clazz)).append(" = new // ").append(clazz.getSimpleName()).append("(") // .append(getValueWithApexIfRequired(methodReturnType, // methodReturnValue)).append(")").toString()); Class<?> methodReturnType = method.getReturnType(); String returnValue = methodInputs.getString("returnValue"); // methodBuilder.addStatement("ObjectDeserializer objDes = new ObjectDeserializer();"); methodBuilder.addStatement("String json = \"" + methodInputs.toJson() + "\""); methodBuilder.addStatement(clazz.getSimpleName() + " " + getInstanceVariableName(clazz) + " = getInstance(json, " + clazz.getSimpleName() + ".class)"); }
/** * genera l'inizializzazione dei parametri e ritorna la lista dei nomi * * @param method * @param methodBuilder * @param methodInputs * @return */ private String getParams(Method method, MethodSpec.Builder methodBuilder, Document methodInputs) { String params = ""; String[] methodArgsValues = methodInputs.getString("argsBefore").split(","); int count = 0; for (Class<?> parameterClass : method.getParameterTypes()) { String parameterName = getInstanceVariableName(parameterClass) + count; params += "," + parameterName; methodBuilder .addStatement(parameterClass.getName() + " " + parameterName + " = " + methodArgsValues[count]); count++; } if (params.startsWith(",")) { params = params.substring(1); } return params; }
/** * genera classe di test per clazz * * @param clazz * @param prop * @param mongo * @return */ @Override public TypeSpec getTypeSpec(Class<?> clazz) { Builder classTestBuilder = TypeSpec.classBuilder(clazz.getSimpleName() + TEST); ClassName superClass = ClassName.get( PropertiesUtils.getRequiredProperty(prop, PropertiesUtils.TEST_BASE_PACKAGE), PropertiesUtils.getRequiredProperty(prop, PropertiesUtils.TEST_BASE_CLASS)); classTestBuilder.superclass(superClass); classTestBuilder.addJavadoc("@author \n"); classTestBuilder.addModifiers(Modifier.PUBLIC); AnnotationSpec.Builder annSpecBuilder = AnnotationSpec.builder(Generated.class); annSpecBuilder.addMember("value", "\"it.fratta.jerkoff.Generator\""); annSpecBuilder.addMember("date", "\"" + Calendar.getInstance().getTime().toString() + "\""); AnnotationSpec annGenSpec = annSpecBuilder.build(); classTestBuilder.addAnnotation(annGenSpec); /* * for spring test */ // FieldSpec.Builder spec = FieldSpec.builder(clazz, // getNewInstanceOfNoParameters(clazz), Modifier.PRIVATE); // spec.addAnnotation(Autowired.class); // classTestBuilder.addField(spec.build()); addClassMethodsToBuilder(classTestBuilder, clazz); return classTestBuilder.build(); }
/** * Generate and save the Java file for the typeElement passed to the constructor * @param directiveTypeElement The {@link VueDirective} class to * generate {@link VueDirectiveOptions} from */ public void generate(TypeElement directiveTypeElement) { ClassName optionsClassName = GenerationNameUtil.directiveOptionsName(directiveTypeElement); Builder componentClassBuilder = TypeSpec .classBuilder(optionsClassName) .addModifiers(Modifier.PUBLIC, Modifier.FINAL) .superclass(VueDirectiveOptions.class) .addAnnotation(JsType.class) .addJavadoc("VueComponent Directive Options for directive {@link $S}", directiveTypeElement.getQualifiedName().toString()); // Initialize constructor MethodSpec.Builder constructorBuilder = MethodSpec.constructorBuilder().addModifiers(Modifier.PUBLIC); // Add the Java Component Instance initialization constructorBuilder.addStatement("this.$L = new $T()", "vuegwt$javaDirectiveInstance", TypeName.get(directiveTypeElement.asType())); // Call the method to copy hooks functions constructorBuilder.addStatement("this.copyHooks()"); // Finish building the constructor componentClassBuilder.addMethod(constructorBuilder.build()); // Build the DirectiveOptions class GenerationUtil.toJavaFile(filer, componentClassBuilder, optionsClassName, directiveTypeElement); }
/** * Process data fields from the {@link VueComponent} Class. * @param component {@link VueComponent} to process * @param optionsBuilder A {@link MethodSpec.Builder} for the method that creates the * {@link VueComponentOptions} */ private void processData(TypeElement component, MethodSpec.Builder optionsBuilder) { Component annotation = component.getAnnotation(Component.class); List<String> fieldsName = ElementFilter .fieldsIn(component.getEnclosedElements()) .stream() .filter(ComponentGenerationUtil::isFieldVisibleInJS) .filter(field -> field.getAnnotation(Prop.class) == null) .map(field -> field.getSimpleName().toString()) .collect(Collectors.toList()); if (fieldsName.isEmpty()) return; // Declare data fields String fieldNamesParameters = fieldsName .stream() .map(fieldName -> "\"" + fieldName + "\"") .collect(Collectors.joining(", ")); optionsBuilder.addStatement("options.initData($L, $L)", annotation.useFactory(), fieldNamesParameters); }
/** * Process Vue Props from the {@link VueComponent} Class. * @param component {@link VueComponent} to process * @param optionsBuilder A {@link MethodSpec.Builder} for the method that creates the * {@link VueComponentOptions} */ private void processProps(TypeElement component, MethodSpec.Builder optionsBuilder) { ElementFilter .fieldsIn(component.getEnclosedElements()) .stream() .filter(field -> hasAnnotation(field, Prop.class)) .forEach(field -> { String fieldName = field.getSimpleName().toString(); Prop prop = field.getAnnotation(Prop.class); if (!isFieldVisibleInJS(field)) { printError("The field \"" + fieldName + "\" annotated with @Prop must also be annotated with @JsProperty.", component); } optionsBuilder.addStatement("options.addJavaProp($S, $L, $S)", fieldName, prop.required(), prop.checkType() ? getNativeNameForJavaType(field.asType()) : null); }); }
/** * Process computed properties from the Component Class. * @param component {@link VueComponent} to process * @param optionsBuilder A {@link MethodSpec.Builder} for the method that creates the * {@link VueComponentOptions} * @param componentJsTypeBuilder Builder for the JsType class */ private void processComputed(TypeElement component, MethodSpec.Builder optionsBuilder, Builder componentJsTypeBuilder) { getMethodsWithAnnotation(component, Computed.class).forEach(method -> { String methodName = method.getSimpleName().toString(); ComputedKind kind = ComputedKind.GETTER; if ("void".equals(method.getReturnType().toString())) kind = ComputedKind.SETTER; String propertyName = GenerationUtil.getComputedPropertyName(method); optionsBuilder.addStatement("options.addJavaComputed($S, $S, $T.$L)", methodName, propertyName, ComputedKind.class, kind); addProxyJsTypeMethodIfNecessary(componentJsTypeBuilder, method); }); addFieldsForComputedMethod(component, componentJsTypeBuilder, new HashSet<>()); }
/** * Process template methods for our {@link VueComponent} class. * @param component {@link VueComponent} to process * @param optionsBuilder A {@link MethodSpec.Builder} for the method that creates the * {@link VueComponentOptions} * @param componentJsTypeBuilder Builder for the JsType class * @param hookMethodsFromInterfaces Hook methods from the interface the {@link VueComponent} * implements */ private void processTemplateMethods(TypeElement component, MethodSpec.Builder optionsBuilder, Builder componentJsTypeBuilder, Set<ExecutableElement> hookMethodsFromInterfaces) { List<ExecutableElement> templateMethods = ElementFilter .methodsIn(component.getEnclosedElements()) .stream() .filter(ComponentGenerationUtil::isMethodVisibleInTemplate) .filter(method -> !isHookMethod(component, method, hookMethodsFromInterfaces)) .collect(Collectors.toList()); templateMethods.forEach(method -> addProxyJsTypeMethodIfNecessary(componentJsTypeBuilder, method)); // Declare methods in the component String methodNamesParameters = templateMethods .stream() .map(method -> "\"" + method.getSimpleName() + "\"") .collect(Collectors.joining(", ")); optionsBuilder.addStatement("options.addMethods($L)", methodNamesParameters); }
/** * Process prop validators from the Component Class. * @param component {@link VueComponent} to process * @param optionsBuilder A {@link MethodSpec.Builder} for the method that creates the * {@link VueComponentOptions} */ private void processPropValidators(TypeElement component, MethodSpec.Builder optionsBuilder, Builder componentJsTypeBuilder) { getMethodsWithAnnotation(component, PropValidator.class).forEach(method -> { PropValidator propValidator = method.getAnnotation(PropValidator.class); if (!TypeName.get(method.getReturnType()).equals(TypeName.BOOLEAN)) { printError("Method " + method.getSimpleName() + " annotated with PropValidator must return a boolean.", component); } String propertyName = propValidator.value(); optionsBuilder.addStatement("options.addJavaPropValidator($S, $S)", method.getSimpleName().toString(), propertyName); addProxyJsTypeMethodIfNecessary(componentJsTypeBuilder, method); }); }
/** * Process the render function from the Component Class if it has one. * @param component {@link VueComponent} to process * @param optionsBuilder A {@link MethodSpec.Builder} for the method that creates the * {@link VueComponentOptions} * @param componentJsTypeBuilder Builder for the JsType class */ private void processRenderFunction(TypeElement component, MethodSpec.Builder optionsBuilder, Builder componentJsTypeBuilder) { if (!hasInterface(processingEnv, component.asType(), HasRender.class)) return; componentJsTypeBuilder.addMethod(MethodSpec .methodBuilder("vuegwt$render") .addModifiers(Modifier.PUBLIC) .returns(VNode.class) .addParameter(CreateElementFunction.class, "createElementFunction") .addStatement("return super.render(new $T(createElementFunction))", VNodeBuilder.class) .build()); // Register the render method optionsBuilder.addStatement("options.addHookMethod($S, $S)", "render", "vuegwt$render"); }
private void callMethodsWithDependencies( ComponentInjectedDependenciesBuilder dependenciesBuilder, MethodSpec.Builder createdMethodBuilder) { for (Entry<String, List<String>> methodNameParametersEntry : dependenciesBuilder .getInjectedParametersByMethod() .entrySet()) { String methodName = methodNameParametersEntry.getKey(); List<String> callParameters = methodNameParametersEntry .getValue() .stream() .map(parameterName -> "dependencies." + parameterName) .collect(Collectors.toList()); createdMethodBuilder.addStatement("$L($L)", methodName, String.join(", ", callParameters)); } }
/** * Add a call to emit an event at the end of the function * @param originalMethod Method we are emitting an event for * @param proxyMethodBuilder Method we are building * @param methodCallParameters Chained parameters name of the method */ private void addEmitEventCall(ExecutableElement originalMethod, MethodSpec.Builder proxyMethodBuilder, String methodCallParameters) { String methodName = "$emit"; if (methodCallParameters != null && !"".equals(methodCallParameters)) { proxyMethodBuilder.addStatement("this.$L($S, $L)", methodName, methodToEventName(originalMethod), methodCallParameters); } else { proxyMethodBuilder.addStatement("this.$L($S)", methodName, methodToEventName(originalMethod)); } }
/** * Process the {@link CustomizeOptions} from the {@link Component} annotation. An instance * of this class should be created with our factory and used to customize our * {@link VueComponentOptions} before passing them to Vue. * @param customizeOptions The {@link CustomizeOptions} we are generating for * @param initBuilder The builder for our {@link VueFactory} init method * @param staticInitParameters The list of static parameters to pass when calling the init * method from a static context */ private void processCustomizeOptions(TypeMirror customizeOptions, MethodSpec.Builder initBuilder, List<CodeBlock> staticInitParameters) { ClassName customizeOptionsClassName = ((ClassName) ClassName.get(customizeOptions)); char c[] = customizeOptionsClassName.simpleName().toCharArray(); c[0] = Character.toLowerCase(c[0]); String parameterName = new String(c); initBuilder.addParameter(customizeOptionsClassName, parameterName); staticInitParameters.add(CodeBlock.of("new $T()", customizeOptionsClassName)); initBuilder.addStatement("$L.$L($L)", parameterName, "customizeOptions", "componentOptions"); }
/** * Generate our {@link VueFactory} class. * @param component The {@link VueComponent} class to generate {@link VueComponentOptions} from */ public void generate(TypeElement component) { ClassName vueFactoryClassName = componentFactoryName(component); Builder vueFactoryBuilder = createFactoryBuilderClass(component, vueFactoryClassName); createProperties(vueFactoryClassName, vueFactoryBuilder); List<CodeBlock> staticInitParameters = createInitMethod(component, vueFactoryBuilder); createStaticGetMethod(vueFactoryClassName, vueFactoryBuilder, staticInitParameters); vueFactoryBuilder.addMethod(MethodSpec .constructorBuilder() .addModifiers(Modifier.PUBLIC) .addAnnotation(Inject.class) .build()); // Build the ComponentOptions class GenerationUtil.toJavaFile(filer, vueFactoryBuilder, vueFactoryClassName, component); }
/** * Add an injected variable to our component * @param element The {@link VariableElement} that was injected * @param fieldName The name of the field */ private void addInjectedVariable(VariableElement element, String fieldName) { TypeName typeName = resolveVariableTypeName(element, messager); // Create field FieldSpec.Builder fieldBuilder = FieldSpec.builder(typeName, fieldName, Modifier.PUBLIC); // Copy field annotations element .getAnnotationMirrors() .stream() .map(AnnotationSpec::get) .forEach(fieldBuilder::addAnnotation); // If the variable element is a method parameter, it might not have the Inject annotation if (!hasInjectAnnotation(element)) fieldBuilder.addAnnotation(Inject.class); // And add field componentInjectedDependenciesBuilder.addField(fieldBuilder.build()); }
public static void toJavaFile(Filer filer, Builder classBuilder, ClassName className, TypeElement... originatingElement) { try { JavaFile javaFile = JavaFile.builder(className.packageName(), classBuilder.build()).build(); JavaFileObject javaFileObject = filer.createSourceFile(className.reflectionName(), originatingElement); Writer writer = javaFileObject.openWriter(); javaFile.writeTo(writer); writer.close(); } catch (IOException e) { e.printStackTrace(); } }
/** * Create the template resource implementation based on the result of the template parser. * @param componentTypeName The name of our Template class * @param templateParserResult The result of the HTML template parsed by {@link TemplateParser} * render function * @param templateCompilerResourceFolder Folder holding res * @return The built Java class representing our template */ public TypeSpec buildTemplateImpl(ClassName componentTypeName, TemplateParserResult templateParserResult, Folder templateCompilerResourceFolder) { Builder templateImplBuilder = TypeSpec .classBuilder(componentTemplateImplName(componentTypeName)) .addModifiers(Modifier.PUBLIC) .superclass(componentJsTypeName(componentTypeName)) .addSuperinterface(componentTemplateName(componentTypeName)); // Compile the resulting HTML template String compileTemplateString(templateImplBuilder, templateParserResult.getProcessedTemplate(), templateCompilerResourceFolder); // Process the java expressions from the template processTemplateExpressions(templateImplBuilder, templateParserResult); return templateImplBuilder.build(); }
/** * Compile the HTML template and transform it to a JS render function. * @param templateBuilder The template builder * @param templateString The HTML template string to compile */ private void compileTemplateString(Builder templateBuilder, String templateString, Folder templateCompilerResourceFolder) { VueTemplateCompilerResult result; try { VueTemplateCompiler vueTemplateCompiler = new VueTemplateCompiler(templateCompilerResourceFolder); result = vueTemplateCompiler.compile(templateString); } catch (VueTemplateCompilerException e) { e.printStackTrace(); throw new RuntimeException(); } generateGetRenderFunction(templateBuilder, result); generateGetStaticRenderFunctions(templateBuilder, result); }
private void addParameters(ClassMethod classMethod, Builder javaFile, ClassName self) { for (final ClassMethodParameter classMethodParameter : classMethod.getParameters()) { final TypeName fieldType = TypeName.get(classMethodParameter.getType()); final String fieldName = classMethodParameter.getName(); javaFile // .addField(fieldType, fieldName, PRIVATE) // .addMethod( methodBuilder("with" + ucFirst(fieldName)) // .addModifiers(PUBLIC) // .addParameter( builder(fieldType, fieldName, FINAL) // .build()) // .addStatement("this." + fieldName + " = " + fieldName) // .addStatement("return this") // .returns(self) // .build()); } }
private void generateInheritedProvisionMethods(ClassName packagedInjectorClassName) { ComponentInfo component = getComponentFromPackagedInjectorClassName(packagedInjectorClassName); Preconditions.checkArgument(componentTree.get(component) != null, String .format("No inherited provision methods to generate for %s", packagedInjectorClassName)); TypeSpec.Builder componentSpecBuilder = getInjectorTypeSpecBuilder(packagedInjectorClassName); ClassName containingPackagedInjectorClassName = getInjectorNameOfScope(packagedInjectorClassName, componentTree.get(component).getScope()); for (NewBindingKey key : generatedBindingsForPackagedInjector .get(containingPackagedInjectorClassName)) { String provisionMethodName = getProvisionMethodName(key); componentSpecBuilder.addMethod(MethodSpec.methodBuilder(provisionMethodName) .addModifiers(Modifier.PUBLIC).returns(key.getTypeName()) .addStatement("return $L.$L()", CONTAINING_PACKAGED_INJECTOR_FIELD, provisionMethodName) .build()); Preconditions.checkState( generatedBindingsForPackagedInjector.put(packagedInjectorClassName, key), String.format("Injector %s already provides %s.", packagedInjectorClassName, key)); } }
private void generateInheritedInjectionMethods(ClassName packagedInjectorClassName) { ComponentInfo component = getComponentFromPackagedInjectorClassName(packagedInjectorClassName); if (componentTree.get(component) == null) { return; } TypeSpec.Builder componentSpecBuilder = getInjectorTypeSpecBuilder(packagedInjectorClassName); ClassName containingPackagedInjectorClassName = getInjectorNameOfScope(packagedInjectorClassName, componentTree.get(component).getScope()); for (ClassName injectedClassName : injectedClassNamesForPackagedInjector .get(containingPackagedInjectorClassName)) { componentSpecBuilder.addMethod(MethodSpec.methodBuilder("inject") .addModifiers(Modifier.PUBLIC).addParameter(injectedClassName, "arg") .addStatement("$L.inject(arg)", CONTAINING_PACKAGED_INJECTOR_FIELD).build()); injectedClassNamesForPackagedInjector.put(packagedInjectorClassName, injectedClassName); } }
private void generateUniqueTypeProvisionMethodFromModule(NewBindingKey key, String suffix) { NewDependencyInfo dependencyInfo = Iterables.getOnlyElement(dependencies.get(key)); Preconditions.checkNotNull(dependencyInfo.getProvisionMethodElement()); TypeMirror returnType = dependencyInfo.getProvisionMethodElement().getReturnType(); ClassName injectorClassName = getPackagedInjectorForNewDependencyInfo(key, dependencyInfo); TypeSpec.Builder componentSpecBuilder = getInjectorTypeSpecBuilder(injectorClassName); NewBindingKey returnKey = NewBindingKey.get(returnType, key.getQualifier()); MethodSpec.Builder methodSpecBuilder = MethodSpec.methodBuilder(getProvisionMethodName(returnKey) + suffix); methodSpecBuilder.addModifiers(suffix.isEmpty() ? Modifier.PUBLIC : Modifier.PRIVATE) .returns(TypeName.get(returnType)); methodSpecBuilder.addStatement("$T result", returnType); addNewStatementToMethodSpec(key, dependencyInfo, injectorClassName, methodSpecBuilder, "result"); methodSpecBuilder.addStatement("return result"); componentSpecBuilder.addMethod(methodSpecBuilder.build()); // messager.printMessage(Kind.NOTE, String.format( // "generateUniqueTypeProvisionMethodFromModule: \n key: %s, \n injector: %s, \n method: %s.", // key, injectorClassName, methodSpecBuilder.build())); }
private void addNewStatementToMethodSpec(TypeElement scope, NewDependencyInfo dependencyInfo, ClassName packagedInjectorClassName, MethodSpec.Builder methodSpecBuilder, String newVarName) { Preconditions.checkNotNull(dependencyInfo.getProvisionMethodElement()); StringBuilder builder = new StringBuilder("$L = $N().$N("); if (dependencyInfo.getDependencies().size() > 0) { for (NewBindingKey dependentKey : Utils .getDependenciesFromExecutableElement(dependencyInfo.getProvisionMethodElement())) { generateProvisionMethodAndAppendAsParameter(dependentKey, dependencyInfo.getSourceClassElement(), packagedInjectorClassName, builder); } builder.delete(builder.length() - 2, builder.length()); } builder.append(")"); methodSpecBuilder.addStatement(builder.toString(), newVarName, getGetModuleMethod(scope, dependencyInfo), dependencyInfo.getProvisionMethodElement().getSimpleName()); }
/** * For key like javax.inject.Provider<Foo> and dagger.Lazy<Foo>. Qualifier, if presented, will * also apply to element binding. */ private void generateProvisionMethodForProviderOrLazy(NewBindingKey key, TypeElement referencingClass, String suffix) { // System.out.println(String.format( // "generateProvisionMethodForProviderOrLazy: key %s, referencingClass: %s, suffix : %s.", key, // referencingClass, suffix)); ClassName injectorClassName = getInjectorFor(key, referencingClass); TypeSpec anonymousTypeSpec = createAnonymousBuiltinTypeForUniqueBinding(injectorClassName, key, referencingClass); MethodSpec.Builder methodSpecBuilder = MethodSpec.methodBuilder(getProvisionMethodName(key) + suffix) .addModifiers(suffix.isEmpty() ? Modifier.PUBLIC : Modifier.PRIVATE) .returns(key.getTypeName()).addStatement("return $L", anonymousTypeSpec); Builder componentSpecBuilder = getInjectorTypeSpecBuilder(getInjectorFor(key, referencingClass)); componentSpecBuilder.addMethod(methodSpecBuilder.build()); }
private void generateScopedProvisionMethod( Builder componentSpecBuilder, NewBindingKey key) { MethodSpec.Builder builder = MethodSpec.methodBuilder(getProvisionMethodName(key)) .returns(key.getTypeName()) .addModifiers(Modifier.PUBLIC); builder .addStatement("$T result = $N", key.getTypeName().box(), getFieldName(key)) .beginControlFlow("if (result == null)") .beginControlFlow("synchronized ($L)", TOP_LEVEL_INJECTOR_FIELD) .addStatement("result = $N", getFieldName(key)).beginControlFlow("if (result == null)") .addStatement("result = $L = $L()", getFieldName(key), getProvisionMethodName(key) + UNSCOPED_SUFFIX) .endControlFlow() // if .endControlFlow() // synchronized .endControlFlow() // if .addStatement("return result"); componentSpecBuilder.addMethod(builder.build()); }
private void extendConcludingBuilder(ProcessorContext context, Builder builderTypeBuilder, DeclaredType concludingBuilder) { if (context.utils().isAssignable(concludingBuilder, context.utils().of(ClassArgBuilder.class), true)) { // implement the constructor with class parameters // TODO that bundle part is redundant... consider improving builderTypeBuilder.addMethod(MethodSpec.constructorBuilder() .addParameter(ClassName.get(AndroidTypes.Bundle.asMirror(context)), "bundle") .addCode("super(bundle, $L.class);", targetClassName).build()); } else if (context.utils().isAssignable(concludingBuilder, context.utils().of(ArgConcludingBuilder.class), true)) { // this is probably an user implemented one builderTypeBuilder.addMethod(MethodSpec.constructorBuilder() .addCode("this.bundle = new Bundle();").build()); } else { throw new AssertionError(concludingBuilder + " is not supported, @ArgConfig should" + " not allow this in the first place..."); } }
private static GeneratedClassWithName staticInnerClass(String... classes) { // maybe (String first, String...more) ? if (classes.length == 0) throw new IllegalArgumentException(""); String[] generatedClasses = new String[classes.length]; TypeSpec.Builder lastBuilder = null; for (int i = classes.length - 1; i >= 0; i--) { String clazz = classes[i]; final Builder currentBuilder = TypeSpec.classBuilder(clazz) .addModifiers((i == 0 ? Modifier.PUBLIC : Modifier.STATIC)) .addField(field(STRING_TYPE, clazz.toLowerCase(), Retained.class)); if (lastBuilder != null) { currentBuilder.addType(lastBuilder.build()); } // we generate static inner class names eg A.B -> A$B generatedClasses[i] = IntStream.range(0, i + 1).boxed().map(n -> classes[n]) .collect(Collectors.joining("$")); lastBuilder = currentBuilder; } final JavaFile file = JavaFile.builder(TEST_PACKAGE, lastBuilder.build()).build(); final JavaFileObject object = JavaFileObjects .forSourceString(TEST_PACKAGE + "." + classes[0], file.toString()); return new GeneratedClassWithName(object, generatedClasses); }
public void generate(Appendable appendable) throws IOException { int pos = this.fullyQualifiedName.lastIndexOf("."); String className; String packageName; if (pos > 0) { packageName = this.fullyQualifiedName.substring(0, pos); className = this.fullyQualifiedName.substring(pos + 1); } else { packageName = ""; className = this.fullyQualifiedName; } Builder classBuilder = TypeSpec.classBuilder(className); classBuilder.addModifiers(Modifier.PUBLIC, Modifier.FINAL); classBuilder.addSuperinterface(CodecProvider.class); addInstanceFields(classBuilder); addConstructor(classBuilder); addGetMethod(classBuilder); JavaFile javaFile = JavaFile.builder(packageName, classBuilder.build()).build(); javaFile.writeTo(appendable); }
public void generate(Appendable appendable) throws IOException { Builder classBuilder = TypeSpec.classBuilder(this.className); classBuilder.addModifiers(Modifier.PUBLIC, Modifier.FINAL); ClassName codec = ClassName.get(Codec.class); classBuilder.addSuperinterface(ParameterizedTypeName.get(codec, this.thisType)); List<FieldModel> fieldInfos = collectFields(); addEncodeMethod(classBuilder, fieldInfos); addDecodeMethod(classBuilder, fieldInfos); addGetEncoderClassMethod(classBuilder); addInstanceFields(classBuilder); addConstructor(classBuilder); JavaFile javaFile = JavaFile.builder(this.packageName, classBuilder.build()) .build(); javaFile.writeTo(appendable); }
private void addInstanceFields(Builder classBuilder) { for (InstanceField instanceField : this.instanceFields) { FieldSpec field; if (instanceField.isRegistryCodec()) { field = FieldSpec .builder( ParameterizedTypeName.get(ClassName.get(Codec.class), instanceField.codecForClass()), instanceField.name()) .addModifiers(Modifier.PRIVATE, Modifier.FINAL).build(); } else { field = FieldSpec.builder(instanceField.type(), instanceField.name()) .addModifiers(Modifier.PRIVATE, Modifier.FINAL).build(); } classBuilder.addField(field); } }
private void addEncodeMethod(Builder classBuilder, List<FieldModel> fieldModel) { MethodSpec.Builder encode = MethodSpec.methodBuilder("encode") .returns(TypeName.VOID).addModifiers(Modifier.PUBLIC) .addAnnotation(Override.class).addParameter(BsonWriter.class, "writer") .addParameter(this.thisType, "value") .addParameter(EncoderContext.class, "encoderContext") .addStatement("writer.writeStartDocument()"); for (FieldModel field : fieldModel) { String getter = "value." + field.methodNameGet() + "()"; String setter = "value." + field.methodNameSet() + "(%s)"; CodeGeneratorContext ctx = new CodeGeneratorContext(field, encode, this.instanceFields, getter, setter); field.codeGen().addEncodeStatements(ctx); } encode.addStatement("writer.writeEndDocument()"); classBuilder.addMethod(encode.build()); }
public void generate(Appendable appendable) throws IOException { Builder classBuilder = TypeSpec.classBuilder(this.className); classBuilder.addModifiers(Modifier.PUBLIC, Modifier.FINAL); for (Constant constant : collectFields()) { FieldSpec fieldSpec = FieldSpec.builder(String.class, constant.getName()) .addModifiers(Modifier.PUBLIC, Modifier.FINAL, Modifier.STATIC) .initializer("$S", constant.getValue()).build(); classBuilder.addField(fieldSpec); } JavaFile javaFile = JavaFile.builder(this.packageName, classBuilder.build()) .build(); javaFile.writeTo(appendable); }
private FieldSpec buildProjectionField() { CodeBlock.Builder initializer = CodeBlock.builder(); initializer.add("{"); boolean first = true; for (RecordField field : parsed.fields) { if (!first) { initializer.add(", "); } initializer.add("$N.$L()", projectionsClass, field.name); first = false; } initializer.add("}"); TypeName arrayOfStrings = ArrayTypeName.of(ClassName.get(String.class)); return FieldSpec.builder(arrayOfStrings, "PROJECTION", Modifier.PRIVATE, Modifier.STATIC, Modifier.FINAL) .initializer(initializer.build().toString()) .build(); }