Skip to content

Commit

Permalink
Merge pull request #398 from olafurpg/synthetic-symbols
Browse files Browse the repository at this point in the history
  • Loading branch information
olafurpg authored Feb 18, 2022
2 parents 604e3b0 + 23c3387 commit 923efaf
Show file tree
Hide file tree
Showing 16 changed files with 251 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,9 @@ object SemanticdbPrinters {
comments: CommentSyntax = CommentSyntax.default
): String = {
val occurrencesByLine = LsifTextDocument
.sortedSymbolOccurrences(doc)
.sortedSymbolOccurrences(
LsifTextDocument.manifestOccurrencesForSyntheticSymbols(doc)
)
.asScala
.groupBy(_.getRange.getStartLine)
val out = new StringBuilder()
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
package com.sourcegraph.lsif_semanticdb;

import com.sourcegraph.semanticdb_javac.Semanticdb;
import com.sourcegraph.semanticdb_javac.SemanticdbSymbols;

import java.nio.file.Path;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.*;

/** Wrapper around a SemanticDB TextDocument with LSIF-related utilities. */
public class LsifTextDocument {
Expand Down Expand Up @@ -74,9 +73,75 @@ void visitIdTree(Semanticdb.IdTree tree) {
}

private void setSemanticdb(Semanticdb.TextDocument semanticdb) {
this.semanticdb = semanticdb;
this.semanticdb = manifestOccurrencesForSyntheticSymbols(semanticdb);
for (Semanticdb.SymbolInformation info : semanticdb.getSymbolsList()) {
symbols.put(info.getSymbol(), info);
}
}

public static Semanticdb.TextDocument manifestOccurrencesForSyntheticSymbols(
Semanticdb.TextDocument semanticdb) {
if (semanticdb.getLanguage() != Semanticdb.Language.SCALA) {
// It's only semanticdb-scalac that emits SymbolInformation for symbols that have no
// definition occurrences.
return semanticdb;
}
Semanticdb.TextDocument.Builder builder = Semanticdb.TextDocument.newBuilder(semanticdb);
HashMap<String, Semanticdb.SymbolOccurrence> definitionOccurrences = new HashMap<>();
for (Semanticdb.SymbolOccurrence occ : semanticdb.getOccurrencesList()) {
if (occ.getRole() == Semanticdb.SymbolOccurrence.Role.DEFINITION) {
definitionOccurrences.put(occ.getSymbol(), occ);
}
}
for (Semanticdb.SymbolInformation info : semanticdb.getSymbolsList()) {
Semanticdb.SymbolOccurrence definition = definitionOccurrences.get(info.getSymbol());
if (definition != null) {
continue;
}
for (String alternativeSymbol : alternativeSymbols(info)) {
Semanticdb.SymbolOccurrence alternativeDefinition =
definitionOccurrences.get(alternativeSymbol);
if (alternativeDefinition != null) {
builder.addOccurrences(
Semanticdb.SymbolOccurrence.newBuilder(alternativeDefinition)
.setSymbol(info.getSymbol()));
break;
}
}
}
return builder.build();
}

public static final Set<String> syntheticCaseClassMethodNames =
new HashSet<>(Arrays.asList("copy", "productElement", "productElementName"));
public static final Set<String> syntheticCompanionObjectNames =
new HashSet<>(Arrays.asList("apply", "copy"));

public static List<String> alternativeSymbols(Semanticdb.SymbolInformation info) {
ArrayList<String> alternatives = new ArrayList<>();
SymbolDescriptor sym = SymbolDescriptor.parseFromSymbol(info.getSymbol());
switch (sym.descriptor.kind) {
case Method:
if (sym.descriptor.name.endsWith("_=")) {
String newName = sym.descriptor.name.substring(0, sym.descriptor.name.length() - 2);
alternatives.add(SemanticdbSymbols.global(sym.owner, sym.descriptor.withName(newName)));
} else if (syntheticCaseClassMethodNames.contains(sym.descriptor.name)) {
alternatives.add(sym.owner);
} else if (syntheticCompanionObjectNames.contains(sym.descriptor.name)) {
alternatives.add(sym.owner);
SymbolDescriptor owner = SymbolDescriptor.parseFromSymbol(sym.owner);
alternatives.add(
SemanticdbSymbols.global(
owner.owner, owner.descriptor.withKind(SemanticdbSymbols.Descriptor.Kind.Type)));
}
break;
case Term:
alternatives.add(
SemanticdbSymbols.global(
sym.owner, sym.descriptor.withKind(SemanticdbSymbols.Descriptor.Kind.Type)));
break;
default:
}
return alternatives;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,14 @@ public Descriptor(Kind kind, String name, String disambiguator) {
this.disambiguator = disambiguator;
}

public Descriptor withName(String newName) {
return new Descriptor(kind, newName, disambiguator);
}

public Descriptor withKind(Kind newKind) {
return new Descriptor(newKind, name, disambiguator);
}

public static Descriptor local(String name) {
return new Descriptor(Kind.Local, name);
}
Expand Down
9 changes: 9 additions & 0 deletions tests/minimized-scala/src/main/scala/minimized/Issue396.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package minimized

case class Issue396(a: Int)
object Issue396App {
println(Issue396)
Issue396.apply(42).copy(a = 41)
Issue396.apply(42).productElement(0)
Issue396.apply(42).productElementName(0)
}
6 changes: 6 additions & 0 deletions tests/minimized-scala/src/main/scala/minimized/Issue397.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package minimized

class Issue397 {
var blah = Set("abc")
blah = Set.empty[String]
}
3 changes: 3 additions & 0 deletions tests/snapshots/src/main/generated/BaseByteRenderer.scala
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import upickle.core.{ArrVisitor, ObjVisitor}
*/
class BaseByteRenderer[T <: upickle.core.ByteOps.Output]
// ^^^^^^^^^^^^^^^^ definition ujson/BaseByteRenderer# class BaseByteRenderer[T <: Output]
// ^^^^^^^^^^^^^^^^ definition ujson/BaseByteRenderer. object BaseByteRenderer
// ^ definition ujson/BaseByteRenderer#[T] T <: Output
// ^^^^^^^ reference upickle/
// ^^^^ reference upickle/core/
Expand Down Expand Up @@ -65,11 +66,13 @@ class BaseByteRenderer[T <: upickle.core.ByteOps.Output]

private[this] var depth: Int = 0
// ^^^^^ definition ujson/BaseByteRenderer#depth(). private[this] var depth: Int
// ^^^^^ definition ujson/BaseByteRenderer#`depth_=`(). private[this] var depth_=(x$1: Int): Unit
// ^^^ reference scala/Int#


private[this] var commaBuffered = false
// ^^^^^^^^^^^^^ definition ujson/BaseByteRenderer#commaBuffered(). private[this] var commaBuffered: Boolean
// ^^^^^^^^^^^^^ definition ujson/BaseByteRenderer#`commaBuffered_=`(). private[this] var commaBuffered_=(x$1: Boolean): Unit

def flushBuffer() = {
// ^^^^^^^^^^^ definition ujson/BaseByteRenderer#flushBuffer(). def flushBuffer(): Unit
Expand Down
3 changes: 3 additions & 0 deletions tests/snapshots/src/main/generated/BaseCharRenderer.scala
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import upickle.core.{ArrVisitor, ObjVisitor}
*/
class BaseCharRenderer[T <: upickle.core.CharOps.Output]
// ^^^^^^^^^^^^^^^^ definition ujson/BaseCharRenderer# class BaseCharRenderer[T <: Output]
// ^^^^^^^^^^^^^^^^ definition ujson/BaseCharRenderer. object BaseCharRenderer
// ^ definition ujson/BaseCharRenderer#[T] T <: Output
// ^^^^^^^ reference upickle/
// ^^^^ reference upickle/core/
Expand Down Expand Up @@ -65,11 +66,13 @@ class BaseCharRenderer[T <: upickle.core.CharOps.Output]

private[this] var depth: Int = 0
// ^^^^^ definition ujson/BaseCharRenderer#depth(). private[this] var depth: Int
// ^^^^^ definition ujson/BaseCharRenderer#`depth_=`(). private[this] var depth_=(x$1: Int): Unit
// ^^^ reference scala/Int#


private[this] var commaBuffered = false
// ^^^^^^^^^^^^^ definition ujson/BaseCharRenderer#commaBuffered(). private[this] var commaBuffered: Boolean
// ^^^^^^^^^^^^^ definition ujson/BaseCharRenderer#`commaBuffered_=`(). private[this] var commaBuffered_=(x$1: Boolean): Unit

def flushBuffer() = {
// ^^^^^^^^^^^ definition ujson/BaseCharRenderer#flushBuffer(). def flushBuffer(): Unit
Expand Down
32 changes: 32 additions & 0 deletions tests/snapshots/src/main/generated/minimized/Issue396.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package minimized
// ^^^^^^^^^ definition minimized/

case class Issue396(a: Int)
// ^^^^^^^^ definition minimized/Issue396# case class Issue396(a: Int)
// ^^^^^^^^ definition minimized/Issue396#copy(). def copy(a: Int): Issue396
// ^^^^^^^^ definition minimized/Issue396#productElement(). def productElement(x$1: Int): Any
// ^^^^^^^^ definition minimized/Issue396. object Issue396
// ^^^^^^^^ definition minimized/Issue396.apply(). def apply(a: Int): Issue396
// ^^^^^^^^ definition minimized/Issue396#productElementName(). def productElementName(x$1: Int): String
// definition minimized/Issue396#`<init>`(). def this(a: Int)
// ^ definition minimized/Issue396#a. val a: Int
// ^^^ reference scala/Int#
object Issue396App {
// ^^^^^^^^^^^ definition minimized/Issue396App. object Issue396App
println(Issue396)
//^^^^^^^ reference scala/Predef.println(+1).
// ^^^^^^^^ reference minimized/Issue396.
Issue396.apply(42).copy(a = 41)
//^^^^^^^^ reference minimized/Issue396.
// ^^^^^ reference minimized/Issue396.apply().
// ^^^^ reference minimized/Issue396#copy().
// ^ reference minimized/Issue396#copy().(a)
Issue396.apply(42).productElement(0)
//^^^^^^^^ reference minimized/Issue396.
// ^^^^^ reference minimized/Issue396.apply().
// ^^^^^^^^^^^^^^ reference minimized/Issue396#productElement().
Issue396.apply(42).productElementName(0)
//^^^^^^^^ reference minimized/Issue396.
// ^^^^^ reference minimized/Issue396.apply().
// ^^^^^^^^^^^^^^^^^^ reference minimized/Issue396#productElementName().
}
17 changes: 17 additions & 0 deletions tests/snapshots/src/main/generated/minimized/Issue397.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package minimized
// ^^^^^^^^^ definition minimized/

class Issue397 {
// ^^^^^^^^ definition minimized/Issue397# class Issue397
// definition minimized/Issue397#`<init>`(). def this()
var blah = Set("abc")
// ^^^^ definition minimized/Issue397#blah(). var blah: Set[String]
// ^^^^ definition minimized/Issue397#`blah_=`(). var blah_=(x$1: Set[String]): Unit
// ^^^ reference scala/Predef.Set.
// reference scala/collection/IterableFactory#apply().
blah = Set.empty[String]
//^^^^ reference minimized/Issue397#`blah_=`().
// ^^^ reference scala/Predef.Set.
// ^^^^^ reference scala/collection/immutable/Set.empty().
// ^^^^^^ reference scala/Predef.String#
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,11 @@ package minimized

case class MinimizedCaseClass(value: String) {
// ^^^^^^^^^^^^^^^^^^ definition minimized/MinimizedCaseClass# case class MinimizedCaseClass(value: String)
// ^^^^^^^^^^^^^^^^^^ definition minimized/MinimizedCaseClass.apply(). def apply(value: String): MinimizedCaseClass
// ^^^^^^^^^^^^^^^^^^ definition minimized/MinimizedCaseClass#productElement(). def productElement(x$1: Int): Any
// ^^^^^^^^^^^^^^^^^^ definition minimized/MinimizedCaseClass. object MinimizedCaseClass
// ^^^^^^^^^^^^^^^^^^ definition minimized/MinimizedCaseClass#productElementName(). def productElementName(x$1: Int): String
// ^^^^^^^^^^^^^^^^^^ definition minimized/MinimizedCaseClass#copy(). def copy(value: String): MinimizedCaseClass
// definition minimized/MinimizedCaseClass#`<init>`(). def this(value: String)
// ^^^^^ definition minimized/MinimizedCaseClass#value. val value: String
// ^^^^^^ reference scala/Predef.String#
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ trait AstTransformer[I] extends Transformer[I] with JsVisitor[I, I]{

private[this] var key: String = null
// ^^^ definition ujson/AstTransformer#AstObjVisitor#key(). private[this] var key: String
// ^^^ definition ujson/AstTransformer#AstObjVisitor#`key_=`(). private[this] var key_=(x$1: String): Unit
// ^^^^^^ reference scala/Predef.String#
private[this] val vs = factory.newBuilder
// ^^ definition ujson/AstTransformer#AstObjVisitor#vs. private[this] val vs: Builder[(String, I), T]
Expand Down
10 changes: 10 additions & 0 deletions tests/snapshots/src/main/generated/ujson/Exceptions.scala
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,11 @@ sealed trait ParsingFailedException extends Exception

case class ParseException(clue: String, index: Int)
// ^^^^^^^^^^^^^^ definition ujson/ParseException# case class ParseException(clue: String, index: Int) extends Exception with ParsingFailedException
// ^^^^^^^^^^^^^^ definition ujson/ParseException#productElementName(). def productElementName(x$1: Int): String
// ^^^^^^^^^^^^^^ definition ujson/ParseException.apply(). def apply(clue: String, index: Int): ParseException
// ^^^^^^^^^^^^^^ definition ujson/ParseException. object ParseException
// ^^^^^^^^^^^^^^ definition ujson/ParseException#copy(). def copy(clue: String, index: Int): ParseException
// ^^^^^^^^^^^^^^ definition ujson/ParseException#productElement(). def productElement(x$1: Int): Any
// definition ujson/ParseException#`<init>`(). def this(clue: String, index: Int)
// ^^^^ definition ujson/ParseException#clue. val clue: String
// ^^^^^^ reference scala/Predef.String#
Expand All @@ -24,6 +29,11 @@ case class ParseException(clue: String, index: Int)

case class IncompleteParseException(msg: String)
// ^^^^^^^^^^^^^^^^^^^^^^^^ definition ujson/IncompleteParseException# case class IncompleteParseException(msg: String) extends Exception with ParsingFailedException
// ^^^^^^^^^^^^^^^^^^^^^^^^ definition ujson/IncompleteParseException#productElement(). def productElement(x$1: Int): Any
// ^^^^^^^^^^^^^^^^^^^^^^^^ definition ujson/IncompleteParseException.apply(). def apply(msg: String): IncompleteParseException
// ^^^^^^^^^^^^^^^^^^^^^^^^ definition ujson/IncompleteParseException#copy(). def copy(msg: String): IncompleteParseException
// ^^^^^^^^^^^^^^^^^^^^^^^^ definition ujson/IncompleteParseException#productElementName(). def productElementName(x$1: Int): String
// ^^^^^^^^^^^^^^^^^^^^^^^^ definition ujson/IncompleteParseException. object IncompleteParseException
// definition ujson/IncompleteParseException#`<init>`(). def this(msg: String)
// ^^^ definition ujson/IncompleteParseException#msg. val msg: String
// ^^^^^^ reference scala/Predef.String#
Expand Down
Loading

0 comments on commit 923efaf

Please sign in to comment.