summaryrefslogtreecommitdiff
path: root/src/main/java/org
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/org')
-rw-r--r--src/main/java/org/javacs/JavaCompilerService.java20
-rw-r--r--src/main/java/org/javacs/WarnUnused.java63
-rw-r--r--src/main/java/org/javacs/Warning.java70
3 files changed, 151 insertions, 2 deletions
diff --git a/src/main/java/org/javacs/JavaCompilerService.java b/src/main/java/org/javacs/JavaCompilerService.java
index 1646ecb..3d47052 100644
--- a/src/main/java/org/javacs/JavaCompilerService.java
+++ b/src/main/java/org/javacs/JavaCompilerService.java
@@ -137,28 +137,44 @@ public class JavaCompilerService {
public List<Diagnostic<? extends JavaFileObject>> reportErrors(Collection<URI> uris) {
LOG.info(String.format("Report errors in %d files...", uris.size()));
- var options = options(sourcePath, classPath);
// Construct list of sources
var files = new ArrayList<File>();
for (var p : uris) files.add(new File(p));
var sources = fileManager.getJavaFileObjectsFromFiles(files);
+
// Create task
+ var options = options(sourcePath, classPath);
var task =
(JavacTask) compiler.getTask(null, fileManager, diags::add, options, Collections.emptyList(), sources);
+ var trees = Trees.instance(task);
+
// Print timing information for optimization
var profiler = new Profiler();
task.addTaskListener(profiler);
+
// Run compilation
diags.clear();
+ Iterable<? extends CompilationUnitTree> roots;
try {
+ roots = task.parse();
task.analyze();
} catch (IOException e) {
throw new RuntimeException(e);
}
profiler.print();
-
LOG.info(String.format("...found %d errors", diags.size()));
+ // Check for unused privates
+ for (var r : roots) {
+ var warnUnused = new WarnUnused(task);
+ warnUnused.scan(r, null);
+ for (var unusedEl : warnUnused.notUsed()) {
+ var path = trees.getPath(unusedEl);
+ diags.add(
+ new Warning(task, path, "unused", String.format("`%s` is not used", unusedEl.getSimpleName())));
+ }
+ }
+
return Collections.unmodifiableList(new ArrayList<>(diags));
}
diff --git a/src/main/java/org/javacs/WarnUnused.java b/src/main/java/org/javacs/WarnUnused.java
new file mode 100644
index 0000000..451a524
--- /dev/null
+++ b/src/main/java/org/javacs/WarnUnused.java
@@ -0,0 +1,63 @@
+package org.javacs;
+
+import com.sun.source.tree.*;
+import com.sun.source.util.*;
+import java.util.*;
+import javax.lang.model.element.*;
+
+class WarnUnused extends TreePathScanner<Void, Void> {
+ private final Trees trees;
+ private final Set<Element> declared = new HashSet<>(), used = new HashSet<>();
+
+ WarnUnused(JavacTask task) {
+ this.trees = Trees.instance(task);
+ }
+
+ Set<Element> notUsed() {
+ declared.removeAll(used);
+ return declared;
+ }
+
+ Element current() {
+ return trees.getElement(getCurrentPath());
+ }
+
+ boolean isPrivate(VariableTree t) {
+ return t.getModifiers().getFlags().contains(Modifier.PRIVATE);
+ }
+
+ boolean isLocal(VariableTree t) {
+ var parent = getCurrentPath().getParentPath().getLeaf();
+ return !(parent instanceof ClassTree);
+ }
+
+ boolean isPrivate(MethodTree t) {
+ return t.getModifiers().getFlags().contains(Modifier.PRIVATE);
+ }
+
+ @Override
+ public Void visitVariable(VariableTree t, Void __) {
+ if (isPrivate(t) || isLocal(t)) {
+ declared.add(current());
+ }
+ return super.visitVariable(t, null);
+ }
+
+ @Override
+ public Void visitIdentifier(IdentifierTree t, Void __) {
+ used.add(current());
+ return super.visitIdentifier(t, null);
+ }
+
+ @Override
+ public Void visitMemberSelect(MemberSelectTree t, Void __) {
+ used.add(current());
+ return super.visitMemberSelect(t, null);
+ }
+
+ @Override
+ public Void visitMemberReference(MemberReferenceTree t, Void __) {
+ used.add(current());
+ return super.visitMemberReference(t, null);
+ }
+}
diff --git a/src/main/java/org/javacs/Warning.java b/src/main/java/org/javacs/Warning.java
new file mode 100644
index 0000000..a173d40
--- /dev/null
+++ b/src/main/java/org/javacs/Warning.java
@@ -0,0 +1,70 @@
+package org.javacs;
+
+import com.sun.source.tree.LineMap;
+import com.sun.source.util.*;
+import java.util.Locale;
+import javax.tools.*;
+import javax.tools.JavaFileObject;
+
+class Warning implements Diagnostic<JavaFileObject> {
+
+ private final JavaFileObject source;
+ private final LineMap lines;
+ private final long start, end;
+ private final String code, message;
+
+ Warning(JavacTask task, TreePath path, String code, String message) {
+ this.source = path.getCompilationUnit().getSourceFile();
+ this.lines = path.getCompilationUnit().getLineMap();
+ var pos = Trees.instance(task).getSourcePositions();
+ this.start = pos.getStartPosition(path.getCompilationUnit(), path.getLeaf());
+ this.end = pos.getEndPosition(path.getCompilationUnit(), path.getLeaf());
+ this.code = code;
+ this.message = message;
+ }
+
+ @Override
+ public Kind getKind() {
+ return Kind.WARNING;
+ }
+
+ @Override
+ public JavaFileObject getSource() {
+ return source;
+ }
+
+ @Override
+ public long getPosition() {
+ return start;
+ }
+
+ @Override
+ public long getStartPosition() {
+ return start;
+ }
+
+ @Override
+ public long getEndPosition() {
+ return end;
+ }
+
+ @Override
+ public long getLineNumber() {
+ return lines.getLineNumber(start);
+ }
+
+ @Override
+ public long getColumnNumber() {
+ return lines.getColumnNumber(start);
+ }
+
+ @Override
+ public String getCode() {
+ return code;
+ }
+
+ @Override
+ public String getMessage(Locale locale) {
+ return message;
+ }
+}