-
Notifications
You must be signed in to change notification settings - Fork 663
Folding Ranges implementation #1326
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from 1 commit
f1616c3
c32bbb7
c691b7d
02723d4
1938da6
86df138
37babb6
18a2737
b7b020f
dd3f93d
7435726
3527adb
3a1f476
08fbeda
30f9df7
f68abaa
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -232,22 +232,20 @@ func addOutliningForLeadingCommentsForPos(pos int, sourceFile *ast.SourceFile, l | |
combineAndAddMultipleSingleLineComments := func() *lsproto.FoldingRange { | ||
// Only outline spans of two or more consecutive single line comments | ||
if singleLineCommentCount > 1 { | ||
|
||
return createFoldingRangeFromBounds( | ||
firstSingleLineCommentStart, lastSingleLineCommentEnd, foldingRangeKindComment, sourceFile, l) | ||
return createFoldingRangeFromBounds(firstSingleLineCommentStart, lastSingleLineCommentEnd, foldingRangeKindComment, sourceFile, l) | ||
} | ||
return nil | ||
} | ||
|
||
sourceText := sourceFile.Text() | ||
comments(func(comment ast.CommentRange) bool { | ||
pos := comment.Pos() | ||
end := comment.End() | ||
commentPos := comment.Pos() | ||
commentEnd := comment.End() | ||
// cancellationToken.throwIfCancellationRequested(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should these be rewritten in terms of |
||
switch comment.Kind { | ||
case ast.KindSingleLineCommentTrivia: | ||
// never fold region delimiters into single-line comment regions | ||
commentText := sourceText[pos:end] | ||
commentText := sourceText[commentPos:commentEnd] | ||
if parseRegionDelimiter(commentText) != nil { | ||
comments := combineAndAddMultipleSingleLineComments() | ||
if comments != nil { | ||
|
@@ -260,17 +258,17 @@ func addOutliningForLeadingCommentsForPos(pos int, sourceFile *ast.SourceFile, l | |
// For single line comments, combine consecutive ones (2 or more) into | ||
// a single span from the start of the first till the end of the last | ||
if singleLineCommentCount == 0 { | ||
firstSingleLineCommentStart = pos | ||
firstSingleLineCommentStart = commentPos | ||
} | ||
lastSingleLineCommentEnd = end | ||
lastSingleLineCommentEnd = commentEnd | ||
singleLineCommentCount++ | ||
break | ||
case ast.KindMultiLineCommentTrivia: | ||
comments := combineAndAddMultipleSingleLineComments() | ||
if comments != nil { | ||
foldingRange = append(foldingRange, comments) | ||
} | ||
foldingRange = append(foldingRange, createFoldingRangeFromBounds(pos, end, foldingRangeKindComment, sourceFile, l)) | ||
foldingRange = append(foldingRange, createFoldingRangeFromBounds(commentPos, commentEnd, foldingRangeKindComment, sourceFile, l)) | ||
singleLineCommentCount = 0 | ||
break | ||
default: | ||
|
@@ -321,43 +319,43 @@ func getOutliningSpanForNode(n *ast.Node, sourceFile *ast.SourceFile, l *Languag | |
// to be the entire span of the parent. | ||
switch n.Parent.Kind { | ||
case ast.KindDoStatement, ast.KindForInStatement, ast.KindForOfStatement, ast.KindForStatement, ast.KindIfStatement, ast.KindWhileStatement, ast.KindWithStatement, ast.KindCatchClause: | ||
return spanForNode(n, n.Parent, ast.KindOpenBraceToken, true /*useFullStart */, sourceFile, l) | ||
return spanForNode(n, ast.KindOpenBraceToken, true /*useFullStart */, sourceFile, l) | ||
case ast.KindTryStatement: | ||
// Could be the try-block, or the finally-block. | ||
tryStatement := n.Parent.AsTryStatement() | ||
if tryStatement.TryBlock == n { | ||
return spanForNode(n, n.Parent, ast.KindOpenBraceToken, true /*useFullStart */, sourceFile, l) | ||
return spanForNode(n, ast.KindOpenBraceToken, true /*useFullStart */, sourceFile, l) | ||
} else if tryStatement.FinallyBlock == n { | ||
node := findChildOfKind(n.Parent, ast.KindFinallyKeyword, sourceFile) | ||
if node != nil { | ||
return spanForNode(n, node, ast.KindOpenBraceToken, true /*useFullStart */, sourceFile, l) | ||
return spanForNode(n, ast.KindOpenBraceToken, true /*useFullStart */, sourceFile, l) | ||
} | ||
} | ||
default: | ||
// Block was a standalone block. In this case we want to only collapse | ||
// the span of the block, independent of any parent span. | ||
return createFoldingRange(l.createLspRangeFromNode(n, sourceFile), "", nil, "") | ||
return createFoldingRange(l.createLspRangeFromNode(n, sourceFile), "", "") | ||
} | ||
case ast.KindModuleBlock: | ||
return spanForNode(n, n.Parent, ast.KindOpenBraceToken, true /*useFullStart */, sourceFile, l) | ||
return spanForNode(n, ast.KindOpenBraceToken, true /*useFullStart */, sourceFile, l) | ||
case ast.KindClassDeclaration, ast.KindClassExpression, ast.KindInterfaceDeclaration, ast.KindEnumDeclaration, ast.KindCaseBlock, ast.KindTypeLiteral, ast.KindObjectBindingPattern: | ||
return spanForNode(n, n, ast.KindOpenBraceToken, true /*useFullStart */, sourceFile, l) | ||
return spanForNode(n, ast.KindOpenBraceToken, true /*useFullStart */, sourceFile, l) | ||
case ast.KindTupleType: | ||
return spanForNode(n, n, ast.KindOpenBracketToken, !ast.IsTupleTypeNode(n.Parent) /*useFullStart */, sourceFile, l) | ||
return spanForNode(n, ast.KindOpenBracketToken, !ast.IsTupleTypeNode(n.Parent) /*useFullStart */, sourceFile, l) | ||
case ast.KindCaseClause, ast.KindDefaultClause: | ||
return spanForNodeArray(n.AsCaseOrDefaultClause().Statements, sourceFile, l) | ||
case ast.KindObjectLiteralExpression: | ||
return spanForNode(n, n, ast.KindOpenBraceToken, !ast.IsArrayLiteralExpression(n.Parent) && !ast.IsCallExpression(n.Parent) /*useFullStart */, sourceFile, l) | ||
return spanForNode(n, ast.KindOpenBraceToken, !ast.IsArrayLiteralExpression(n.Parent) && !ast.IsCallExpression(n.Parent) /*useFullStart */, sourceFile, l) | ||
case ast.KindArrayLiteralExpression: | ||
return spanForNode(n, n, ast.KindOpenBracketToken, !ast.IsArrayLiteralExpression(n.Parent) && !ast.IsCallExpression(n.Parent) /*useFullStart */, sourceFile, l) | ||
return spanForNode(n, ast.KindOpenBracketToken, !ast.IsArrayLiteralExpression(n.Parent) && !ast.IsCallExpression(n.Parent) /*useFullStart */, sourceFile, l) | ||
case ast.KindJsxElement, ast.KindJsxFragment: | ||
return spanForJSXElement(n, sourceFile, l) | ||
case ast.KindJsxSelfClosingElement, ast.KindJsxOpeningElement: | ||
return spanForJSXAttributes(n, sourceFile, l) | ||
case ast.KindTemplateExpression, ast.KindNoSubstitutionTemplateLiteral: | ||
return spanForTemplateLiteral(n, sourceFile, l) | ||
case ast.KindArrayBindingPattern: | ||
return spanForNode(n, n, ast.KindOpenBracketToken, !ast.IsBindingElement(n.Parent) /*useFullStart */, sourceFile, l) | ||
return spanForNode(n, ast.KindOpenBracketToken, !ast.IsBindingElement(n.Parent) /*useFullStart */, sourceFile, l) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. A lot of these |
||
case ast.KindArrowFunction: | ||
return spanForArrowFunction(n, sourceFile, l) | ||
case ast.KindCallExpression: | ||
|
@@ -387,7 +385,7 @@ func spanForImportExportElements(node *ast.Node, sourceFile *ast.SourceFile, l * | |
if openToken == nil || closeToken == nil || printer.PositionsAreOnSameLine(openToken.Pos(), closeToken.Pos(), sourceFile) { | ||
return nil | ||
} | ||
return rangeBetweenTokens(openToken, closeToken, node, sourceFile, false /*useFullStart*/, l) | ||
return rangeBetweenTokens(openToken, closeToken, sourceFile, false /*useFullStart*/, l) | ||
} | ||
|
||
func spanForParenthesizedExpression(node *ast.Node, sourceFile *ast.SourceFile, l *LanguageService) *lsproto.FoldingRange { | ||
|
@@ -396,7 +394,7 @@ func spanForParenthesizedExpression(node *ast.Node, sourceFile *ast.SourceFile, | |
return nil | ||
} | ||
textRange := l.createLspRangeFromBounds(start, node.End(), sourceFile) | ||
return createFoldingRange(textRange, "", l.createLspRangeFromNode(node, sourceFile), "") | ||
return createFoldingRange(textRange, "", "") | ||
} | ||
|
||
func spanForCallExpression(node *ast.Node, sourceFile *ast.SourceFile, l *LanguageService) *lsproto.FoldingRange { | ||
|
@@ -409,7 +407,7 @@ func spanForCallExpression(node *ast.Node, sourceFile *ast.SourceFile, l *Langua | |
return nil | ||
} | ||
|
||
return rangeBetweenTokens(openToken, closeToken, node, sourceFile, true /*useFullStart*/, l) | ||
return rangeBetweenTokens(openToken, closeToken, sourceFile, true /*useFullStart*/, l) | ||
} | ||
|
||
func spanForArrowFunction(node *ast.Node, sourceFile *ast.SourceFile, l *LanguageService) *lsproto.FoldingRange { | ||
|
@@ -418,7 +416,7 @@ func spanForArrowFunction(node *ast.Node, sourceFile *ast.SourceFile, l *Languag | |
return nil | ||
} | ||
textRange := l.createLspRangeFromBounds(arrowFunctionNode.Body.Pos(), arrowFunctionNode.Body.End(), sourceFile) | ||
return createFoldingRange(textRange, "", l.createLspRangeFromNode(node, sourceFile), "") | ||
return createFoldingRange(textRange, "", "") | ||
} | ||
|
||
func spanForTemplateLiteral(node *ast.Node, sourceFile *ast.SourceFile, l *LanguageService) *lsproto.FoldingRange { | ||
|
@@ -448,7 +446,7 @@ func spanForJSXElement(node *ast.Node, sourceFile *ast.SourceFile, l *LanguageSe | |
bannerText.WriteString("<>...</>") | ||
} | ||
|
||
return createFoldingRange(textRange, "", nil, bannerText.String()) | ||
return createFoldingRange(textRange, "", bannerText.String()) | ||
} | ||
|
||
func spanForJSXAttributes(node *ast.Node, sourceFile *ast.SourceFile, l *LanguageService) *lsproto.FoldingRange { | ||
|
@@ -466,38 +464,35 @@ func spanForJSXAttributes(node *ast.Node, sourceFile *ast.SourceFile, l *Languag | |
|
||
func spanForNodeArray(statements *ast.NodeList, sourceFile *ast.SourceFile, l *LanguageService) *lsproto.FoldingRange { | ||
if statements != nil && len(statements.Nodes) != 0 { | ||
return createFoldingRange(l.createLspRangeFromBounds(statements.Pos(), statements.End(), sourceFile), "", nil, "") | ||
return createFoldingRange(l.createLspRangeFromBounds(statements.Pos(), statements.End(), sourceFile), "", "") | ||
} | ||
return nil | ||
} | ||
|
||
func spanForNode(node *ast.Node, hintSpanNode *ast.Node, open ast.Kind, useFullStart bool, sourceFile *ast.SourceFile, l *LanguageService) *lsproto.FoldingRange { | ||
close := ast.KindCloseBraceToken | ||
func spanForNode(node *ast.Node, open ast.Kind, useFullStart bool, sourceFile *ast.SourceFile, l *LanguageService) *lsproto.FoldingRange { | ||
closeBrace := ast.KindCloseBraceToken | ||
if open != ast.KindOpenBraceToken { | ||
close = ast.KindCloseBracketToken | ||
closeBrace = ast.KindCloseBracketToken | ||
} | ||
openToken := findChildOfKind(node, open, sourceFile) | ||
closeToken := findChildOfKind(node, close, sourceFile) | ||
closeToken := findChildOfKind(node, closeBrace, sourceFile) | ||
if openToken != nil && closeToken != nil { | ||
return rangeBetweenTokens(openToken, closeToken, hintSpanNode, sourceFile, useFullStart, l) | ||
return rangeBetweenTokens(openToken, closeToken, sourceFile, useFullStart, l) | ||
} | ||
return nil | ||
} | ||
|
||
func rangeBetweenTokens(openToken *ast.Node, closeToken *ast.Node, hintSpanNode *ast.Node, sourceFile *ast.SourceFile, useFullStart bool, l *LanguageService) *lsproto.FoldingRange { | ||
func rangeBetweenTokens(openToken *ast.Node, closeToken *ast.Node, sourceFile *ast.SourceFile, useFullStart bool, l *LanguageService) *lsproto.FoldingRange { | ||
var textRange *lsproto.Range | ||
if useFullStart { | ||
textRange = l.createLspRangeFromBounds(openToken.Pos(), closeToken.End(), sourceFile) | ||
} else { | ||
textRange = l.createLspRangeFromBounds(astnav.GetStartOfNode(openToken, sourceFile, false /*includeJSDoc*/), closeToken.End(), sourceFile) | ||
} | ||
return createFoldingRange(textRange, "", l.createLspRangeFromNode(hintSpanNode, sourceFile), "") | ||
return createFoldingRange(textRange, "", "") | ||
} | ||
|
||
func createFoldingRange(textRange *lsproto.Range, foldingRangeKind lsproto.FoldingRangeKind, hintRange *lsproto.Range, collapsedText string) *lsproto.FoldingRange { | ||
if hintRange == nil { | ||
hintRange = textRange | ||
} | ||
func createFoldingRange(textRange *lsproto.Range, foldingRangeKind lsproto.FoldingRangeKind, collapsedText string) *lsproto.FoldingRange { | ||
if collapsedText == "" { | ||
defaultText := "..." | ||
collapsedText = defaultText | ||
|
@@ -517,14 +512,14 @@ func createFoldingRange(textRange *lsproto.Range, foldingRangeKind lsproto.Foldi | |
} | ||
|
||
func createFoldingRangeFromBounds(pos int, end int, foldingRangeKind lsproto.FoldingRangeKind, sourceFile *ast.SourceFile, l *LanguageService) *lsproto.FoldingRange { | ||
return createFoldingRange(l.createLspRangeFromBounds(pos, end, sourceFile), foldingRangeKind, nil, "") | ||
return createFoldingRange(l.createLspRangeFromBounds(pos, end, sourceFile), foldingRangeKind, "") | ||
} | ||
|
||
func functionSpan(node *ast.Node, body *ast.Node, sourceFile *ast.SourceFile, l *LanguageService) *lsproto.FoldingRange { | ||
openToken := tryGetFunctionOpenToken(node, body, sourceFile) | ||
closeToken := findChildOfKind(body, ast.KindCloseBraceToken, sourceFile) | ||
if openToken != nil && closeToken != nil { | ||
return rangeBetweenTokens(openToken, closeToken, node, sourceFile, true /*useFullStart*/, l) | ||
return rangeBetweenTokens(openToken, closeToken, sourceFile, true /*useFullStart*/, l) | ||
} | ||
return nil | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -845,7 +845,7 @@ type B =[| [ | |
}|] | ||
|
||
interface IFoo[| { | ||
[|// all consecutive single line comments should be in one block regardless of their number or empty lines/spaces inbetween | ||
[|// all consecutive single line comments should be in one block regardless of their number or empty lines/spaces in between | ||
|
||
// comment 2 | ||
// comment 3 | ||
|
@@ -880,8 +880,6 @@ type B =[| [ | |
}|] | ||
|
||
function Foo()[| { | ||
[|// comment 1 | ||
// comment 2|] | ||
this.method = function (param)[| { | ||
}|] | ||
|
||
|
@@ -1101,12 +1099,6 @@ const[| { | |
const foo = null; | ||
|
||
function Foo()[| { | ||
[|/** | ||
* Description | ||
* | ||
* @param {string} param | ||
* @returns | ||
*/|] | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Does this crash, and that's why it's being removed? Can we leave the comment in and make sure we don't crash? If we do crash, the editor will pop up an error message. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It doesn't crash, the range is just returned twice because of the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Gotcha; that seems fine, though it seems like There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same reason for the other change in that same commit. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. With the new reparsed JS AST, JSDoc nodes are not actually declaration nodes anymore, as we should be inserting into the tree real nodes instead. But, that all is in flux. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I compared the debugging here with Strada, it's not exactly JSDoc, what's happening is that when the node is a There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Oh, bleh, because BinaryExpressions are currently Declarations for JSDoc reasons. Can you easily special case that for now until that is resolved? |
||
this.method = function (param)[| { | ||
}|] | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not that you can't, but why was this written this way instead of
for comment := range GetLeadingCommentRanges
?