Skip to content

Commit c559b3e

Browse files
authored
emit overridden methods for method SymbolInformation (#172)
1 parent a86c1cc commit c559b3e

File tree

7 files changed

+200
-4
lines changed

7 files changed

+200
-4
lines changed

lsif-semanticdb/src/main/java/com/sourcegraph/lsif_semanticdb/LsifSemanticdb.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,20 @@ private Integer processDocument(
155155
writer.emitHoverEdge(ids.resultSet, hoverId);
156156
}
157157
}
158+
159+
// Overrides
160+
if (symbolInformation.getOverriddenSymbolsCount() > 0) {
161+
int[] overriddenReferenceResultIds = new int[symbolInformation.getOverriddenSymbolsCount()];
162+
for (int i = 0; i < symbolInformation.getOverriddenSymbolsCount(); i++) {
163+
String overriddenSymbol = symbolInformation.getOverriddenSymbols(i);
164+
ResultIds overriddenIds = results.getOrInsertResultSet(overriddenSymbol);
165+
overriddenReferenceResultIds[i] = overriddenIds.referenceResult;
166+
writer.emitReferenceResultsItemEdge(
167+
overriddenIds.referenceResult, new int[] {rangeId}, doc.id);
168+
}
169+
writer.emitReferenceResultsItemEdge(
170+
ids.referenceResult, overriddenReferenceResultIds, doc.id);
171+
}
158172
}
159173
writer.emitContains(doc.id, new ArrayList<>(rangeIds));
160174
writer.flush();

lsif-semanticdb/src/main/java/com/sourcegraph/lsif_semanticdb/LsifWriter.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,16 @@ public void emitItem(int outV, int inV, int document) {
133133
emitObject(lsifEdge("item").setOutV(outV).addInVs(inV).setDocument(document));
134134
}
135135

