Summary: SuppressWarnings annotations are hardly used and add considerable complexity due to requiring recompilation with an annotation processor. Reviewed By: jvillard Differential Revision: D4312193 fbshipit-source-id: c4fc07emaster
parent
00f3c4227b
commit
3dfaa9ed7b
@ -1,123 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2015 - present Facebook, Inc.
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* This source code is licensed under the BSD style license found in the
|
|
||||||
* LICENSE file in the root directory of this source tree. An additional grant
|
|
||||||
* of patent rights can be found in the PATENTS file in the same directory.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.facebook.infer.annotprocess;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.PrintWriter;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.LinkedHashMap;
|
|
||||||
import java.util.LinkedHashSet;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
import javax.annotation.processing.AbstractProcessor;
|
|
||||||
import javax.annotation.processing.RoundEnvironment;
|
|
||||||
import javax.annotation.processing.SupportedAnnotationTypes;
|
|
||||||
import javax.annotation.processing.SupportedOptions;
|
|
||||||
import javax.lang.model.SourceVersion;
|
|
||||||
import javax.lang.model.element.Element;
|
|
||||||
import javax.lang.model.element.ExecutableElement;
|
|
||||||
import javax.lang.model.element.TypeElement;
|
|
||||||
import javax.lang.model.util.Elements;
|
|
||||||
|
|
||||||
@SupportedOptions({ "SuppressWarningsOutputFilename" })
|
|
||||||
@SupportedAnnotationTypes({ "java.lang.SuppressWarnings" })
|
|
||||||
public class CollectSuppressWarnings extends AbstractProcessor {
|
|
||||||
|
|
||||||
private static final String OUTPUT_FILENAME_OPTION = "SuppressWarningsOutputFilename";
|
|
||||||
|
|
||||||
// map of (classes -> methods in class). an empty set means suppress all warnings on class
|
|
||||||
public Map<String, Set<String>> mSuppressMap = new LinkedHashMap<String, Set<String>>();
|
|
||||||
|
|
||||||
// total number of classes/methods with a SuppressWarnings annotation
|
|
||||||
private int mNumToSuppress = 0;
|
|
||||||
|
|
||||||
// write the methods/classes to suppress to .inferconfig-style JSON
|
|
||||||
private void exportSuppressMap() throws IOException {
|
|
||||||
|
|
||||||
Map<String, String> options = processingEnv.getOptions();
|
|
||||||
String mOutputFilename =
|
|
||||||
Preconditions.checkNotNull(options.get(OUTPUT_FILENAME_OPTION),
|
|
||||||
"The filename should be passed from the Infer top-level script");
|
|
||||||
|
|
||||||
// output .inferconfig format file in JSON
|
|
||||||
try (PrintWriter out = new PrintWriter(mOutputFilename)) {
|
|
||||||
int elemCount = 0;
|
|
||||||
out.println("{ \"suppress_warnings\": [");
|
|
||||||
for (Map.Entry<String, Set<String>> entry : mSuppressMap.entrySet()) {
|
|
||||||
String clazz = entry.getKey();
|
|
||||||
Set<String> methods = entry.getValue();
|
|
||||||
if (methods.isEmpty()) { // empty set of methods means annotation is on class
|
|
||||||
JSONOutputUtils.outputClass(out, clazz, ++elemCount, mNumToSuppress);
|
|
||||||
} else {
|
|
||||||
for (String method : methods) {
|
|
||||||
JSONOutputUtils.outputMethod(out, clazz, method, ++elemCount, mNumToSuppress);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
out.println("] }");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// we only care about @SuppressWarnings("null") and @SuppressWarnings("infer"); ignore otherwise
|
|
||||||
private boolean shouldProcess(SuppressWarnings annot) {
|
|
||||||
for (String value : annot.value()) {
|
|
||||||
if (value.equals("null") || value.equals("infer")) return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// collect all of the SuppressWarnings annotations from the Java source files being compiled
|
|
||||||
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
|
|
||||||
|
|
||||||
Elements elements = processingEnv.getElementUtils();
|
|
||||||
for (TypeElement te : annotations) {
|
|
||||||
for (Element e : roundEnv.getElementsAnnotatedWith(te)) {
|
|
||||||
SuppressWarnings annot = e.getAnnotation(SuppressWarnings.class);
|
|
||||||
if (annot != null && shouldProcess(annot)) {
|
|
||||||
if (e instanceof TypeElement) { // class
|
|
||||||
String className = elements.getBinaryName((TypeElement) e).toString();
|
|
||||||
mSuppressMap.put(className, Collections.EMPTY_SET);
|
|
||||||
mNumToSuppress++;
|
|
||||||
} else if (e instanceof ExecutableElement) { // method
|
|
||||||
String classname = e.getEnclosingElement().toString();
|
|
||||||
java.util.Set<String> suppressMethods = mSuppressMap.get(classname);
|
|
||||||
if (suppressMethods != null && suppressMethods.isEmpty()) {
|
|
||||||
// empty set means suppress warnings on all methods in class; do nothing
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (suppressMethods == null) {
|
|
||||||
suppressMethods = new LinkedHashSet<String>();
|
|
||||||
}
|
|
||||||
suppressMethods.add(e.getSimpleName().toString());
|
|
||||||
mSuppressMap.put(classname, suppressMethods);
|
|
||||||
mNumToSuppress++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (roundEnv.processingOver() && mNumToSuppress > 0) {
|
|
||||||
try {
|
|
||||||
exportSuppressMap();
|
|
||||||
} catch (IOException e) {
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public SourceVersion getSupportedSourceVersion() {
|
|
||||||
return SourceVersion.latestSupported();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1 +0,0 @@
|
|||||||
com.facebook.infer.annotprocess.CollectSuppressWarnings
|
|
@ -1,51 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2015 - present Facebook, Inc.
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* This source code is licensed under the BSD style license found in the
|
|
||||||
* LICENSE file in the root directory of this source tree. An additional grant
|
|
||||||
* of patent rights can be found in the PATENTS file in the same directory.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package codetoanalyze.java.eradicate;
|
|
||||||
|
|
||||||
import java.lang.SuppressWarnings;
|
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
|
||||||
|
|
||||||
public class SuppressWarningsExample {
|
|
||||||
|
|
||||||
@SuppressWarnings("null")
|
|
||||||
static class DoSuppress {
|
|
||||||
|
|
||||||
@Nullable Object mFld;
|
|
||||||
|
|
||||||
void doSuppress1(@Nullable Object o) {
|
|
||||||
o.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
void doSuppress2() {
|
|
||||||
mFld.toString();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("null")
|
|
||||||
public void doSuppress(@Nullable Object o) {
|
|
||||||
o.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("infer")
|
|
||||||
public void doSuppressInferAnnot(@Nullable Object o) {
|
|
||||||
o.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
public void doNotSuppressWrongAnnot(@Nullable Object o) {
|
|
||||||
o.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void doNotSuppressNoAnnot(@Nullable Object o) {
|
|
||||||
o.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
Loading…
Reference in new issue