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 @@ -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