Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,20 @@ private Integer processDocument(
writer.emitHoverEdge(ids.resultSet, hoverId);
}
}

// Overrides
if (symbolInformation.getOverriddenSymbolsCount() > 0) {
int[] overriddenReferenceResultIds = new int[symbolInformation.getOverriddenSymbolsCount()];
for (int i = 0; i < symbolInformation.getOverriddenSymbolsCount(); i++) {
String overriddenSymbol = symbolInformation.getOverriddenSymbols(i);
ResultIds overriddenIds = results.getOrInsertResultSet(overriddenSymbol);
overriddenReferenceResultIds[i] = overriddenIds.referenceResult;
writer.emitReferenceResultsItemEdge(
overriddenIds.referenceResult, new int[] {rangeId}, doc.id);
}
writer.emitReferenceResultsItemEdge(
ids.referenceResult, overriddenReferenceResultIds, doc.id);
}
}
writer.emitContains(doc.id, new ArrayList<>(rangeIds));
writer.flush();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,16 @@ public void emitItem(int outV, int inV, int document) {
emitObject(lsifEdge("item").setOutV(outV).addInVs(inV).setDocument(document));
}

public void emitReferenceResultsItemEdge(int outV, int[] inVs, int document) {
List<Integer> ints = Arrays.stream(inVs).boxed().collect(Collectors.toList());
emitObject(
lsifEdge("item")
.setOutV(outV)
.addAllInVs(ints)
.setDocument(document)
.setProperty("referenceResults"));
}

