(ctx context.Context, params *lsproto.VSOnAutoInsertParams)
| 10 | ) |
| 11 | |
| 12 | func (l *LanguageService) ProvideOnAutoInsert(ctx context.Context, params *lsproto.VSOnAutoInsertParams) (lsproto.VSOnAutoInsertResponse, error) { |
| 13 | if l.UserPreferences().EnableAutoClosingTags.IsFalse() { |
| 14 | return lsproto.VSOnAutoInsertResponse{}, nil |
| 15 | } |
| 16 | if params.VSCh != ">" { |
| 17 | return lsproto.VSOnAutoInsertResponse{}, nil |
| 18 | } |
| 19 | |
| 20 | _, sourceFile := l.getProgramAndFile(params.VSTextDocument.Uri) |
| 21 | position := l.converters.LineAndCharacterToPosition(sourceFile, params.VSPosition) |
| 22 | |
| 23 | token := astnav.FindPrecedingToken(sourceFile, int(position)) |
| 24 | if token == nil { |
| 25 | return lsproto.VSOnAutoInsertResponse{}, nil |
| 26 | } |
| 27 | |
| 28 | var closingText string |
| 29 | var element *ast.Node |
| 30 | if token.Kind == ast.KindGreaterThanToken && ast.IsJsxOpeningElement(token.Parent) { |
| 31 | element = token.Parent.Parent |
| 32 | } else if ast.IsJsxText(token) && ast.IsJsxElement(token.Parent) { |
| 33 | element = token.Parent |
| 34 | } |
| 35 | |
| 36 | if element != nil && isUnclosedTag(element.AsJsxElement()) { |
| 37 | tagNameNode := element.AsJsxElement().OpeningElement.TagName() |
| 38 | // Slight divergence from Strada - we don't use the verbatim text from the opening tag. |
| 39 | closingText = "</" + ast.EntityNameToString(tagNameNode, scanner.GetTextOfNode) + ">" |
| 40 | } else { |
| 41 | var fragment *ast.Node |
| 42 | if token.Kind == ast.KindGreaterThanToken && ast.IsJsxOpeningFragment(token.Parent) { |
| 43 | fragment = token.Parent.Parent |
| 44 | } else if ast.IsJsxText(token) && ast.IsJsxFragment(token.Parent) { |
| 45 | fragment = token.Parent |
| 46 | } |
| 47 | |
| 48 | if fragment != nil && isUnclosedFragment(fragment.AsJsxFragment()) { |
| 49 | closingText = "</>" |
| 50 | } |
| 51 | } |
| 52 | |
| 53 | if closingText == "" { |
| 54 | return lsproto.VSOnAutoInsertResponse{}, nil |
| 55 | } |
| 56 | |
| 57 | return lsproto.VSOnAutoInsertResponse{ |
| 58 | VSOnAutoInsertResponseItem: &lsproto.VSOnAutoInsertResponseItem{ |
| 59 | VSTextEditFormat: lsproto.InsertTextFormatSnippet, |
| 60 | VSTextEdit: &lsproto.TextEdit{ |
| 61 | Range: lsproto.Range{Start: params.VSPosition, End: params.VSPosition}, |
| 62 | // Tag names can contain `$` (valid JSX identifier characters), so |
| 63 | // escape the closing text to avoid being interpreted as a snippet |
| 64 | // placeholder/variable. |
| 65 | NewText: "$0" + escapeSnippetText(closingText), |
| 66 | }, |
| 67 | }, |
| 68 | }, nil |
| 69 | } |
no test coverage detected