/* * Copyright (C) 2018 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License */ package com.android.dialer.rootcomponentgenerator; import static com.google.auto.common.AnnotationMirrors.getAnnotationValue; import static com.google.auto.common.MoreElements.getAnnotationMirror; import static javax.lang.model.element.Modifier.ABSTRACT; import static javax.lang.model.element.Modifier.PUBLIC; import static javax.lang.model.element.Modifier.STATIC; import static javax.lang.model.util.ElementFilter.typesIn; import com.android.dialer.inject.IncludeInDialerRoot; import com.google.auto.common.BasicAnnotationProcessor.ProcessingStep; import com.google.auto.common.MoreElements; import com.google.common.base.Optional; import com.google.common.collect.ImmutableSet; import com.google.common.collect.SetMultimap; import com.squareup.javapoet.AnnotationSpec; import com.squareup.javapoet.ClassName; import com.squareup.javapoet.FieldSpec; import com.squareup.javapoet.MethodSpec; import com.squareup.javapoet.ParameterSpec; import com.squareup.javapoet.TypeName; import com.squareup.javapoet.TypeSpec; import dagger.Subcomponent; import java.lang.annotation.Annotation; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Set; import javax.annotation.processing.ProcessingEnvironment; import javax.lang.model.element.AnnotationMirror; import javax.lang.model.element.AnnotationValue; import javax.lang.model.element.Element; import javax.lang.model.element.ExecutableElement; import javax.lang.model.element.TypeElement; import javax.lang.model.element.VariableElement; import javax.lang.model.type.TypeMirror; /** * Generates component for a type annotated with {@link IncludeInDialerRoot}. * *
Our components have boilerplate code like: * *
* *
*
*
* {@literal @}dagger.Subcomponent
* public abstract class GenXXXXComponent {
* public static SimulatorComponent get(Context context) {
* return ((HasComponent)((HasRootComponent) context.getApplicationContext()).component())
* .simulatorComponent();
* }
* {@literal @}IncludeInDialerRoot
* public interface HasComponent {
* SimulatorComponent simulatorComponent();
* }
* }
*
*
*/
final class ComponentGeneratingStep implements ProcessingStep {
private static final String DIALER_INJECT_PACKAGE = "com.android.dialer.inject";
private static final String DIALER_HASROOTCOMPONENT_INTERFACE = "HasRootComponent";
private static final ClassName ANDROID_CONTEXT_CLASS_NAME =
ClassName.get("android.content", "Context");
private final ProcessingEnvironment processingEnv;
public ComponentGeneratingStep(ProcessingEnvironment processingEnv) {
this.processingEnv = processingEnv;
}
@Override
public Set extends Class extends Annotation>> annotations() {
return ImmutableSet.of(IncludeInDialerRoot.class);
}
@Override
public Set extends Element> process(
SetMultimapThe annotation processor will generate a new type file with some prefix, which contains
* public static XXX get(Context context) method and HasComponent interface.
*
* @param dialerComponentElement a component used by the annotation processor.
*/
private void generateComponent(TypeElement dialerComponentElement) {
TypeSpec.Builder componentClass =
dialerComponentElement.getKind().isClass()
? cloneClass(dialerComponentElement, RootComponentUtils.GENERATED_COMPONENT_PREFIX)
: cloneInterface(dialerComponentElement, RootComponentUtils.GENERATED_COMPONENT_PREFIX);
componentClass.addAnnotation(makeDaggerSubcomponentAnnotation(dialerComponentElement));
RootComponentUtils.writeJavaFile(
processingEnv,
ClassName.get(dialerComponentElement).packageName(),
dialerBoilerplateCode(componentClass, dialerComponentElement));
}
@SuppressWarnings("unchecked")
private AnnotationSpec makeDaggerSubcomponentAnnotation(TypeElement dialerComponentElement) {
Optional