diff --git a/internal/ast/ast.go b/internal/ast/ast.go index 37629b9cbf..ec9ae5cce2 100644 --- a/internal/ast/ast.go +++ b/internal/ast/ast.go @@ -10940,6 +10940,8 @@ func (node *SourceFile) BindOnce(bind func()) { }) } +// Gets a token from the file's token cache, or creates it if it does not already exist. +// This function should NOT be used for creating synthetic tokens that are not in the file in the first place. func (node *SourceFile) GetOrCreateToken( kind Kind, pos int, diff --git a/internal/ls/change/tracker.go b/internal/ls/change/tracker.go index cbb80f046d..e9de6aec88 100644 --- a/internal/ls/change/tracker.go +++ b/internal/ls/change/tracker.go @@ -178,7 +178,9 @@ func (t *Tracker) InsertNodeBefore(sourceFile *ast.SourceFile, before *ast.Node, // InsertModifierBefore inserts a modifier token (like 'type') before a node with a trailing space. func (t *Tracker) InsertModifierBefore(sourceFile *ast.SourceFile, modifier ast.Kind, before *ast.Node) { pos := astnav.GetStartOfNode(before, sourceFile, false) - token := sourceFile.GetOrCreateToken(modifier, pos, pos, before.Parent, ast.TokenFlagsNone) + token := t.NewToken(modifier) + token.Loc = core.NewTextRange(pos, pos) + token.Parent = before.Parent t.InsertNodeAt(sourceFile, core.TextPos(pos), token, NodeOptions{Suffix: " "}) } @@ -260,9 +262,12 @@ func (t *Tracker) endPosForInsertNodeAfter(sourceFile *ast.SourceFile, after *as // check if previous statement ends with semicolon // if not - insert semicolon to preserve the code from changing the meaning due to ASI endPos := t.converters.PositionToLineAndCharacter(sourceFile, core.TextPos(after.End())) + semicolon := t.NewToken(ast.KindSemicolonToken) + semicolon.Loc = core.NewTextRange(after.End(), after.End()) + semicolon.Parent = after.Parent t.ReplaceRange(sourceFile, lsproto.Range{Start: endPos, End: endPos}, - sourceFile.GetOrCreateToken(ast.KindSemicolonToken, after.End(), after.End(), after.Parent, ast.TokenFlagsNone), + semicolon, NodeOptions{}, ) } @@ -347,7 +352,10 @@ func (t *Tracker) InsertNodeInListAfter(sourceFile *ast.SourceFile, after *ast.N // insert separator immediately following the 'after' node to preserve comments in trailing trivia // !!! formatcontext - t.ReplaceRange(sourceFile, lsproto.Range{Start: end, End: end}, sourceFile.GetOrCreateToken(separator, after.End(), after.End()+len(separatorString), after.Parent, ast.TokenFlagsNone), NodeOptions{}) + separatorToken := t.NewToken(separator) + separatorToken.Loc = core.NewTextRange(after.End(), after.End()+len(separatorString)) + separatorToken.Parent = after.Parent + t.ReplaceRange(sourceFile, lsproto.Range{Start: end, End: end}, separatorToken, NodeOptions{}) // use the same indentation as 'after' item indentation := format.FindFirstNonWhitespaceColumn(afterStartLinePosition, afterStart, sourceFile, t.formatSettings) // insert element before the line break on the line that contains 'after' element