public void build() throws IOException {
close();
Files.move(tmp, options.output, StandardCopyOption.REPLACE_EXISTING);
Expand Down
1 change: 1 addition & 0 deletions lsif-semanticdb/src/main/protobuf/lsif.proto
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ message LsifObject {
LsifPosition end = 20;
string name = 21;
string manager = 22;
string property = 23;
}

message LsifToolInfo {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package com.sourcegraph.semanticdb_javac;

import com.sun.source.util.*;
import com.sun.tools.javac.api.BasicJavacTask;
import com.sun.tools.javac.model.JavacTypes;

/** Entrypoint of the semanticdb-javac compiler plugin. */
public class SemanticdbPlugin implements Plugin {
Expand All @@ -15,12 +17,14 @@ public void init(JavacTask task, String... args) {
SemanticdbReporter reporter = new SemanticdbReporter();
SemanticdbJavacOptions options = SemanticdbJavacOptions.parse(args);
GlobalSymbolsCache globals = new GlobalSymbolsCache(options);
JavacTypes javacTypes = JavacTypes.instance(((BasicJavacTask) task).getContext());
if (!options.errors.isEmpty()) {
for (String error : options.errors) {
reporter.error(error);
}
} else {
task.addTaskListener(new SemanticdbTaskListener(options, task, globals, reporter));
task.addTaskListener(
new SemanticdbTaskListener(options, task, globals, reporter, javacTypes));
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import com.sun.source.util.TaskEvent;
import com.sun.source.util.TaskListener;
import com.sourcegraph.semanticdb_javac.Semanticdb;
import com.sun.tools.javac.model.JavacTypes;

import java.io.IOException;
import java.nio.file.Files;
Expand All @@ -19,16 +20,19 @@ public final class SemanticdbTaskListener implements TaskListener {
private final JavacTask task;
private final GlobalSymbolsCache globals;
private final SemanticdbReporter reporter;
private final JavacTypes javacTypes;

public SemanticdbTaskListener(
SemanticdbJavacOptions options,
JavacTask task,
GlobalSymbolsCache globals,
SemanticdbReporter reporter) {
SemanticdbReporter reporter,
JavacTypes javacTypes) {
this.options = options;
this.task = task;
this.globals = globals;
this.reporter = reporter;
this.javacTypes = javacTypes;
}

@Override
Expand All @@ -51,7 +55,7 @@ private void onFinishedAnalyze(TaskEvent e) {
Result<Path, String> path = semanticdbOutputPath(options, e);
if (path.isOk()) {
Semanticdb.TextDocument textDocument =
new SemanticdbVisitor(task, globals, e, options)
new SemanticdbVisitor(task, globals, e, options, javacTypes)
.buildTextDocument(e.getCompilationUnit());
writeSemanticdb(path.getOrThrow(), textDocument);
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import com.sun.tools.javac.code.Flags;
import com.sun.tools.javac.code.Symbol;
import com.sun.tools.javac.code.Type;
import com.sun.tools.javac.model.JavacTypes;
import com.sun.tools.javac.tree.EndPosTable;
import com.sun.tools.javac.tree.JCTree;
import com.sun.tools.javac.util.JCDiagnostic;
Expand All @@ -19,10 +20,7 @@
import java.nio.file.Path;
import java.nio.file.Paths;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Optional;
import java.util.*;
import java.util.stream.Collectors;

import static com.sourcegraph.semanticdb_javac.SemanticdbTypeVisitor.ARRAY_SYMBOL;
Expand All @@ -34,6 +32,7 @@ public class SemanticdbVisitor extends TreePathScanner<Void, Void> {
private final LocalSymbolsCache locals;
private final JavacTask task;
private final TaskEvent event;
private final JavacTypes javacTypes;
private final Trees trees;
private final SemanticdbJavacOptions options;
private final EndPosTable endPosTable;
Expand All @@ -42,12 +41,17 @@ public class SemanticdbVisitor extends TreePathScanner<Void, Void> {
private String source;

public SemanticdbVisitor(
JavacTask task, GlobalSymbolsCache globals, TaskEvent event, SemanticdbJavacOptions options) {
JavacTask task,
GlobalSymbolsCache globals,
TaskEvent event,
SemanticdbJavacOptions options,
JavacTypes javacTypes) {
this.task = task;
this.globals = globals; // Reused cache between compilation units.
this.locals = new LocalSymbolsCache(); // Fresh cache per compilation unit.
this.event = event;
this.options = options;
this.javacTypes = javacTypes;
this.trees = Trees.instance(task);
if (event.getCompilationUnit() instanceof JCTree.JCCompilationUnit) {
this.endPosTable = ((JCTree.JCCompilationUnit) event.getCompilationUnit()).endPositions;
Expand Down Expand Up @@ -113,6 +117,7 @@ private void emitSymbolInformation(Symbol sym, JCTree tree) {
break;
case METHOD:
builder.setKind(Kind.METHOD);
builder.addAllOverriddenSymbols(semanticdbOverrides(sym));
break;
case CONSTRUCTOR:
builder.setKind(Kind.CONSTRUCTOR);
Expand Down Expand Up @@ -502,6 +507,17 @@ private int semanticdbSymbolInfoProperties(Symbol sym) {
return properties;
}

private List<String> semanticdbOverrides(Symbol sym) {
ArrayList<String> overriddenSymbols = new ArrayList<>();
Set<Symbol.MethodSymbol> overriddenMethods = javacTypes.getOverriddenMethods(sym);

for (Symbol.MethodSymbol meth : overriddenMethods) {
overriddenSymbols.add(semanticdbSymbol(meth));
}

return overriddenSymbols;
}

private Semanticdb.Access semanticdbAccess(Symbol sym) {
switch ((int) sym.flags() & Flags.AccessFlags) {
case Flags.PRIVATE:
Expand Down
144 changes: 144 additions & 0 deletions tests/unit/src/test/scala/tests/OverridesSuite.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
package tests

import java.util.stream.Collectors

import scala.meta.Input

import com.sourcegraph.lsif_semanticdb.Symtab
import munit.FunSuite
import munit.TestOptions

class OverridesSuite extends FunSuite with TempDirectories {

val targetroot = new DirectoryFixture()

override def munitFixtures: Seq[Fixture[_]] =
super.munitFixtures ++ List(targetroot)

def checkOverrides(
options: TestOptions,
source: String,
extractSymbol: String,
expectedSymbols: String*
): Unit = {
test(options) {
val compiler = new TestCompiler(targetroot())
val relativePath = "example.Parent".replace('.', '/') + ".java"
val input = Input.VirtualFile(relativePath, source)
val result = compiler.compileSemanticdb(List(input))
val symtab = new Symtab(result.textDocument)

val expectedSyms = expectedSymbols.mkString("\n")
val syms = symtab
.symbols
.get(extractSymbol)
.getOverriddenSymbolsList
.stream
.collect(Collectors.joining("\n"))
assertNoDiff(expectedSyms, syms)
}
}

checkOverrides(
"same file",
"""package example;
|
|class Parent {
| public void stuff() {}
|
| class Child extends Parent {
| @Override
| public void stuff() {}
| }
|}
|""".stripMargin,
"example/Parent#Child#stuff().",
"example/Parent#stuff()."
)

checkOverrides(
"external override",
"""package example;
|
|class Parent {
| @Override
| public String toString() { return ""; }
|}
|""".stripMargin,
"example/Parent#toString().",
"java/lang/Object#toString()."
)

checkOverrides(
"implement interface",
"""package example;
|
|class Parent {
| interface Test {
| public void stuff();
| }
|
| class Child implements Test {
| @Override
| public void stuff() {}
| }
|}
|""".stripMargin,
"example/Parent#Child#stuff().",
"example/Parent#Test#stuff()."
)

checkOverrides(
"type params",
"""package example;
|
|class Parent {
| interface Haha<T> {
| void add(T elem);
| }
| class IntHaha implements Haha<Integer> {
| void add(Integer elem) {}
| }
|}
|""".stripMargin,
"example/Parent#IntHaha#add().",
"example/Parent#Haha#add()."
)

checkOverrides(
"multiple",
"""package example;
|
|class Parent {
| @Override
| public String toString() { return ""; }
|
| class Child extends Parent {
| @Override
| public String toString() { return ""; }
| }
|}
|""".stripMargin,
"example/Parent#Child#toString().",
"""example/Parent#toString().
|java/lang/Object#toString().
|""".stripMargin
)

checkOverrides(
"abstract",
"""package example;
|
|abstract class Parent {
| public abstract void stuff();
|
| class Child extends Parent {
| @Override
| public void stuff() {}
| }
|}
|""".stripMargin,
"example/Parent#Child#stuff().",
"example/Parent#stuff()."
)
}