diff --git a/packages/language-server/src/plugins/typescript/DocumentSnapshot.ts b/packages/language-server/src/plugins/typescript/DocumentSnapshot.ts index 764e8cfc7..72895882a 100644 --- a/packages/language-server/src/plugins/typescript/DocumentSnapshot.ts +++ b/packages/language-server/src/plugins/typescript/DocumentSnapshot.ts @@ -1,6 +1,4 @@ import { EncodedSourceMap, TraceMap, originalPositionFor } from '@jridgewell/trace-mapping'; -import path from 'path'; -import { walk } from 'svelte/compiler'; import { TemplateNode } from 'svelte/types/compiler/interfaces'; import { svelte2tsx, IExportedNames, internalHelpers } from 'svelte2tsx'; import ts from 'typescript'; @@ -19,7 +17,7 @@ import { } from '../../lib/documents'; import { pathToUrl, urlToPath } from '../../utils'; import { ConsumerDocumentMapper } from './DocumentMapper'; -import { SvelteNode } from './svelte-ast-utils'; +import { SvelteNode, SvelteNodeWalker, walkSvelteAst } from './svelte-ast-utils'; import { getScriptKindFromAttributes, getScriptKindFromFileName, @@ -335,19 +333,19 @@ export class SvelteDocumentSnapshot implements DocumentSnapshot { : this.parent.offsetAt(positionOrOffset); let foundNode: SvelteNode | null = null; - walk(this.htmlAst as any, { + this.walkSvelteAst({ enter(node) { // In case the offset is at a point where a node ends and a new one begins, // the node where the code ends is used. If this introduces problems, introduce // an affinity parameter to prefer the node where it ends/starts. - if ((node as SvelteNode).start > offset || (node as SvelteNode).end < offset) { + if (node.start > offset || node.end < offset) { this.skip(); return; } const parent = foundNode; // Spread so the "parent" property isn't added to the original ast, // causing an infinite loop - foundNode = { ...node } as SvelteNode; + foundNode = { ...node }; if (parent) { foundNode.parent = parent; } @@ -357,6 +355,14 @@ export class SvelteDocumentSnapshot implements DocumentSnapshot { return foundNode; } + walkSvelteAst(walker: SvelteNodeWalker) { + if (!this.htmlAst) { + return; + } + + walkSvelteAst(this.htmlAst, walker); + } + getOriginalPosition(pos: Position): Position { return this.getMapper().getOriginalPosition(pos); } diff --git a/packages/language-server/src/plugins/typescript/TypeScriptPlugin.ts b/packages/language-server/src/plugins/typescript/TypeScriptPlugin.ts index eb14d4934..af6fad0e0 100644 --- a/packages/language-server/src/plugins/typescript/TypeScriptPlugin.ts +++ b/packages/language-server/src/plugins/typescript/TypeScriptPlugin.ts @@ -217,7 +217,7 @@ export class TypeScriptPlugin return []; } - const { lang, tsDoc } = await this.getLSAndTSDoc(document); + const { lang, tsDoc } = await this.lsAndTsDocResolver.getLsForSyntheticOperations(document); if (cancellationToken?.isCancellationRequested) { return []; @@ -366,7 +366,7 @@ export class TypeScriptPlugin } async getDefinitions(document: Document, position: Position): Promise { - const { lang, tsDoc } = await this.getLSAndTSDoc(document); + const { lang, tsDoc } = await this.lsAndTsDocResolver.getLSAndTSDoc(document); const defs = lang.getDefinitionAndBoundSpan( tsDoc.filePath, @@ -644,10 +644,6 @@ export class TypeScriptPlugin return this.foldingRangeProvider.getFoldingRanges(document); } - private async getLSAndTSDoc(document: Document) { - return this.lsAndTsDocResolver.getLSAndTSDoc(document); - } - /** * @internal Public for tests only */ diff --git a/packages/language-server/src/plugins/typescript/features/FoldingRangeProvider.ts b/packages/language-server/src/plugins/typescript/features/FoldingRangeProvider.ts index a39614d8c..cb6712e4d 100644 --- a/packages/language-server/src/plugins/typescript/features/FoldingRangeProvider.ts +++ b/packages/language-server/src/plugins/typescript/features/FoldingRangeProvider.ts @@ -1,8 +1,7 @@ import ts from 'typescript'; -import { Node } from 'vscode-html-languageservice'; import { FoldingRangeKind, Range } from 'vscode-languageserver'; import { FoldingRange } from 'vscode-languageserver-types'; -import { Document, mapRangeToOriginal } from '../../../lib/documents'; +import { Document, isInTag, mapRangeToOriginal, toRange } from '../../../lib/documents'; import { isNotNullOrUndefined } from '../../../utils'; import { FoldingRangeProvider } from '../../interfaces'; import { LSAndTSDocResolver } from '../LSAndTSDocResolver'; @@ -11,6 +10,17 @@ import { isTextSpanInGeneratedCode } from './utils'; import { LSConfigManager } from '../../../ls-config'; import { LineRange, indentBasedFoldingRange } from '../../../lib/foldingRange/indentFolding'; import { SvelteDocumentSnapshot } from '../DocumentSnapshot'; +import { + SvelteNode, + SvelteNodeWalker, + findElseBlockTagStart, + findIfBlockEndTagStart, + hasElseBlock, + isAwaitBlock, + isEachBlock, + isElseBlockWithElseIf +} from '../svelte-ast-utils'; +import { Node } from 'vscode-html-languageservice'; export class FoldingRangeProviderImpl implements FoldingRangeProvider { constructor( @@ -18,8 +28,20 @@ export class FoldingRangeProviderImpl implements FoldingRangeProvider { private readonly configManager: LSConfigManager ) {} private readonly foldEndPairCharacters = ['}', ']', ')', '`', '>']; + private readonly endBlockKeywords = [ + ':else', + ':catch', + ':then', + '/if', + '/each', + '/await', + '/key' + ]; async getFoldingRanges(document: Document): Promise { + // don't use ls.getProgram unless it's necessary + // this feature is pure syntactic and doesn't need type information + const { lang, tsDoc } = await this.lsAndTsDocResolver.getLsForSyntheticOperations(document); const foldingRanges = @@ -31,53 +53,214 @@ export class FoldingRangeProviderImpl implements FoldingRangeProvider { !!this.configManager.getClientCapabilities()?.textDocument?.foldingRange ?.lineFoldingOnly; - const htmlStartMap = new Map(); - const collectHTMLTag = (node: Node) => { - htmlStartMap.set(node.start, node); - node.children?.forEach(collectHTMLTag); - }; - for (const node of document.html.roots) { - collectHTMLTag(node); - } - const result = foldingRanges .filter((span) => !isTextSpanInGeneratedCode(tsDoc.getFullText(), span.textSpan)) .map((span) => ({ - originalRange: mapRangeToOriginal(tsDoc, convertRange(tsDoc, span.textSpan)), + originalRange: this.mapToOriginalRange(tsDoc, span.textSpan, document), span })) - .filter( - ({ originalRange }) => - originalRange.start.line >= 0 && - originalRange.end.line >= 0 && - !htmlStartMap.has(document.offsetAt(originalRange.start)) - ) .map(({ originalRange, span }) => this.convertOutliningSpan(span, document, originalRange, lineFoldingOnly) ) .filter(isNotNullOrUndefined) + .concat(this.collectSvelteBlockFolding(document, tsDoc, lineFoldingOnly)) .concat(this.getSvelteTagFoldingIfParserError(document, tsDoc)) - .filter( - (r) => r.startLine < r.endLine && (!lineFoldingOnly || r.startLine !== r.endLine) - ); + .filter((r) => (lineFoldingOnly ? r.startLine < r.endLine : r.startLine <= r.endLine)); return result; } + private mapToOriginalRange( + tsDoc: SvelteDocumentSnapshot, + textSpan: ts.TextSpan, + document: Document + ) { + const range = mapRangeToOriginal(tsDoc, convertRange(tsDoc, textSpan)); + const startOffset = document.offsetAt(range.start); + + if (range.start.line < 0 || range.end.line < 0 || range.start.line > range.end.line) { + return; + } + + if ( + isInTag(range.start, document.scriptInfo) || + isInTag(range.start, document.moduleScriptInfo) + ) { + return range; + } + + const endOffset = document.offsetAt(range.end); + const originalText = document.getText().slice(startOffset, endOffset); + + if (originalText.length === 0) { + return; + } + + const generatedText = tsDoc.getText(textSpan.start, textSpan.start + textSpan.length); + const oneToOne = originalText.trim() === generatedText.trim(); + + if (oneToOne) { + return range; + } + } + + /** + * Doing this here with the svelte2tsx's svelte ast is slightly + * less prone to error and faster than + * using the svelte ast in the svelte plugins. + */ + private collectSvelteBlockFolding( + document: Document, + tsDoc: SvelteDocumentSnapshot, + lineFoldingOnly: boolean + ) { + if (tsDoc.parserError) { + return []; + } + + const ranges: FoldingRange[] = []; + + const provider = this; + const enter: SvelteNodeWalker['enter'] = function (node, parent, key) { + if (key === 'attributes') { + this.skip(); + } + + // use sub-block for await block + if (!node.type.endsWith('Block') || node.type === 'AwaitBlock') { + return; + } + + if (node.type === 'IfBlock') { + provider.getIfBlockFolding(node, document, ranges); + return; + } + + if (isElseBlockWithElseIf(node)) { + return; + } + + if ((node.type === 'CatchBlock' || node.type === 'ThenBlock') && isAwaitBlock(parent)) { + const expressionEnd = + (node.type === 'CatchBlock' ? parent.error?.end : parent.value?.end) ?? + document.getText().indexOf('}', node.start); + + const beforeBlockStartTagEnd = document.getText().indexOf('}', expressionEnd); + if (beforeBlockStartTagEnd == -1) { + return; + } + ranges.push( + provider.createFoldingRange(document, beforeBlockStartTagEnd + 1, node.end) + ); + + return; + } + + if (isEachBlock(node)) { + const start = document.getText().indexOf('}', (node.key ?? node.expression).end); + const elseStart = node.else + ? findElseBlockTagStart(document.getText(), node.else) + : -1; + + ranges.push( + provider.createFoldingRange( + document, + start, + elseStart === -1 ? node.end : elseStart + ) + ); + + return; + } + + if ('expression' in node && node.expression && typeof node.expression === 'object') { + const start = provider.getStartForNodeWithExpression( + node as SvelteNode & { expression: SvelteNode }, + document + ); + const end = node.end; + + ranges.push(provider.createFoldingRange(document, start, end)); + return; + } + + if (node.start != null && node.end != null) { + const start = node.start; + const end = node.end; + + ranges.push(provider.createFoldingRange(document, start, end)); + } + }; + + tsDoc.walkSvelteAst({ + enter + }); + + if (lineFoldingOnly) { + return ranges.map((r) => ({ + startLine: r.startLine, + endLine: this.previousLineOfEndLine(r.startLine, r.endLine) + })); + } + + return ranges; + } + + private getIfBlockFolding(node: SvelteNode, document: Document, ranges: FoldingRange[]) { + const typed = node as SvelteNode & { + else?: SvelteNode; + expression: SvelteNode; + }; + + const documentText = document.getText(); + const start = this.getStartForNodeWithExpression(typed, document); + const end = hasElseBlock(typed) + ? findElseBlockTagStart(documentText, typed.else) + : findIfBlockEndTagStart(documentText, typed); + + ranges.push(this.createFoldingRange(document, start, end)); + } + + private getStartForNodeWithExpression( + node: SvelteNode & { expression: SvelteNode }, + document: Document + ) { + return document.getText().indexOf('}', node.expression.end) + 1; + } + + private createFoldingRange(document: Document, start: number, end: number) { + const range = toRange(document.getText(), start, end); + return { + startLine: range.start.line, + startCharacter: range.start.character, + endLine: range.end.line, + endCharacter: range.end.character + }; + } + private convertOutliningSpan( span: ts.OutliningSpan, document: Document, - originalRange: Range, + originalRange: Range | undefined, lineFoldingOnly: boolean ): FoldingRange | null { - const end = this.adjustFoldingEnd(originalRange, document, lineFoldingOnly); - return { + if (!originalRange) { + return null; + } + + const end = lineFoldingOnly + ? this.adjustFoldingEndToNotHideEnd(originalRange, document) + : originalRange.end; + + const result = { startLine: originalRange.start.line, endLine: end.line, kind: this.getFoldingRangeKind(span), startCharacter: lineFoldingOnly ? undefined : originalRange.start.character, endCharacter: lineFoldingOnly ? undefined : end.character }; + + return result; } private getFoldingRangeKind(span: ts.OutliningSpan): FoldingRangeKind | undefined { @@ -94,13 +277,12 @@ export class FoldingRangeProviderImpl implements FoldingRangeProvider { } } - private adjustFoldingEnd( + private adjustFoldingEndToNotHideEnd( range: Range, - document: Document, - lineFoldingOnly: boolean + document: Document ): { line: number; character?: number } { // don't fold end bracket, brace... - if (range.end.character > 0 && lineFoldingOnly) { + if (range.end.character > 0) { const text = document.getText(); const offsetBeforeEnd = document.offsetAt({ line: range.end.line, @@ -112,34 +294,6 @@ export class FoldingRangeProviderImpl implements FoldingRangeProvider { } } - let endOffset = document.offsetAt(range.end); - const elseKeyword = ':else'; - const lastPossibleOffsetIfOverlap = endOffset - elseKeyword.length + 1; - const isMiddleOfElseBlock = document - .getText() - .slice(lastPossibleOffsetIfOverlap, endOffset + elseKeyword.length - 1) - .includes(elseKeyword); - - if (isMiddleOfElseBlock) { - endOffset = document - .getText() - .lastIndexOf( - '{', - document.getText().indexOf(elseKeyword, lastPossibleOffsetIfOverlap) - ); - range.end = document.positionAt(endOffset); - } - - if (!lineFoldingOnly) { - return range.end; - } - - const after = document.getText().slice(endOffset); - - if (after.startsWith('{:') || after.startsWith('{/')) { - return { line: this.previousLineOfEndLine(range.start.line, range.end.line) }; - } - return range.end; } @@ -153,11 +307,7 @@ export class FoldingRangeProviderImpl implements FoldingRangeProvider { return indentBasedFoldingRange({ document, skipFold: (_, lineContent) => { - return ( - !lineContent.includes('{#') && - !lineContent.includes('{/') && - !lineContent.includes('{:') - ); + return !/{\s*(#|\/|:)/.test(lineContent); }, ranges: htmlTemplateRanges }); diff --git a/packages/language-server/src/plugins/typescript/features/SelectionRangeProvider.ts b/packages/language-server/src/plugins/typescript/features/SelectionRangeProvider.ts index 1d2ba6c4c..bd7cb1c35 100644 --- a/packages/language-server/src/plugins/typescript/features/SelectionRangeProvider.ts +++ b/packages/language-server/src/plugins/typescript/features/SelectionRangeProvider.ts @@ -13,7 +13,7 @@ export class SelectionRangeProviderImpl implements SelectionRangeProvider { document: Document, position: Position ): Promise { - const { tsDoc, lang } = await this.lsAndTsDocResolver.getLSAndTSDoc(document); + const { tsDoc, lang } = await this.lsAndTsDocResolver.getLsForSyntheticOperations(document); const tsSelectionRange = lang.getSmartSelectionRange( tsDoc.filePath, diff --git a/packages/language-server/src/plugins/typescript/features/utils.ts b/packages/language-server/src/plugins/typescript/features/utils.ts index cfbaf4643..e790773b3 100644 --- a/packages/language-server/src/plugins/typescript/features/utils.ts +++ b/packages/language-server/src/plugins/typescript/features/utils.ts @@ -163,6 +163,24 @@ export function isAfterSvelte2TsxPropsReturn(text: string, end: number) { } } +// function binarySearch(node: ts.Node, comparer: (node: ts.Node) => -1 | 0 | 1) { +// let low = node.getStart(); +// let high = node.getEnd(); + +// while (low <= high) { +// const mid = low + (high - low) / 2; +// const child = node.getChildAt(mid); +// if (child) { +// return child; +// } +// if (mid < low) { +// low = mid + 1; +// } else if (mid > high) { +// high = mid - 1; +// } +// } +// } + export function findContainingNode( node: ts.Node, textSpan: ts.TextSpan, diff --git a/packages/language-server/src/plugins/typescript/svelte-ast-utils.ts b/packages/language-server/src/plugins/typescript/svelte-ast-utils.ts index 86c7ee579..46d90acc0 100644 --- a/packages/language-server/src/plugins/typescript/svelte-ast-utils.ts +++ b/packages/language-server/src/plugins/typescript/svelte-ast-utils.ts @@ -1,3 +1,7 @@ +import { Node } from 'estree'; +import { walk } from 'svelte/compiler'; +import { TemplateNode } from 'svelte/types/compiler/interfaces'; + export interface SvelteNode { start: number; end: number; @@ -7,6 +11,30 @@ export interface SvelteNode { type HTMLLike = 'Element' | 'InlineComponent' | 'Body' | 'Window'; +export interface AwaitBlock extends SvelteNode { + type: 'AwaitBlock'; + expression: SvelteNode & Node; + value: (SvelteNode & Node) | null; + error: (SvelteNode & Node) | null; + pending: AwaitSubBlock; + then: AwaitSubBlock; + catch: AwaitSubBlock; +} + +export interface AwaitSubBlock extends SvelteNode { + skip: boolean; + children: SvelteNode[]; +} + +export interface EachBlock extends SvelteNode { + type: 'EachBlock'; + expression: SvelteNode & Node; + context: SvelteNode & Node; + key?: SvelteNode & Node; + else?: SvelteNode; + children: SvelteNode[]; +} + function matchesOnly(type: string | undefined, only?: 'Element' | 'InlineComponent'): boolean { return ( !only || @@ -73,3 +101,70 @@ export function isEventHandler( ) { return !!node && node.type === 'EventHandler' && matchesOnly(node.parent?.type, only); } + +export function isElseBlockWithElseIf(node: SvelteNode | null | undefined) { + return ( + !!node && + node.type === 'ElseBlock' && + 'children' in node && + Array.isArray(node.children) && + node.children.length === 1 && + node.children[0].type === 'IfBlock' + ); +} + +export function hasElseBlock(node: SvelteNode): node is SvelteNode & { else: SvelteNode } { + return 'else' in node && !!node.else; +} + +export function findElseBlockTagStart(documentText: string, elseBlock: SvelteNode) { + return documentText.lastIndexOf('{', documentText.lastIndexOf(':else', elseBlock.start)); +} + +export function findIfBlockEndTagStart(documentText: string, ifBlock: SvelteNode) { + return documentText.lastIndexOf('{', documentText.lastIndexOf('/if', ifBlock.end)); +} + +export interface SvelteNodeWalker { + enter?: ( + this: { + skip: () => void; + remove: () => void; + replace: (node: SvelteNode) => void; + }, + node: SvelteNode, + parent: SvelteNode, + key: string, + index: number + ) => void; + leave?: ( + this: { + skip: () => void; + remove: () => void; + replace: (node: SvelteNode) => void; + }, + node: SvelteNode, + parent: SvelteNode, + key: string, + index: number + ) => void; +} + +export function walkSvelteAst(htmlAst: TemplateNode, walker: SvelteNodeWalker) { + walk(htmlAst as any, { + enter(node, parent, key, index) { + walker.enter?.call(this, node as SvelteNode, parent as SvelteNode, key, index); + }, + leave(node, parent, key, index) { + walker.leave?.call(this, node as SvelteNode, parent as SvelteNode, key, index); + } + }); +} + +export function isAwaitBlock(node: SvelteNode): node is AwaitBlock { + return node.type === 'AwaitBlock'; +} + +export function isEachBlock(node: SvelteNode): node is EachBlock { + return node.type === 'EachBlock'; +} diff --git a/packages/language-server/test/plugins/typescript/features/folding-range/fixtures/await-catch/expectedv2.json b/packages/language-server/test/plugins/typescript/features/folding-range/fixtures/await-catch/expectedv2.json index 98bf02d30..ff07652a2 100644 --- a/packages/language-server/test/plugins/typescript/features/folding-range/fixtures/await-catch/expectedv2.json +++ b/packages/language-server/test/plugins/typescript/features/folding-range/fixtures/await-catch/expectedv2.json @@ -1,4 +1,4 @@ [ { "startLine": 0, "endLine": 1 }, - { "startLine": 4, "endLine": 7 } + { "startLine": 6, "endLine": 7 } ] diff --git a/packages/language-server/test/plugins/typescript/features/folding-range/fixtures/await-peding-catch/expectedv2.json b/packages/language-server/test/plugins/typescript/features/folding-range/fixtures/await-peding-catch/expectedv2.json index ff07652a2..6c5814c47 100644 --- a/packages/language-server/test/plugins/typescript/features/folding-range/fixtures/await-peding-catch/expectedv2.json +++ b/packages/language-server/test/plugins/typescript/features/folding-range/fixtures/await-peding-catch/expectedv2.json @@ -1,4 +1,6 @@ [ { "startLine": 0, "endLine": 1 }, - { "startLine": 6, "endLine": 7 } + { "startLine": 2, "endLine": 3 }, + { "startLine": 6, "endLine": 7 }, + { "startLine": 9, "endLine": 10 } ] diff --git a/packages/language-server/test/plugins/typescript/features/folding-range/fixtures/await-pending-only/expectedv2.json b/packages/language-server/test/plugins/typescript/features/folding-range/fixtures/await-pending-only/expectedv2.json index fe51488c7..ee866a024 100644 --- a/packages/language-server/test/plugins/typescript/features/folding-range/fixtures/await-pending-only/expectedv2.json +++ b/packages/language-server/test/plugins/typescript/features/folding-range/fixtures/await-pending-only/expectedv2.json @@ -1 +1 @@ -[] +[{ "startLine": 0, "endLine": 1 }] diff --git a/packages/language-server/test/plugins/typescript/features/folding-range/fixtures/await-pending-then-catch/expectedv2.json b/packages/language-server/test/plugins/typescript/features/folding-range/fixtures/await-pending-then-catch/expectedv2.json index a621896be..a029fbdc6 100644 --- a/packages/language-server/test/plugins/typescript/features/folding-range/fixtures/await-pending-then-catch/expectedv2.json +++ b/packages/language-server/test/plugins/typescript/features/folding-range/fixtures/await-pending-then-catch/expectedv2.json @@ -1,8 +1,8 @@ [ - { "startLine": 2, "endLine": 3 }, { "startLine": 0, "endLine": 1 }, + { "startLine": 2, "endLine": 3 }, { "startLine": 4, "endLine": 5 }, - { "startLine": 10, "endLine": 12 }, { "startLine": 8, "endLine": 9 }, - { "startLine": 13, "endLine": 15 } + { "startLine": 11, "endLine": 12 }, + { "startLine": 14, "endLine": 15 } ] diff --git a/packages/language-server/test/plugins/typescript/features/folding-range/fixtures/await-pending-then/expectedv2.json b/packages/language-server/test/plugins/typescript/features/folding-range/fixtures/await-pending-then/expectedv2.json index ee866a024..c75b3a509 100644 --- a/packages/language-server/test/plugins/typescript/features/folding-range/fixtures/await-pending-then/expectedv2.json +++ b/packages/language-server/test/plugins/typescript/features/folding-range/fixtures/await-pending-then/expectedv2.json @@ -1 +1,4 @@ -[{ "startLine": 0, "endLine": 1 }] +[ + { "startLine": 0, "endLine": 1 }, + { "startLine": 2, "endLine": 3 } +] diff --git a/packages/language-server/test/plugins/typescript/features/folding-range/fixtures/await-then-catch-shorthand/expectedv2.json b/packages/language-server/test/plugins/typescript/features/folding-range/fixtures/await-then-catch-shorthand/expectedv2.json new file mode 100644 index 000000000..c75b3a509 --- /dev/null +++ b/packages/language-server/test/plugins/typescript/features/folding-range/fixtures/await-then-catch-shorthand/expectedv2.json @@ -0,0 +1,4 @@ +[ + { "startLine": 0, "endLine": 1 }, + { "startLine": 2, "endLine": 3 } +] diff --git a/packages/language-server/test/plugins/typescript/features/folding-range/fixtures/await-then-catch-shorthand/input.svelte b/packages/language-server/test/plugins/typescript/features/folding-range/fixtures/await-then-catch-shorthand/input.svelte new file mode 100644 index 000000000..2c787de40 --- /dev/null +++ b/packages/language-server/test/plugins/typescript/features/folding-range/fixtures/await-then-catch-shorthand/input.svelte @@ -0,0 +1,5 @@ +{#await Promise.resolve() then value} + {value} +{:catch} + error +{/await} \ No newline at end of file diff --git a/packages/language-server/test/plugins/typescript/features/folding-range/fixtures/await-then-catch/expectedv2.json b/packages/language-server/test/plugins/typescript/features/folding-range/fixtures/await-then-catch/expectedv2.json new file mode 100644 index 000000000..c75b3a509 --- /dev/null +++ b/packages/language-server/test/plugins/typescript/features/folding-range/fixtures/await-then-catch/expectedv2.json @@ -0,0 +1,4 @@ +[ + { "startLine": 0, "endLine": 1 }, + { "startLine": 2, "endLine": 3 } +] diff --git a/packages/language-server/test/plugins/typescript/features/folding-range/fixtures/await-then-catch/input.svelte b/packages/language-server/test/plugins/typescript/features/folding-range/fixtures/await-then-catch/input.svelte new file mode 100644 index 000000000..98955f55e --- /dev/null +++ b/packages/language-server/test/plugins/typescript/features/folding-range/fixtures/await-then-catch/input.svelte @@ -0,0 +1,5 @@ +{#await Promise.resolve() then value} + {value} +{:catch error} + {error} +{/await} \ No newline at end of file diff --git a/packages/language-server/test/plugins/typescript/features/folding-range/fixtures/await-then/expectedv2.json b/packages/language-server/test/plugins/typescript/features/folding-range/fixtures/await-then/expectedv2.json index 98bf02d30..ff07652a2 100644 --- a/packages/language-server/test/plugins/typescript/features/folding-range/fixtures/await-then/expectedv2.json +++ b/packages/language-server/test/plugins/typescript/features/folding-range/fixtures/await-then/expectedv2.json @@ -1,4 +1,4 @@ [ { "startLine": 0, "endLine": 1 }, - { "startLine": 4, "endLine": 7 } + { "startLine": 6, "endLine": 7 } ] diff --git a/packages/language-server/test/plugins/typescript/features/folding-range/fixtures/each-block/expectedv2.json b/packages/language-server/test/plugins/typescript/features/folding-range/fixtures/each-block/expectedv2.json index d94ee7104..9cfe3e186 100644 --- a/packages/language-server/test/plugins/typescript/features/folding-range/fixtures/each-block/expectedv2.json +++ b/packages/language-server/test/plugins/typescript/features/folding-range/fixtures/each-block/expectedv2.json @@ -1,4 +1,4 @@ [ { "startLine": 0, "endLine": 1 }, - { "startLine": 4, "endLine": 5 } + { "startLine": 5, "endLine": 6 } ] diff --git a/packages/language-server/test/plugins/typescript/features/folding-range/fixtures/each-block/input.svelte b/packages/language-server/test/plugins/typescript/features/folding-range/fixtures/each-block/input.svelte index 5324264c2..e09edee46 100644 --- a/packages/language-server/test/plugins/typescript/features/folding-range/fixtures/each-block/input.svelte +++ b/packages/language-server/test/plugins/typescript/features/folding-range/fixtures/each-block/input.svelte @@ -2,8 +2,7 @@ {item} {/each} -{#each items as item} +{#each items as + item} {item} -{:else} - no items -{/each} \ No newline at end of file +{/each} diff --git a/packages/language-server/test/plugins/typescript/features/folding-range/fixtures/each-else/expectedv2.json b/packages/language-server/test/plugins/typescript/features/folding-range/fixtures/each-else/expectedv2.json new file mode 100644 index 000000000..c75b3a509 --- /dev/null +++ b/packages/language-server/test/plugins/typescript/features/folding-range/fixtures/each-else/expectedv2.json @@ -0,0 +1,4 @@ +[ + { "startLine": 0, "endLine": 1 }, + { "startLine": 2, "endLine": 3 } +] diff --git a/packages/language-server/test/plugins/typescript/features/folding-range/fixtures/each-else/input.svelte b/packages/language-server/test/plugins/typescript/features/folding-range/fixtures/each-else/input.svelte new file mode 100644 index 000000000..bfbff7239 --- /dev/null +++ b/packages/language-server/test/plugins/typescript/features/folding-range/fixtures/each-else/input.svelte @@ -0,0 +1,5 @@ +{#each items as item} + {item} +{:else} + no items +{/each} \ No newline at end of file diff --git a/packages/language-server/test/plugins/typescript/features/folding-range/fixtures/each-keyed/expectedv2.json b/packages/language-server/test/plugins/typescript/features/folding-range/fixtures/each-keyed/expectedv2.json new file mode 100644 index 000000000..c46adf55a --- /dev/null +++ b/packages/language-server/test/plugins/typescript/features/folding-range/fixtures/each-keyed/expectedv2.json @@ -0,0 +1 @@ +[{ "startLine": 2, "endLine": 3 }] diff --git a/packages/language-server/test/plugins/typescript/features/folding-range/fixtures/each-keyed/input.svelte b/packages/language-server/test/plugins/typescript/features/folding-range/fixtures/each-keyed/input.svelte new file mode 100644 index 000000000..c5fd34b66 --- /dev/null +++ b/packages/language-server/test/plugins/typescript/features/folding-range/fixtures/each-keyed/input.svelte @@ -0,0 +1,5 @@ +{#each items as +{id} +(id)} + {id} +{/each} diff --git a/packages/language-server/test/plugins/typescript/features/folding-range/fixtures/key-block/expectedv2.json b/packages/language-server/test/plugins/typescript/features/folding-range/fixtures/key-block/expectedv2.json new file mode 100644 index 000000000..ff07652a2 --- /dev/null +++ b/packages/language-server/test/plugins/typescript/features/folding-range/fixtures/key-block/expectedv2.json @@ -0,0 +1,4 @@ +[ + { "startLine": 0, "endLine": 1 }, + { "startLine": 6, "endLine": 7 } +] diff --git a/packages/language-server/test/plugins/typescript/features/folding-range/fixtures/key-block/input.svelte b/packages/language-server/test/plugins/typescript/features/folding-range/fixtures/key-block/input.svelte new file mode 100644 index 000000000..1dc659512 --- /dev/null +++ b/packages/language-server/test/plugins/typescript/features/folding-range/fixtures/key-block/input.svelte @@ -0,0 +1,9 @@ +{#key hi} + {hi} +{/key} + +{#key + +hi} + {hi} +{/key} \ No newline at end of file diff --git a/packages/language-server/test/plugins/typescript/features/folding-range/index.test.ts b/packages/language-server/test/plugins/typescript/features/folding-range/index.test.ts index aefd82e11..76a342c4b 100644 --- a/packages/language-server/test/plugins/typescript/features/folding-range/index.test.ts +++ b/packages/language-server/test/plugins/typescript/features/folding-range/index.test.ts @@ -113,7 +113,7 @@ async function executeTest( const executeTests = createSnapshotTester(executeTest); -describe.only('FoldingRangeProvider', function () { +describe('FoldingRangeProvider', function () { executeTests({ dir: join(__dirname, 'fixtures'), workspaceDir: join(__dirname, 'fixtures'),