136+
public void emitReferenceResultsItemEdge(int outV, int[] inVs, int document) {
137+
List<Integer> ints = Arrays.stream(inVs).boxed().collect(Collectors.toList());
138+
emitObject(
139+
lsifEdge("item")
140+
.setOutV(outV)
141+
.addAllInVs(ints)
142+
.setDocument(document)
143+
.setProperty("referenceResults"));
144+
}
145+
136146
public void build() throws IOException {
137147
close();
138148
Files.move(tmp, options.output, StandardCopyOption.REPLACE_EXISTING);

lsif-semanticdb/src/main/protobuf/lsif.proto

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ message LsifObject {
2525
LsifPosition end = 20;
2626
string name = 21;
2727
string manager = 22;
28+
string property = 23;
2829
}
2930

3031
message LsifToolInfo {

semanticdb-javac/src/main/java/com/sourcegraph/semanticdb_javac/SemanticdbPlugin.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
package com.sourcegraph.semanticdb_javac;
22

33
import com.sun.source.util.*;
4+
import com.sun.tools.javac.api.BasicJavacTask;
5+
import com.sun.tools.javac.model.JavacTypes;
46

57
/** Entrypoint of the semanticdb-javac compiler plugin. */
68
public class SemanticdbPlugin implements Plugin {
@@ -15,12 +17,14 @@ public void init(JavacTask task, String... args) {
1517
SemanticdbReporter reporter = new SemanticdbReporter();
1618
SemanticdbJavacOptions options = SemanticdbJavacOptions.parse(args);
1719
GlobalSymbolsCache globals = new GlobalSymbolsCache(options);
20+
JavacTypes javacTypes = JavacTypes.instance(((BasicJavacTask) task).getContext());
1821
if (!options.errors.isEmpty()) {
1922
for (String error : options.errors) {
2023
reporter.error(error);
2124
}
2225
} else {
23-
task.addTaskListener(new SemanticdbTaskListener(options, task, globals, reporter));
26+
task.addTaskListener(
27+
new SemanticdbTaskListener(options, task, globals, reporter, javacTypes));
2428
}
2529
}
2630
}

semanticdb-javac/src/main/java/com/sourcegraph/semanticdb_javac/SemanticdbTaskListener.java

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import com.sun.source.util.TaskEvent;
55
import com.sun.source.util.TaskListener;
66
import com.sourcegraph.semanticdb_javac.Semanticdb;
7+
import com.sun.tools.javac.model.JavacTypes;
78

89
import java.io.IOException;
910
import java.nio.file.Files;
@@ -19,16 +20,19 @@ public final class SemanticdbTaskListener implements TaskListener {
1920
private final JavacTask task;
2021
private final GlobalSymbolsCache globals;
2122
private final SemanticdbReporter reporter;
23+
private final JavacTypes javacTypes;
2224

2325
public SemanticdbTaskListener(
2426
SemanticdbJavacOptions options,
2527
JavacTask task,
2628
GlobalSymbolsCache globals,
27-
SemanticdbReporter reporter) {
29+
SemanticdbReporter reporter,
30+
JavacTypes javacTypes) {
2831
this.options = options;
2932
this.task = task;
3033
this.globals = globals;
3134
this.reporter = reporter;
35+
this.javacTypes = javacTypes;
3236
}
3337

3438
@Override
@@ -51,7 +55,7 @@ private void onFinishedAnalyze(TaskEvent e) {
5155
Result<Path, String> path = semanticdbOutputPath(options, e);
5256
if (path.isOk()) {
5357
Semanticdb.TextDocument textDocument =
54-
new SemanticdbVisitor(task, globals, e, options)
58+
new SemanticdbVisitor(task, globals, e, options, javacTypes)
5559
.buildTextDocument(e.getCompilationUnit());
5660
writeSemanticdb(path.getOrThrow(), textDocument);
5761
} else {

semanticdb-javac/src/main/java/com/sourcegraph/semanticdb_javac/SemanticdbVisitor.java

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import com.sun.tools.javac.code.Flags;
66
import com.sun.tools.javac.code.Symbol;
77
import com.sun.tools.javac.code.Type;
8+
import com.sun.tools.javac.model.JavacTypes;
89
import com.sun.tools.javac.tree.EndPosTable;
910
import com.sun.tools.javac.tree.JCTree;
1011
import com.sun.tools.javac.util.JCDiagnostic;
@@ -31,6 +32,7 @@ public class SemanticdbVisitor extends TreePathScanner<Void, Void> {
3132
private final LocalSymbolsCache locals;
3233
private final JavacTask task;
3334
private final TaskEvent event;
35+
private final JavacTypes javacTypes;
3436
private final Trees trees;
3537
private final SemanticdbJavacOptions options;
3638
private final EndPosTable endPosTable;
@@ -39,12 +41,17 @@ public class SemanticdbVisitor extends TreePathScanner<Void, Void> {
3941
private String source;
4042

4143
public SemanticdbVisitor(
42-
JavacTask task, GlobalSymbolsCache globals, TaskEvent event, SemanticdbJavacOptions options) {
44+
JavacTask task,
45+
GlobalSymbolsCache globals,
46+
TaskEvent event,
47+
SemanticdbJavacOptions options,
48+
JavacTypes javacTypes) {
4349
this.task = task;
4450
this.globals = globals; // Reused cache between compilation units.
4551
this.locals = new LocalSymbolsCache(); // Fresh cache per compilation unit.
4652
this.event = event;
4753
this.options = options;
54+
this.javacTypes = javacTypes;
4855
this.trees = Trees.instance(task);
4956
if (event.getCompilationUnit() instanceof JCTree.JCCompilationUnit) {
5057
this.endPosTable = ((JCTree.JCCompilationUnit) event.getCompilationUnit()).endPositions;
@@ -110,6 +117,7 @@ private void emitSymbolInformation(Symbol sym, JCTree tree) {
110117
break;
111118
case METHOD:
112119
builder.setKind(Kind.METHOD);
120+
builder.addAllOverriddenSymbols(semanticdbOverrides(sym));
113121
break;
114122
case CONSTRUCTOR:
115123
builder.setKind(Kind.CONSTRUCTOR);
@@ -545,6 +553,17 @@ private int semanticdbSymbolInfoProperties(Symbol sym) {
545553
return properties;
546554
}
547555

556+
private List<String> semanticdbOverrides(Symbol sym) {
557+
ArrayList<String> overriddenSymbols = new ArrayList<>();
558+
Set<Symbol.MethodSymbol> overriddenMethods = javacTypes.getOverriddenMethods(sym);
559+
560+
for (Symbol.MethodSymbol meth : overriddenMethods) {
561+
overriddenSymbols.add(semanticdbSymbol(meth));
562+
}
563+
564+
return overriddenSymbols;
565+
}
566+
548567
private Semanticdb.Access semanticdbAccess(Symbol sym) {
549568
switch ((int) sym.flags() & Flags.AccessFlags) {
550569
case Flags.PRIVATE:
Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
package tests
2+
3+
import java.util.stream.Collectors
4+
5+
import scala.meta.Input
6+
7+
import com.sourcegraph.lsif_semanticdb.Symtab
8+
import munit.FunSuite
9+
import munit.TestOptions
10+
11+
class OverridesSuite extends FunSuite with TempDirectories {
12+
13+
val targetroot = new DirectoryFixture()
14+
15+
override def munitFixtures: Seq[Fixture[_]] =
16+
super.munitFixtures ++ List(targetroot)
17+
18+
def checkOverrides(
19+
options: TestOptions,
20+
source: String,
21+
extractSymbol: String,
22+
expectedSymbols: String*
23+
): Unit = {
24+
test(options) {
25+
val compiler = new TestCompiler(targetroot())
26+
val relativePath = "example.Parent".replace('.', '/') + ".java"
27+
val input = Input.VirtualFile(relativePath, source)
28+
val result = compiler.compileSemanticdb(List(input))
29+
val symtab = new Symtab(result.textDocument)
30+
31+
val expectedSyms = expectedSymbols.mkString("\n")
32+
val syms = symtab
33+
.symbols
34+
.get(extractSymbol)
35+
.getOverriddenSymbolsList
36+
.stream
37+
.collect(Collectors.joining("\n"))
38+
assertNoDiff(expectedSyms, syms)
39+
}
40+
}
41+
42+
checkOverrides(
43+
"same file",
44+
"""package example;
45+
|
46+
|class Parent {
47+
| public void stuff() {}
48+
|
49+
| class Child extends Parent {
50+
| @Override
51+
| public void stuff() {}
52+
| }
53+
|}
54+
|""".stripMargin,
55+
"example/Parent#Child#stuff().",
56+
"example/Parent#stuff()."
57+
)
58+
59+
checkOverrides(
60+
"external override",
61+
"""package example;
62+
|
63+
|class Parent {
64+
| @Override
65+
| public String toString() { return ""; }
66+
|}
67+
|""".stripMargin,
68+
"example/Parent#toString().",
69+
"java/lang/Object#toString()."
70+
)
71+
72+
checkOverrides(
73+
"implement interface",
74+
"""package example;
75+
|
76+
|class Parent {
77+
| interface Test {
78+
| public void stuff();
79+
| }
80+
|
81+
| class Child implements Test {
82+
| @Override
83+
| public void stuff() {}
84+
| }
85+
|}
86+
|""".stripMargin,
87+
"example/Parent#Child#stuff().",
88+
"example/Parent#Test#stuff()."
89+
)
90+
91+
checkOverrides(
92+
"type params",
93+
"""package example;
94+
|
95+
|class Parent {
96+
| interface Haha<T> {
97+
| void add(T elem);
98+
| }
99+
| class IntHaha implements Haha<Integer> {
100+
| void add(Integer elem) {}
101+
| }
102+
|}
103+
|""".stripMargin,
104+
"example/Parent#IntHaha#add().",
105+
"example/Parent#Haha#add()."
106+
)
107+
108+
checkOverrides(
109+
"multiple",
110+
"""package example;
111+
|
112+
|class Parent {
113+
| @Override
114+
| public String toString() { return ""; }
115+
|
116+
| class Child extends Parent {
117+
| @Override
118+
| public String toString() { return ""; }
119+
| }
120+
|}
121+
|""".stripMargin,
122+
"example/Parent#Child#toString().",
123+
"""example/Parent#toString().
124+
|java/lang/Object#toString().
125+
|""".stripMargin
126+
)
127+
128+
checkOverrides(
129+
"abstract",
130+
"""package example;
131+
|
132+
|abstract class Parent {
133+
| public abstract void stuff();
134+
|
135+
| class Child extends Parent {
136+
| @Override
137+
| public void stuff() {}
138+
| }
139+
|}
140+
|""".stripMargin,
141+
"example/Parent#Child#stuff().",
142+
"example/Parent#stuff()."
143+
)
144+
}

0 commit comments

Comments
 (0)