Skip to content

Commit

Permalink
scheme: Add is_definition relationship (#88)
Browse files Browse the repository at this point in the history
  • Loading branch information
varungandhi-src authored Sep 23, 2022
1 parent b8dda7d commit ae09e3b
Show file tree
Hide file tree
Showing 21 changed files with 2,958 additions and 2,130 deletions.
3 changes: 3 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,6 @@ bindings/rust/src/scip.rs linguist-generated=true
bindings/haskell/src/Proto/**.hs linguist-generated=true
docs/scip.md linguist-generated=true
yarn.lock linguist-generated=true
cmd/tests/reprolang/src/grammar.json linguist-generated=true
cmd/tests/reprolang/src/node-types.json linguist-generated=true
cmd/tests/reprolang/src/parser.c linguist-generated=true
9 changes: 9 additions & 0 deletions bindings/go/scip/convert.go
Original file line number Diff line number Diff line change
Expand Up @@ -289,6 +289,15 @@ func (g *graph) emitRelationship(relationship *Relationship, rangeID, documentID
return []int{relationshipIDs.ReferenceResult}
}

if relationship.IsDefinition {
g.emitEdge("item", reader.Edge{
OutV: relationshipIDs.DefinitionResult,
InVs: []int{rangeID},
Document: documentID,
})
return []int{relationshipIDs.DefinitionResult}
}

return nil
}

Expand Down
394 changes: 210 additions & 184 deletions bindings/go/scip/scip.pb.go

Large diffs are not rendered by default.

1,358 changes: 713 additions & 645 deletions bindings/haskell/src/Proto/Scip.hs

Large diffs are not rendered by default.

6 changes: 6 additions & 0 deletions bindings/haskell/src/Proto/Scip_Fields.hs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1,481 changes: 768 additions & 713 deletions bindings/rust/src/generated/scip.rs

Large diffs are not rendered by default.

23 changes: 23 additions & 0 deletions bindings/typescript/scip.ts

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

21 changes: 16 additions & 5 deletions cmd/tests/reprolang/bindings/go/repro/ast.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,21 @@ import (
"github.com/sourcegraph/scip/bindings/go/scip"
)

type definitionStatement struct {
docstring string
name *identifier
type relationships struct {
implementsRelation *identifier
referencesRelation *identifier
typeDefinesRelation *identifier
definedByRelation *identifier
}

type definitionStatement struct {
docstring string
name *identifier
relations relationships
}

func (s *definitionStatement) relationIdentifiers() []*identifier {
return []*identifier{s.implementsRelation, s.referencesRelation, s.typeDefinesRelation}
func (r *relationships) identifiers() []*identifier {
return []*identifier{r.implementsRelation, r.referencesRelation, r.typeDefinesRelation, r.definedByRelation}
}

type referenceStatement struct {
Expand Down Expand Up @@ -53,6 +58,11 @@ func newIdentifier(s *reproSourceFile, n *sitter.Node) *identifier {
}
}

type relationshipsStatement struct {
name *identifier
relations relationships
}

func NewRangePositionFromNode(node *sitter.Node) *scip.Range {
return &scip.Range{
Start: scip.Position{
Expand All @@ -73,6 +83,7 @@ func (i *identifier) resolveSymbol(localScope *reproScope, context *reproContext
}
symbol, ok := scope.names[i.value]
if !ok {
fmt.Printf("scope.names = %v\n", scope.names)
symbol = "local ERROR_UNRESOLVED_SYMBOL"
}
i.symbol = symbol
Expand Down
62 changes: 41 additions & 21 deletions cmd/tests/reprolang/bindings/go/repro/namer.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,63 +9,83 @@ import (
// enterGlobalDefinitions inserts the names of the global symbols that are defined in this
// dependency into the provided global scope.
func (d *reproDependency) enterGlobalDefinitions(context *reproContext) {
enter := func(file *reproSourceFile, name *identifier) {
if name.isLocalSymbol() {
return
}
symbol := newGlobalSymbol(d.Package, file, name)
parsedSymbol, err := scip.ParseSymbol(symbol)
if err != nil {
return
}
newName := newGlobalName(context.pkg, parsedSymbol)
context.globalScope.names[newName] = symbol
}
for _, file := range d.Sources {
for _, definition := range file.definitions {
if definition.name.isLocalSymbol() {
continue
}
symbol := newGlobalSymbol(d.Package, file, definition)
parsedSymbol, err := scip.ParseSymbol(symbol)
if err != nil {
continue
}
name := newGlobalName(context.pkg, parsedSymbol)
context.globalScope.names[name] = symbol
enter(file, definition.name)
}
for _, relationship := range file.relationships {
enter(file, relationship.name)
}
}
}

// enterDefinitions inserts the names of the definitions into the appropriate scope (local symbols go into the local scope).
func (s *reproSourceFile) enterDefinitions(context *reproContext) {
for _, def := range s.definitions {
enter := func(name *identifier, defName *identifier) {
scope := context.globalScope
if def.name.isLocalSymbol() {
if name.isLocalSymbol() {
scope = s.localScope
}
var symbol string
if def.name.isLocalSymbol() {
symbol = fmt.Sprintf("local %s", def.name.value[len("local"):])
if name.isLocalSymbol() {
symbol = fmt.Sprintf("local %s", defName.value[len("local"):])
} else {
symbol = newGlobalSymbol(context.pkg, s, def)
symbol = newGlobalSymbol(context.pkg, s, defName)
}
name.symbol = symbol
scope.names[name.value] = symbol
}
for _, def := range s.definitions {
enter(def.name, def.name)
}
for _, rel := range s.relationships {
if rel.relations.definedByRelation != nil {
enter(rel.name, rel.relations.definedByRelation)
}
def.name.symbol = symbol
scope.names[def.name.value] = symbol
}
}

// resolveReferences updates the .symbol field for all names of reference identifiers.
func (s *reproSourceFile) resolveReferences(context *reproContext) {
for _, def := range s.definitions {
for _, ident := range def.relationIdentifiers() {
resolveIdents := func(rel relationships) {
for _, ident := range rel.identifiers() {
if ident == nil {
continue
}
ident.resolveSymbol(s.localScope, context)
}
}
for _, def := range s.definitions {
resolveIdents(def.relations)
}
for _, rel := range s.relationships {
resolveIdents(rel.relations)
}
for _, ref := range s.references {
ref.name.resolveSymbol(s.localScope, context)
}
}

// newGlobalSymbol returns an SCIP symbol for the given definition.
func newGlobalSymbol(pkg *scip.Package, document *reproSourceFile, definition *definitionStatement) string {
func newGlobalSymbol(pkg *scip.Package, document *reproSourceFile, name *identifier) string {
return fmt.Sprintf(
"reprolang repro_manager %v %v %v/%v",
pkg.Name,
pkg.Version,
document.Source.RelativePath,
definition.name.value,
name.value,
)
}

Expand Down
29 changes: 20 additions & 9 deletions cmd/tests/reprolang/bindings/go/repro/parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,28 +27,39 @@ func (s *reproSourceFile) loadStatements() {
continue
}
switch child.Type() {
case "definition_statement":
case "relationships_statement", "definition_statement":
docstring := ""
docstringNode := child.ChildByFieldName("docstring")
if docstringNode != nil {
docstring = s.nodeText(docstringNode)[len("# doctring:"):]
}
statement := &definitionStatement{
docstring: docstring,
name: newIdentifier(s, child.ChildByFieldName("name")),
}
name := newIdentifier(s, child.ChildByFieldName("name"))
relations := relationships{}
for i := uint32(0); i < child.NamedChildCount(); i++ {
relation := child.NamedChild(int(i))
switch relation.Type() {
case "implementation_relation":
statement.implementsRelation = newIdentifier(s, relation.ChildByFieldName("name"))
relations.implementsRelation = newIdentifier(s, relation.ChildByFieldName("name"))
case "type_definition_relation":
statement.typeDefinesRelation = newIdentifier(s, relation.ChildByFieldName("name"))
relations.typeDefinesRelation = newIdentifier(s, relation.ChildByFieldName("name"))
case "references_relation":
statement.referencesRelation = newIdentifier(s, relation.ChildByFieldName("name"))
relations.referencesRelation = newIdentifier(s, relation.ChildByFieldName("name"))
case "defined_by_relation":
relations.definedByRelation = newIdentifier(s, relation.ChildByFieldName("name"))
}
}
s.definitions = append(s.definitions, statement)
if child.Type() == "definition_statement" {
s.definitions = append(s.definitions, &definitionStatement{
docstring: docstring,
name: name,
relations: relations,
})
} else {
s.relationships = append(s.relationships, &relationshipsStatement{
name: name,
relations: relations,
})
}
case "reference_statement":
s.references = append(s.references, &referenceStatement{
name: newIdentifier(s, child.ChildByFieldName("name")),
Expand Down
Loading

0 comments on commit ae09e3b

Please sign in to comment.