1 /*
2  * Copyright (C) 2016 The Dagger Authors.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package dagger.grpc.server.processor;
18 
19 import static javax.lang.model.util.ElementFilter.typesIn;
20 
21 import com.google.auto.common.BasicAnnotationProcessor;
22 import com.google.auto.common.BasicAnnotationProcessor.ProcessingStep;
23 import com.google.auto.service.AutoService;
24 import com.google.common.collect.ImmutableList;
25 import com.google.common.collect.ImmutableSet;
26 import com.google.common.collect.SetMultimap;
27 import com.google.googlejavaformat.java.filer.FormattingFiler;
28 import com.squareup.javapoet.ClassName;
29 import com.squareup.javapoet.JavaFile;
30 import dagger.grpc.server.GrpcService;
31 import java.io.IOException;
32 import java.lang.annotation.Annotation;
33 import java.util.Set;
34 import javax.annotation.processing.Processor;
35 import javax.lang.model.SourceVersion;
36 import javax.lang.model.element.Element;
37 import javax.lang.model.element.TypeElement;
38 import javax.tools.Diagnostic.Kind;
39 
40 /**
41  * Generates code from types annotated with {@link GrpcService @GrpcService}.
42  *
43  * @see <a href="https://dagger.dev/dev-guide/grpc">https://dagger.dev/dev-guide/grpc</a>
44  */
45 @AutoService(Processor.class)
46 public class GrpcServiceProcessor extends BasicAnnotationProcessor implements ProcessingStep {
47 
48   @Override
initSteps()49   protected ImmutableList<GrpcServiceProcessor> initSteps() {
50     return ImmutableList.of(this);
51   }
52 
53   @Override
annotations()54   public ImmutableSet<Class<GrpcService>> annotations() {
55     return ImmutableSet.of(GrpcService.class);
56   }
57 
58   @Override
getSupportedSourceVersion()59   public SourceVersion getSupportedSourceVersion() {
60     return SourceVersion.latest();
61   }
62 
63   @Override
process( SetMultimap<Class<? extends Annotation>, Element> elementsByAnnotation)64   public Set<Element> process(
65       SetMultimap<Class<? extends Annotation>, Element> elementsByAnnotation) {
66     ImmutableSet.Builder<Element> deferredElements = ImmutableSet.builder();
67     for (TypeElement element : typesIn(elementsByAnnotation.get(GrpcService.class))) {
68       try {
69         GrpcServiceModel grpcServiceModel = new GrpcServiceModel(processingEnv, element);
70         if (grpcServiceModel.validate()) {
71           write(new ServiceDefinitionTypeGenerator(grpcServiceModel), element);
72           write(new ProxyModuleGenerator(grpcServiceModel), element);
73           write(new GrpcServiceModuleGenerator(grpcServiceModel), element);
74           write(new UnscopedGrpcServiceModuleGenerator(grpcServiceModel), element);
75         }
76       } catch (TypeNotPresentException e) {
77         deferredElements.add(element);
78       }
79     }
80     return deferredElements.build();
81   }
82 
write(SourceGenerator grpcServiceTypeWriter, final TypeElement element)83   private void write(SourceGenerator grpcServiceTypeWriter, final TypeElement element) {
84     JavaFile javaFile = grpcServiceTypeWriter.javaFile();
85     ClassName outputClassName = ClassName.get(javaFile.packageName, javaFile.typeSpec.name);
86     try {
87       javaFile.writeTo(new FormattingFiler(processingEnv.getFiler()));
88     } catch (IOException e) {
89       processingEnv
90           .getMessager()
91           .printMessage(
92               Kind.ERROR, String.format("Error writing %s: %s", outputClassName, e), element);
93     }
94   }
95 }
96