| /* |
| * Copyright 2014 The Kythe Authors. All rights reserved. |
| * |
| * 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.google.devtools.kythe.extractors.java; |
| |
| import com.sun.tools.javac.code.Symbol.ClassSymbol; |
| import com.sun.tools.javac.code.Symbol.TypeSymbol; |
| import java.io.IOException; |
| import java.util.Arrays; |
| import java.util.Set; |
| import java.util.logging.Level; |
| import java.util.logging.Logger; |
| import javax.annotation.processing.AbstractProcessor; |
| import javax.annotation.processing.Generated; |
| import javax.annotation.processing.RoundEnvironment; |
| import javax.annotation.processing.SupportedAnnotationTypes; |
| import javax.lang.model.SourceVersion; |
| import javax.lang.model.element.Element; |
| import javax.lang.model.element.TypeElement; |
| import javax.tools.JavaFileObject; |
| import javax.tools.JavaFileObject.Kind; |
| import javax.tools.StandardLocation; |
| |
| /** |
| * This class is used to visit all the annotation used in Java files and record the usage of these |
| * annotation as JavaFileObject. This processing will eliminate some of the platform errors caused |
| * by javac not being able to find the class for some of the annotations in the analysis phase. The |
| * recorded files will later be put in the datastore for analysis phase. |
| */ |
| @SupportedAnnotationTypes(value = {"*"}) |
| public class ProcessAnnotation extends AbstractProcessor { |
| |
| private static final Logger logger = Logger.getLogger(ProcessAnnotation.class.getName()); |
| |
| // ANDROID_BUILD: This line has been copied from ../../platform/shared/Metadata.java to avoid |
| // compiling that file and all its dependencies when building javac_extractor for Android. |
| private static final String ANNOTATION_COMMENT_PREFIX = "annotations:"; |
| |
| UsageAsInputReportingFileManager fileManager; |
| |
| public ProcessAnnotation(UsageAsInputReportingFileManager fileManager) { |
| this.fileManager = fileManager; |
| } |
| |
| @Override |
| public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) { |
| for (TypeElement e : annotations) { |
| TypeSymbol s = (TypeSymbol) e; |
| try { |
| UsageAsInputReportingJavaFileObject jfo = |
| (UsageAsInputReportingJavaFileObject) |
| fileManager.getJavaFileForInput( |
| StandardLocation.CLASS_OUTPUT, s.flatName().toString(), Kind.CLASS); |
| if (jfo == null) { |
| jfo = |
| (UsageAsInputReportingJavaFileObject) |
| fileManager.getJavaFileForInput( |
| StandardLocation.CLASS_PATH, s.flatName().toString(), Kind.CLASS); |
| } |
| if (jfo == null) { |
| jfo = |
| (UsageAsInputReportingJavaFileObject) |
| fileManager.getJavaFileForInput( |
| StandardLocation.SOURCE_PATH, s.flatName().toString(), Kind.CLASS); |
| } |
| if (jfo != null) { |
| jfo.markUsed(); |
| } |
| } catch (IOException ex) { |
| // We only log any IO exception here and do not cancel the whole processing because of an |
| // exception in this stage. |
| logger.log(Level.SEVERE, "Error in annotation processing", ex); |
| } |
| } |
| for (Element ae : roundEnv.getElementsAnnotatedWith(Generated.class)) { |
| Generated generated = ae.getAnnotation(Generated.class); |
| if (generated == null |
| || generated.comments() == null |
| || !generated.comments().startsWith(ANNOTATION_COMMENT_PREFIX)) { |
| continue; |
| } |
| String annotationFile = generated.comments().substring(ANNOTATION_COMMENT_PREFIX.length()); |
| if (ae instanceof ClassSymbol) { |
| ClassSymbol cs = (ClassSymbol) ae; |
| try { |
| String annotationPath = cs.sourcefile.toUri().resolve(annotationFile).getPath(); |
| for (JavaFileObject file : |
| fileManager.getJavaFileForSources(Arrays.asList(annotationPath))) { |
| ((UsageAsInputReportingJavaFileObject) file).markUsed(); |
| } |
| } catch (IllegalArgumentException ex) { |
| logger.log(Level.WARNING, "Bad annotationFile: " + annotationFile, ex); |
| } |
| } |
| } |
| // We must return false so normal processors run after us. |
| return false; |
| } |
| |
| @Override |
| public SourceVersion getSupportedSourceVersion() { |
| return SourceVersion.latest(); |
| } |
| } |