vendor tsgo

This commit is contained in:
2026-07-09 16:50:43 -04:00
parent c06ea2e5a4
commit 98978e4930
5804 changed files with 1556156 additions and 101 deletions

View File

@@ -0,0 +1,99 @@
package ls
import (
"context"
"github.com/microsoft/typescript-go/internal/ast"
"github.com/microsoft/typescript-go/internal/astnav"
"github.com/microsoft/typescript-go/internal/lsp/lsproto"
"github.com/microsoft/typescript-go/internal/scanner"
)
func (l *LanguageService) ProvideOnAutoInsert(ctx context.Context, params *lsproto.VSOnAutoInsertParams) (lsproto.VSOnAutoInsertResponse, error) {
if l.UserPreferences().EnableAutoClosingTags.IsFalse() {
return lsproto.VSOnAutoInsertResponse{}, nil
}
if params.VSCh != ">" {
return lsproto.VSOnAutoInsertResponse{}, nil
}
_, sourceFile := l.getProgramAndFile(params.VSTextDocument.Uri)
position := l.converters.LineAndCharacterToPosition(sourceFile, params.VSPosition)
token := astnav.FindPrecedingToken(sourceFile, int(position))
if token == nil {
return lsproto.VSOnAutoInsertResponse{}, nil
}
var closingText string
var element *ast.Node
if token.Kind == ast.KindGreaterThanToken && ast.IsJsxOpeningElement(token.Parent) {
element = token.Parent.Parent
} else if ast.IsJsxText(token) && ast.IsJsxElement(token.Parent) {
element = token.Parent
}
if element != nil && isUnclosedTag(element.AsJsxElement()) {
tagNameNode := element.AsJsxElement().OpeningElement.TagName()
// Slight divergence from Strada - we don't use the verbatim text from the opening tag.
closingText = "</" + ast.EntityNameToString(tagNameNode, scanner.GetTextOfNode) + ">"
} else {
var fragment *ast.Node
if token.Kind == ast.KindGreaterThanToken && ast.IsJsxOpeningFragment(token.Parent) {
fragment = token.Parent.Parent
} else if ast.IsJsxText(token) && ast.IsJsxFragment(token.Parent) {
fragment = token.Parent
}
if fragment != nil && isUnclosedFragment(fragment.AsJsxFragment()) {
closingText = "</>"
}
}
if closingText == "" {
return lsproto.VSOnAutoInsertResponse{}, nil
}
return lsproto.VSOnAutoInsertResponse{
VSOnAutoInsertResponseItem: &lsproto.VSOnAutoInsertResponseItem{
VSTextEditFormat: lsproto.InsertTextFormatSnippet,
VSTextEdit: &lsproto.TextEdit{
Range: lsproto.Range{Start: params.VSPosition, End: params.VSPosition},
// Tag names can contain `$` (valid JSX identifier characters), so
// escape the closing text to avoid being interpreted as a snippet
// placeholder/variable.
NewText: "$0" + escapeSnippetText(closingText),
},
},
}, nil
}
func isUnclosedTag(node *ast.JsxElement) bool {
openingElement := node.OpeningElement
closingElement := node.ClosingElement
if !ast.TagNamesAreEquivalent(openingElement.TagName(), closingElement.TagName()) {
return true
}
parent := node.Parent
if ast.IsJsxElement(parent) {
parent := parent.AsJsxElement()
return ast.TagNamesAreEquivalent(openingElement.TagName(), parent.OpeningElement.TagName()) && isUnclosedTag(parent)
}
return false
}
func isUnclosedFragment(node *ast.JsxFragment) bool {
closingFragment := node.ClosingFragment
if closingFragment.Flags&ast.NodeFlagsThisNodeHasError != 0 {
return true
}
parent := node.Parent
if ast.IsJsxFragment(parent) && isUnclosedFragment(parent.AsJsxFragment()) {
return true
}
return false
}