-
Notifications
You must be signed in to change notification settings - Fork 33
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge remote-tracking branch 'upstream/master'
- Loading branch information
Showing
8 changed files
with
457 additions
and
5 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
package lsp | ||
|
||
import ( | ||
"context" | ||
|
||
"github.com/nokia/ntt/internal/lsp/protocol" | ||
"github.com/nokia/ntt/ttcn3" | ||
"github.com/nokia/ntt/ttcn3/syntax" | ||
) | ||
|
||
func (s *Server) inlayHint(ctx context.Context, params *protocol.InlayHintParams) ([]protocol.InlayHint, error) { | ||
if !s.serverConfig.InlayHintEnabled { | ||
return nil, nil | ||
} | ||
|
||
file := string(params.TextDocument.URI) | ||
tree := ttcn3.ParseFile(file) | ||
begin := tree.PosFor(int(params.Range.Start.Line)+1, int(params.Range.Start.Character+1)) | ||
end := tree.PosFor(int(params.Range.End.Line+1), int(params.Range.End.Character+1)) | ||
return ProcessInlayHint(tree, &s.db, begin, end), nil | ||
} | ||
|
||
func ProcessInlayHint(tree *ttcn3.Tree, db *ttcn3.DB, begin int, end int) []protocol.InlayHint { | ||
var hints []protocol.InlayHint | ||
|
||
tree.Inspect(func(n syntax.Node) bool { | ||
if n == nil || n.End() < begin || end < n.Pos() { | ||
return false | ||
} | ||
|
||
if callExpr, ok := n.(*syntax.CallExpr); ok { | ||
|
||
for _, decl := range tree.LookupWithDB(callExpr.Fun, db) { | ||
|
||
if params := getDeclarationParams(decl.Node); params != nil { | ||
|
||
for idx, arg := range callExpr.Args.List { | ||
|
||
// Stop processing further arguments after the first assignment notation. | ||
// Value arguments are not allowed: ES 201 873-1, 5.4.2, Restrictions, point o). | ||
if binaryExpr, ok := arg.(*syntax.BinaryExpr); ok { | ||
if binaryExpr.Op.String() == ":=" { | ||
break | ||
} | ||
} | ||
|
||
name := params.List[idx].Name.Tok.String() | ||
lbl := protocol.InlayHintLabelPart{Value: name + " :="} | ||
pos := syntax.Begin(arg) | ||
pos.Line -= 1 | ||
pos.Column -= 1 | ||
ppos := protocol.Position{Line: uint32(pos.Line), Character: uint32(pos.Column)} | ||
hint := protocol.InlayHint{ | ||
Position: ppos, | ||
Label: []protocol.InlayHintLabelPart{lbl}, | ||
Kind: protocol.Parameter, | ||
PaddingRight: true, | ||
} | ||
hints = append(hints, hint) | ||
|
||
} | ||
|
||
// Stop after the first declaration is processed. | ||
break | ||
} | ||
} | ||
} | ||
return true | ||
}) | ||
return hints | ||
} | ||
|
||
func getDeclarationParams(node syntax.Node) *syntax.FormalPars { | ||
if decl, ok := node.(*syntax.FuncDecl); ok { | ||
return decl.Params | ||
} | ||
if decl, ok := node.(*syntax.TemplateDecl); ok { | ||
return decl.Params | ||
} | ||
return nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,115 @@ | ||
package lsp_test | ||
|
||
import ( | ||
"fmt" | ||
"testing" | ||
|
||
"github.com/nokia/ntt/internal/fs" | ||
"github.com/nokia/ntt/internal/lsp" | ||
"github.com/nokia/ntt/internal/lsp/protocol" | ||
"github.com/nokia/ntt/ttcn3" | ||
"github.com/stretchr/testify/assert" | ||
) | ||
|
||
type Hint struct { | ||
Line uint32 | ||
Char uint32 | ||
Label string | ||
} | ||
|
||
func TestInlayHintForFunction(t *testing.T) { | ||
actual := testInlayHint(t, nil, ` | ||
module Test { | ||
function func(integer a := 0, integer b := 0, integer c := 0) {} | ||
function test() { | ||
func(1, 2, 3) | ||
func(1, | ||
2, | ||
3) | ||
func(a := 1, b := 2, c := 3) | ||
func(1 + 2) | ||
func(1, 2, c := 3) | ||
} | ||
}`) | ||
|
||
assert.Equal(t, []Hint{ | ||
// All parameters in the same line. | ||
{Line: 4, Char: 13, Label: "a :="}, | ||
{Line: 4, Char: 16, Label: "b :="}, | ||
{Line: 4, Char: 19, Label: "c :="}, | ||
// Parameters spanning multiple lines. | ||
{Line: 5, Char: 13, Label: "a :="}, | ||
{Line: 6, Char: 13, Label: "b :="}, | ||
{Line: 7, Char: 13, Label: "c :="}, | ||
// Binary expression parameter. | ||
{Line: 8, Char: 13, Label: "a :="}, | ||
// Mixed assignment / value list notation. | ||
{Line: 9, Char: 13, Label: "a :="}, | ||
{Line: 9, Char: 14, Label: "b :="}, | ||
}[0], actual[0]) | ||
} | ||
|
||
func TestInlayHintForTemplate(t *testing.T) { | ||
actual := testInlayHint(t, nil, ` | ||
module Test { | ||
template integer templ(integer x, integer y) := (x .. y) | ||
function test() { | ||
var template integer t := templ(2, 3) | ||
} | ||
}`) | ||
|
||
assert.Equal(t, []Hint{ | ||
{Line: 4, Char: 40, Label: "x :="}, | ||
{Line: 6, Char: 43, Label: "y :="}, | ||
}[0], actual[0]) | ||
} | ||
|
||
func TestInlayHintNestedCalls(t *testing.T) { | ||
actual := testInlayHint(t, nil, ` | ||
module Test { | ||
function foo(integer a) return integer { return 1; } | ||
function bar(integer b) return integer { return 1; } | ||
function baz(integer c) return integer { return 1; } | ||
function test() { | ||
foo(bar(baz(1))) | ||
} | ||
}`) | ||
|
||
assert.Equal(t, []Hint{ | ||
{Line: 6, Char: 12, Label: "a :="}, | ||
{Line: 6, Char: 16, Label: "b :="}, | ||
{Line: 6, Char: 20, Label: "c :="}, | ||
}[0], actual[0]) | ||
} | ||
|
||
func testInlayHint(t *testing.T, rng *protocol.Range, text string) []Hint { | ||
t.Helper() | ||
|
||
file := fmt.Sprintf("%s.ttcn3", t.Name()) | ||
fs.SetContent(file, []byte(text)) | ||
tree := ttcn3.ParseFile(file) | ||
if tree.Err != nil { | ||
t.Fatal(tree.Err) | ||
} | ||
|
||
// Build index to for tree.Lookup to resolve imported symbols. | ||
db := &ttcn3.DB{} | ||
db.Index(file) | ||
|
||
begin := tree.Pos() | ||
end := tree.End() | ||
if rng != nil { | ||
begin = tree.PosFor(int(rng.Start.Line), int(rng.Start.Character)) | ||
end = tree.PosFor(int(rng.End.Line), int(rng.End.Character)) | ||
} | ||
|
||
var hints []Hint | ||
for _, h := range lsp.ProcessInlayHint(tree, db, begin, end) { | ||
hints = append(hints, Hint{ | ||
Line: h.Position.Line, | ||
Char: h.Position.Character, | ||
Label: h.Label[0].Value, | ||
}) | ||
} | ||
return hints | ||
} |
Oops, something went wrong.