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
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# scip-dart

Experimental spike on a [scip](https://github.com/sourcegraph/scip) indexer for [dart](https://github.com/dart-lang)
Implementation of a [scip](https://github.com/sourcegraph/scip) indexer for [dart](https://github.com/dart-lang)

Designed to be a replacement for [lsif_indexer](https://github.com/Workiva/lsif_indexer), with better coverage and reliability

Expand Down
53 changes: 53 additions & 0 deletions lib/src/relationship_generator.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:scip_dart/src/gen/scip.pbserver.dart';
import 'package:scip_dart/src/symbol_generator.dart';

List<Relationship>? relationshipsFor(
Declaration node,
Element element,
SymbolGenerator symbolGenerator,
) {
// Only classes have relationships. Mixins and enums do not support
// inheritance themselves and therefore do not have any relationships
// to define.
if (element is ClassElement) {
// All things inherit from Object, if they have one supertype
// there are no relationships
if (element.allSupertypes.length <= 1) return null;

return element.allSupertypes
.where((type) => !type.isDartCoreObject)
.map((type) => Relationship(
symbol: symbolGenerator.symbolFor(type.element),
isImplementation: true,
))
Comment on lines +20 to +24
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If a class has any supertypes, all of those supertypes (allSupertypes refers to every super type, including super types of super types) are relationships

.toList();
}

// Since mixins do not support inheritance, we only care about
// methods that exist on classes
if (node is MethodDeclaration && node.parent is ClassDeclaration) {
final parentNode = node.parent as ClassDeclaration;
final parentElement = parentNode.declaredElement as ClassElement;

// retrieve all of the methods and accessors of every parent type that
// has the same name of [node]. These are the elements that this [node]
// are overriding
final referencingElements = parentElement.allSupertypes
.map((type) => [...type.methods, ...type.accessors])
.expand((type) => type)
.where((type) => type.name == node.name.toString());

if (referencingElements.isNotEmpty) {
return referencingElements
.map((type) => Relationship(
symbol: symbolGenerator.symbolFor(type),
isImplementation: true,
isReference: true))
.toList();
}
}

return null;
}
14 changes: 11 additions & 3 deletions lib/src/scip_visitor.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ import 'package:package_config/package_config.dart';
import 'package:pubspec_parse/pubspec_parse.dart';
import 'package:scip_dart/src/metadata.dart';
import 'package:scip_dart/src/gen/scip.pb.dart';
import 'package:scip_dart/src/symbol.dart';
import 'package:scip_dart/src/relationship_generator.dart';
import 'package:scip_dart/src/symbol_generator.dart';
import 'package:scip_dart/src/utils.dart';

List<SymbolInformation> globalExternalSymbols = [];
Expand Down Expand Up @@ -61,7 +62,10 @@ class ScipVisitor extends GeneralizingAstVisitor {
if (node.declaredElement == null) return;

final element = node.declaredElement!;
_registerAsDefinition(element);
_registerAsDefinition(
element,
relationships: relationshipsFor(node, element, _symbolGenerator),
);
}

void _visitNormalFormalParameter(NormalFormalParameter node) {
Expand Down Expand Up @@ -160,13 +164,17 @@ class ScipVisitor extends GeneralizingAstVisitor {
///
/// This adds both a symbol, and an occurrence for the element and it's
/// name
void _registerAsDefinition(Element element) {
void _registerAsDefinition(
Element element, {
List<Relationship>? relationships,
}) {
final symbol = _symbolGenerator.symbolFor(element);
if (symbol != null) {
final meta = getSymbolMetadata(element);
symbols.add(SymbolInformation(
symbol: symbol,
documentation: meta.documentation,
relationships: relationships,
));

occurrences.add(Occurrence(
Expand Down
5 changes: 1 addition & 4 deletions lib/src/symbol.dart → lib/src/symbol_generator.dart
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,7 @@ class SymbolGenerator {
/// Use []
Map<Element, String> _localElementRegistry = {};

SymbolGenerator(
this._packageConfig,
this._pubspec,
);
SymbolGenerator(this._packageConfig, this._pubspec);

/// For a given `Element` returns the scip symbol form.
///
Expand Down
19 changes: 19 additions & 0 deletions snapshots/input/basic-project/lib/relationships.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
abstract class Mammal {
String get hierarchy;
}

abstract class Animal extends Mammal {
String sound() => 'NOISE!';
}

mixin SwimAction {
void execute() => print('swimming...');
}

class Dog extends Animal with SwimAction {
@override
String sound() => 'woof';

@override
String get hierarchy => 'dog.animal.mammal';
}
2 changes: 2 additions & 0 deletions snapshots/output/basic-project/lib/more.dart
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
class Animal with SleepMixin {
// ^^^^^^ definition scip-dart pub dart_test 1.0.0 lib/more.dart/Animal#
// documentation ```dart
// relationship scip-dart pub dart_test 1.0.0 lib/more.dart/SleepMixin# implementation
// ^^^^^^^^^^ reference scip-dart pub dart_test 1.0.0 lib/more.dart/SleepMixin#
String name;
// ^^^^^^ reference scip-dart pub dart:core 2.18.0 dart:core/string.dart/String#
Expand Down Expand Up @@ -102,6 +103,7 @@
// ^^^^^^ reference scip-dart pub dart:core 2.18.0 dart:core/string.dart/String#
// ^^^^^^^^ definition scip-dart pub dart_test 1.0.0 lib/more.dart/Animal#toString().
// documentation ```dart
// relationship scip-dart pub dart:core 2.18.0 dart:core/object.dart/Object#toString(). implementation reference
return '$name the $type';
// ^^^^ reference scip-dart pub dart_test 1.0.0 lib/more.dart/Animal#name.
// ^^^^ reference scip-dart pub dart_test 1.0.0 lib/more.dart/Animal#type.
Expand Down
54 changes: 54 additions & 0 deletions snapshots/output/basic-project/lib/relationships.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
abstract class Mammal {
// definition scip-dart pub dart_test 1.0.0 lib/relationships.dart/
// ^^^^^^ definition scip-dart pub dart_test 1.0.0 lib/relationships.dart/Mammal#
// documentation ```dart
String get hierarchy;
// ^^^^^^ reference scip-dart pub dart:core 2.18.0 dart:core/string.dart/String#
// ^^^^^^^^^ definition scip-dart pub dart_test 1.0.0 lib/relationships.dart/Mammal#hierarchy.
// documentation ```dart
}

abstract class Animal extends Mammal {
// ^^^^^^ definition scip-dart pub dart_test 1.0.0 lib/relationships.dart/Animal#
// documentation ```dart
// relationship scip-dart pub dart_test 1.0.0 lib/relationships.dart/Mammal# implementation
// ^^^^^^ reference scip-dart pub dart_test 1.0.0 lib/relationships.dart/Mammal#
String sound() => 'NOISE!';
// ^^^^^^ reference scip-dart pub dart:core 2.18.0 dart:core/string.dart/String#
// ^^^^^ definition scip-dart pub dart_test 1.0.0 lib/relationships.dart/Animal#sound().
// documentation ```dart
}

mixin SwimAction {
// ^^^^^^^^^^ definition scip-dart pub dart_test 1.0.0 lib/relationships.dart/SwimAction#
// documentation ```dart
void execute() => print('swimming...');
// ^^^^^^^ definition scip-dart pub dart_test 1.0.0 lib/relationships.dart/SwimAction#execute().
// documentation ```dart
// ^^^^^ reference scip-dart pub dart:core 2.18.0 dart:core/print.dart/print().
}

class Dog extends Animal with SwimAction {
// ^^^ definition scip-dart pub dart_test 1.0.0 lib/relationships.dart/Dog#
// documentation ```dart
// relationship scip-dart pub dart_test 1.0.0 lib/relationships.dart/Animal# implementation
// relationship scip-dart pub dart_test 1.0.0 lib/relationships.dart/Mammal# implementation
// relationship scip-dart pub dart_test 1.0.0 lib/relationships.dart/SwimAction# implementation
// ^^^^^^ reference scip-dart pub dart_test 1.0.0 lib/relationships.dart/Animal#
// ^^^^^^^^^^ reference scip-dart pub dart_test 1.0.0 lib/relationships.dart/SwimAction#
@override
// ^^^^^^^^ reference scip-dart pub dart:core 2.18.0 dart:core/annotations.dart/override.
String sound() => 'woof';
// ^^^^^^ reference scip-dart pub dart:core 2.18.0 dart:core/string.dart/String#
// ^^^^^ definition scip-dart pub dart_test 1.0.0 lib/relationships.dart/Dog#sound().
// documentation ```dart
// relationship scip-dart pub dart_test 1.0.0 lib/relationships.dart/Animal#sound(). implementation reference

@override
// ^^^^^^^^ reference scip-dart pub dart:core 2.18.0 dart:core/annotations.dart/override.
String get hierarchy => 'dog.animal.mammal';
// ^^^^^^ reference scip-dart pub dart:core 2.18.0 dart:core/string.dart/String#
// ^^^^^^^^^ definition scip-dart pub dart_test 1.0.0 lib/relationships.dart/Dog#hierarchy.
// documentation ```dart
// relationship scip-dart pub dart_test 1.0.0 lib/relationships.dart/Mammal#hierarchy. implementation reference
}