diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index c741138d9..17143b2ab 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -23,6 +23,31 @@ jobs: env: CI: true + test-svelte5: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v3 + - uses: pnpm/action-setup@v2.2.4 + - uses: actions/setup-node@v3 + with: + node-version: "18.x" + cache: pnpm + + # Lets us use one-liner JSON manipulations the package.json files + - run: "npm install -g json" + + # Get projects set up + - run: json -I -f package.json -e 'this.pnpm={"overrides":{"svelte":"^5.0.0-next.100"}}' + - run: pnpm install --no-frozen-lockfile + - run: pnpm bootstrap + - run: pnpm build + + # Run any tests + - run: pnpm test + env: + CI: true + lint: runs-on: ubuntu-latest diff --git a/packages/language-server/src/plugins/svelte/features/getDiagnostics.ts b/packages/language-server/src/plugins/svelte/features/getDiagnostics.ts index dbc21bfb8..4c1f91d7a 100644 --- a/packages/language-server/src/plugins/svelte/features/getDiagnostics.ts +++ b/packages/language-server/src/plugins/svelte/features/getDiagnostics.ts @@ -63,7 +63,7 @@ async function tryGetDiagnostics( if (cancellationToken?.isCancellationRequested) { return []; } - return (((res.stats as any)?.warnings || res.warnings || []) as Warning[]) + return (res.warnings || []) .filter((warning) => settings[warning.code] !== 'ignore') .map((warning) => { const start = warning.start || { line: 1, column: 0 }; diff --git a/packages/language-server/src/plugins/typescript/DocumentSnapshot.ts b/packages/language-server/src/plugins/typescript/DocumentSnapshot.ts index 5f243b13e..d5d921af5 100644 --- a/packages/language-server/src/plugins/typescript/DocumentSnapshot.ts +++ b/packages/language-server/src/plugins/typescript/DocumentSnapshot.ts @@ -87,6 +87,7 @@ export namespace DocumentSnapshot { document, parserError, scriptKind, + options.version, text, nrPrependedLines, exportedNames, @@ -272,6 +273,7 @@ export class SvelteDocumentSnapshot implements DocumentSnapshot { public readonly parent: Document, public readonly parserError: ParserError | null, public readonly scriptKind: ts.ScriptKind, + public readonly svelteVersion: string | undefined, private readonly text: string, private readonly nrPrependedLines: number, private readonly exportedNames: IExportedNames, @@ -279,6 +281,10 @@ export class SvelteDocumentSnapshot implements DocumentSnapshot { private readonly htmlAst?: TemplateNode ) {} + get isSvelte5Plus() { + return Number(this.svelteVersion?.split('.')[0]) >= 5; + } + get filePath() { return this.parent.getFilePath() || ''; } diff --git a/packages/language-server/src/plugins/typescript/features/DiagnosticsProvider.ts b/packages/language-server/src/plugins/typescript/features/DiagnosticsProvider.ts index 64223ac35..485b041f2 100644 --- a/packages/language-server/src/plugins/typescript/features/DiagnosticsProvider.ts +++ b/packages/language-server/src/plugins/typescript/features/DiagnosticsProvider.ts @@ -21,7 +21,14 @@ import { isStoreVariableIn$storeDeclaration, get$storeOffsetOf$storeDeclaration } from './utils'; -import { not, flatten, passMap, swapRangeStartEndIfNecessary, memoize } from '../../../utils'; +import { + not, + flatten, + passMap, + swapRangeStartEndIfNecessary, + memoize, + traverseTypeString +} from '../../../utils'; import { LSConfigManager } from '../../../ls-config'; import { isAttributeName, isEventHandler } from '../svelte-ast-utils'; @@ -37,7 +44,10 @@ export enum DiagnosticCode { DUPLICATED_JSX_ATTRIBUTES = 17001, // "JSX elements cannot have multiple attributes with the same name." DUPLICATE_IDENTIFIER = 2300, // "Duplicate identifier 'xxx'" MULTIPLE_PROPS_SAME_NAME = 1117, // "An object literal cannot have multiple properties with the same name in strict mode." - TYPE_X_NOT_ASSIGNABLE_TO_TYPE_Y = 2345, // "Argument of type '..' is not assignable to parameter of type '..'." + ARG_TYPE_X_NOT_ASSIGNABLE_TO_TYPE_Y = 2345, // "Argument of type '..' is not assignable to parameter of type '..'." + TYPE_X_NOT_ASSIGNABLE_TO_TYPE_Y = 2322, // "Type '..' is not assignable to type '..'." + TYPE_X_NOT_ASSIGNABLE_TO_TYPE_Y_DID_YOU_MEAN = 2820, // "Type '..' is not assignable to type '..'. Did you mean '...'?" + UNKNOWN_PROP = 2353, // "Object literal may only specify known properties, and '...' does not exist in type '...'" MISSING_PROPS = 2739, // "Type '...' is missing the following properties from type '..': ..." MISSING_PROP = 2741, // "Property '..' is missing in type '..' but required in type '..'." NO_OVERLOAD_MATCHES_CALL = 2769, // "No overload matches this call" @@ -101,7 +111,7 @@ export class DiagnosticsProviderImpl implements DiagnosticsProvider { for (const diagnostic of diagnostics) { if ( (diagnostic.code === DiagnosticCode.NO_OVERLOAD_MATCHES_CALL || - diagnostic.code === DiagnosticCode.TYPE_X_NOT_ASSIGNABLE_TO_TYPE_Y) && + diagnostic.code === DiagnosticCode.ARG_TYPE_X_NOT_ASSIGNABLE_TO_TYPE_Y) && !notGenerated(diagnostic) ) { if (isStoreVariableIn$storeDeclaration(tsDoc.getFullText(), diagnostic.start!)) { @@ -147,7 +157,7 @@ export class DiagnosticsProviderImpl implements DiagnosticsProvider { .map(mapRange(tsDoc, document, lang)) .filter(hasNoNegativeLines) .filter(isNoFalsePositive(document, tsDoc)) - .map(enhanceIfNecessary) + .map(adjustIfNecessary) .map(swapDiagRangeStartEndIfNecessary); } @@ -180,9 +190,11 @@ function mapRange( } if ( - [DiagnosticCode.MISSING_PROP, DiagnosticCode.MISSING_PROPS].includes( + ([DiagnosticCode.MISSING_PROP, DiagnosticCode.MISSING_PROPS].includes( diagnostic.code as number - ) && + ) || + (DiagnosticCode.TYPE_X_NOT_ASSIGNABLE_TO_TYPE_Y && + diagnostic.message.includes("'PropsWithChildren<"))) && !hasNonZeroRange({ range }) ) { const node = getNodeIfIsInStartTag(document.html, document.offsetAt(range.start)); @@ -286,11 +298,11 @@ function isNoUsedBeforeAssigned( } /** - * Some diagnostics have JSX-specific nomenclature. Enhance them for more clarity. + * Some diagnostics have JSX-specific or confusing nomenclature. Enhance/adjust them for more clarity. */ -function enhanceIfNecessary(diagnostic: Diagnostic): Diagnostic { +function adjustIfNecessary(diagnostic: Diagnostic): Diagnostic { if ( - diagnostic.code === DiagnosticCode.TYPE_X_NOT_ASSIGNABLE_TO_TYPE_Y && + diagnostic.code === DiagnosticCode.ARG_TYPE_X_NOT_ASSIGNABLE_TO_TYPE_Y && diagnostic.message.includes('ConstructorOfATypedSvelteComponent') ) { return { @@ -315,6 +327,37 @@ function enhanceIfNecessary(diagnostic: Diagnostic): Diagnostic { }; } + if ( + (diagnostic.code === DiagnosticCode.TYPE_X_NOT_ASSIGNABLE_TO_TYPE_Y || + diagnostic.code === DiagnosticCode.TYPE_X_NOT_ASSIGNABLE_TO_TYPE_Y_DID_YOU_MEAN) && + diagnostic.message.includes("'Bindable<") + ) { + const countBindable = (diagnostic.message.match(/'Bindable\ from diagnostic message + const start = diagnostic.message.indexOf("'Bindable<"); + const startType = start + "'Bindable".length; + const end = traverseTypeString(diagnostic.message, startType, '>'); + diagnostic.message = + diagnostic.message.substring(0, start + 1) + + diagnostic.message.substring(startType + 1, end) + + diagnostic.message.substring(end + 1); + } else if (countBinding === 3 && countBindable === 1) { + // Only keep Type '...' is not assignable to type '...' in + // Type Bindings<...> is not assignable to type Bindable<...>, Type Binding<...> is not assignable to type Bindable<...>, Type '...' is not assignable to type '...' + const lines = diagnostic.message.split('\n'); + if (lines.length === 3) { + diagnostic.message = lines[2].trimStart(); + } + } + + return { + ...diagnostic, + message: diagnostic.message + }; + } + return diagnostic; } diff --git a/packages/language-server/src/plugins/typescript/features/RenameProvider.ts b/packages/language-server/src/plugins/typescript/features/RenameProvider.ts index ff1902766..3ba763e3c 100644 --- a/packages/language-server/src/plugins/typescript/features/RenameProvider.ts +++ b/packages/language-server/src/plugins/typescript/features/RenameProvider.ts @@ -37,6 +37,9 @@ interface TsRenameLocation extends ts.RenameLocation { newName?: string; } +const bind = 'bind:'; +const bindShortHandGeneratedLength = ':__sveltets_2_binding('.length; + export class RenameProviderImpl implements RenameProvider { constructor( private readonly lsAndTsDocResolver: LSAndTSDocResolver, @@ -73,7 +76,7 @@ export class RenameProviderImpl implements RenameProvider { const renameLocations = lang.findRenameLocations( tsDoc.filePath, - offset, + offset + (renameInfo.bindShorthand || 0), false, false, true @@ -157,6 +160,7 @@ export class RenameProviderImpl implements RenameProvider { ): | (ts.RenameInfoSuccess & { isStore?: boolean; + bindShorthand?: number; }) | null { // Don't allow renames in error-state, because then there is no generated svelte2tsx-code @@ -165,6 +169,15 @@ export class RenameProviderImpl implements RenameProvider { return null; } + const svelteNode = tsDoc.svelteNodeAt(originalPosition); + + let bindOffset = 0; + const bindingShorthand = this.getBindingShorthand(tsDoc, originalPosition, svelteNode); + if (bindingShorthand) { + bindOffset = bindingShorthand.end - bindingShorthand.start; + generatedOffset += bindShortHandGeneratedLength + bindOffset; + } + const renameInfo = lang.getRenameInfo(tsDoc.filePath, generatedOffset, { allowRenameOfImportPath: false }); @@ -178,7 +191,6 @@ export class RenameProviderImpl implements RenameProvider { return null; } - const svelteNode = tsDoc.svelteNodeAt(originalPosition); if ( isInHTMLTagRange(doc.html, doc.offsetAt(originalPosition)) || isAttributeName(svelteNode, 'Element') || @@ -188,16 +200,22 @@ export class RenameProviderImpl implements RenameProvider { } // If $store is renamed, only allow rename for $|store| - if (tsDoc.getFullText().charAt(renameInfo.triggerSpan.start) === '$') { + const text = tsDoc.getFullText(); + if (text.charAt(renameInfo.triggerSpan.start) === '$') { const definition = lang.getDefinitionAndBoundSpan(tsDoc.filePath, generatedOffset) ?.definitions?.[0]; - if (definition && isTextSpanInGeneratedCode(tsDoc.getFullText(), definition.textSpan)) { + if (definition && isTextSpanInGeneratedCode(text, definition.textSpan)) { renameInfo.triggerSpan.start++; renameInfo.triggerSpan.length--; (renameInfo as any).isStore = true; } } + if (bindOffset) { + renameInfo.triggerSpan.start -= bindShortHandGeneratedLength + bindOffset; + (renameInfo as any).bindShorthand = bindShortHandGeneratedLength + bindOffset; + } + return renameInfo; } @@ -325,7 +343,6 @@ export class RenameProviderImpl implements RenameProvider { replacementsForProp, snapshots ); - const bind = 'bind:'; // Adjust shorthands return renameLocations.map((location) => { @@ -351,31 +368,29 @@ export class RenameProviderImpl implements RenameProvider { const { parent } = snapshot; - let rangeStart = parent.offsetAt(location.range.start); - let suffixText = location.suffixText?.trimStart(); - - // suffix is of the form `: oldVarName` -> hints at a shorthand - if (!suffixText?.startsWith(':') || !getNodeIfIsInStartTag(parent.html, rangeStart)) { - return location; - } - - const original = parent.getText({ - start: Position.create( - location.range.start.line, - location.range.start.character - bind.length - ), - end: location.range.end - }); - - if (original.startsWith(bind)) { + const bindingShorthand = this.getBindingShorthand(snapshot, location.range.start); + if (bindingShorthand) { // bind:|foo| -> bind:|newName|={foo} + const name = parent + .getText() + .substring(bindingShorthand.start, bindingShorthand.end); return { ...location, prefixText: '', - suffixText: `={${original.slice(bind.length)}}` + suffixText: `={${name}}` }; } + let rangeStart = parent.offsetAt(location.range.start); + + // suffix is of the form `: oldVarName` -> hints at a shorthand + if ( + !location.suffixText?.trimStart()?.startsWith(':') || + !getNodeIfIsInStartTag(parent.html, rangeStart) + ) { + return location; + } + if (snapshot.getOriginalText().charAt(rangeStart - 1) === '{') { // {|foo|} -> |{foo|} rangeStart--; @@ -582,8 +597,6 @@ export class RenameProviderImpl implements RenameProvider { renameLocations: TsRenameLocation[], snapshots: SnapshotMap ): TsRenameLocation[] { - const bind = 'bind:'; - return renameLocations.map((location) => { const sourceFile = lang.getProgram()?.getSourceFile(location.fileName); @@ -625,6 +638,38 @@ export class RenameProviderImpl implements RenameProvider { suffixText: '}' }; } + + if (snapshot.isSvelte5Plus) { + const bindingShorthand = this.getBindingShorthand( + snapshot, + location.range.start + ); + if (bindingShorthand) { + const name = parent + .getText() + .substring(bindingShorthand.start, bindingShorthand.end); + const start = { + line: location.range.start.line, + character: location.range.start.character - name.length + }; + // If binding is followed by the closing tag, start is one character too soon, + // else binding is ending one character too far + if (parent.getText().charAt(parent.offsetAt(start)) === ':') { + start.character++; + } else { + location.range.end.character--; + } + return { + ...location, + range: { + start: start, + end: location.range.end + }, + prefixText: name + '={', + suffixText: '}' + }; + } + } } if (!prefixText || prefixText.slice(-1) !== ':') { @@ -668,4 +713,17 @@ export class RenameProviderImpl implements RenameProvider { return location; }); } + + private getBindingShorthand( + snapshot: SvelteDocumentSnapshot, + position: Position, + svelteNode = snapshot.svelteNodeAt(position) + ) { + if ( + svelteNode?.parent?.type === 'Binding' && + svelteNode.parent.expression.end === svelteNode.parent.end + ) { + return svelteNode.parent.expression; + } + } } 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 df51edb26..b023a23c3 100644 --- a/packages/language-server/src/plugins/typescript/svelte-ast-utils.ts +++ b/packages/language-server/src/plugins/typescript/svelte-ast-utils.ts @@ -8,6 +8,7 @@ export interface SvelteNode { end: number; type: string; parent?: SvelteNode; + [key: string]: any; } type HTMLLike = 'Element' | 'InlineComponent' | 'Body' | 'Window'; diff --git a/packages/language-server/src/utils.ts b/packages/language-server/src/utils.ts index 34d828937..a79c49999 100644 --- a/packages/language-server/src/utils.ts +++ b/packages/language-server/src/utils.ts @@ -341,3 +341,45 @@ export function removeLineWithString(str: string, keyword: string) { const filteredLines = lines.filter((line) => !line.includes(keyword)); return filteredLines.join('\n'); } + +/** + * Traverses a string and returns the index of the end character, taking into account quotes, curlies and generic tags. + */ +export function traverseTypeString(str: string, start: number, endChar: string): number { + let singleQuoteOpen = false; + let doubleQuoteOpen = false; + let countCurlyBrace = 0; + let countAngleBracket = 0; + + for (let i = start; i < str.length; i++) { + const char = str[i]; + + if (!doubleQuoteOpen && char === "'") { + singleQuoteOpen = !singleQuoteOpen; + } else if (!singleQuoteOpen && char === '"') { + doubleQuoteOpen = !doubleQuoteOpen; + } else if (!doubleQuoteOpen && !singleQuoteOpen) { + if (char === '{') { + countCurlyBrace++; + } else if (char === '}') { + countCurlyBrace--; + } else if (char === '<') { + countAngleBracket++; + } else if (char === '>') { + countAngleBracket--; + } + } + + if ( + !singleQuoteOpen && + !doubleQuoteOpen && + countCurlyBrace === 0 && + countAngleBracket === 0 && + char === endChar + ) { + return i; + } + } + + return -1; +} diff --git a/packages/language-server/test/plugins/svelte/SveltePlugin.test.ts b/packages/language-server/test/plugins/svelte/SveltePlugin.test.ts index db5d5e7d4..2712a095c 100644 --- a/packages/language-server/test/plugins/svelte/SveltePlugin.test.ts +++ b/packages/language-server/test/plugins/svelte/SveltePlugin.test.ts @@ -12,6 +12,9 @@ import * as importPackage from '../../../src/importPackage'; import sinon from 'sinon'; import { join } from 'path'; import { pathToUrl, urlToPath } from '../../../src/utils'; +import { VERSION } from 'svelte/compiler'; + +const isSvelte5Plus = Number(VERSION.split('.')[0]) >= 5; describe('Svelte Plugin', () => { function setup( @@ -35,9 +38,11 @@ describe('Svelte Plugin', () => { const diagnostics = await plugin.getDiagnostics(document); const diagnostic = Diagnostic.create( Range.create(1, 0, 1, 21), - 'A11y: element should have an alt attribute', + isSvelte5Plus + ? ' element should have an alt attribute' + : 'A11y: element should have an alt attribute', DiagnosticSeverity.Warning, - 'a11y-missing-attribute', + isSvelte5Plus ? 'a11y_missing_attribute' : 'a11y-missing-attribute', 'svelte' ); @@ -50,9 +55,9 @@ describe('Svelte Plugin', () => { const diagnostics = await plugin.getDiagnostics(document); const diagnostic = Diagnostic.create( Range.create(0, 10, 0, 18), - 'whatever is not declared', + isSvelte5Plus ? 'Can only bind to state or props' : 'whatever is not declared', DiagnosticSeverity.Error, - 'binding-undeclared', + isSvelte5Plus ? 'invalid_binding_value' : 'binding-undeclared', 'svelte' ); diff --git a/packages/language-server/test/plugins/svelte/features/getDiagnostics.test.ts b/packages/language-server/test/plugins/svelte/features/getDiagnostics.test.ts index 8ce588264..9f7ef475b 100644 --- a/packages/language-server/test/plugins/svelte/features/getDiagnostics.test.ts +++ b/packages/language-server/test/plugins/svelte/features/getDiagnostics.test.ts @@ -12,6 +12,9 @@ import { SvelteConfig } from '../../../../src/lib/documents/configLoader'; import { CompilerWarningsSettings, LSConfigManager } from '../../../../src/ls-config'; import { pathToUrl } from '../../../../src/utils'; import { SveltePlugin } from '../../../../src/plugins'; +import { VERSION } from 'svelte/compiler'; + +const isSvelte5Plus = Number(VERSION.split('.')[0]) >= 5; describe('SveltePlugin#getDiagnostics', () => { async function expectDiagnosticsFor({ @@ -286,16 +289,14 @@ describe('SveltePlugin#getDiagnostics', () => { }), getCompiled: () => Promise.resolve({ - stats: { - warnings: [ - { - start: { line: 1, column: 0 }, - end: { line: 1, column: 0 }, - message: 'warning', - code: 123 - } - ] - } + warnings: [ + { + start: { line: 1, column: 0 }, + end: { line: 1, column: 0 }, + message: 'warning', + code: 123 + } + ] }), config: {} }) @@ -415,16 +416,14 @@ describe('SveltePlugin#getDiagnostics', () => { }), getCompiled: () => Promise.resolve({ - stats: { - warnings: [ - { - start: { line: 1, column: 0 }, - end: { line: 1, column: 0 }, - message: 'warning', - code: '123' - } - ] - } + warnings: [ + { + start: { line: 1, column: 0 }, + end: { line: 1, column: 0 }, + message: 'warning', + code: '123' + } + ] }), config: {}, settings: { 123: 'error' } @@ -460,7 +459,7 @@ describe('SveltePlugin#getDiagnostics', () => { "Component has unused export property 'name'. If it is for external reference only, please consider using `export const name`", severity: 2, source: 'svelte', - code: 'unused-export-let' + code: isSvelte5Plus ? 'unused_export_let' : 'unused-export-let' } ]); }); @@ -472,10 +471,14 @@ describe('SveltePlugin#getDiagnostics', () => { assert.deepStrictEqual(diagnostics, [ { range: { start: { line: 1, character: 4 }, end: { line: 1, character: 26 } }, - message: '$: has no effect in a module script', + message: isSvelte5Plus + ? 'Reactive declarations only exist at the top level of the instance script' + : '$: has no effect in a module script', severity: 2, source: 'svelte', - code: 'module-script-reactive-declaration' + code: isSvelte5Plus + ? 'no_reactive_declaration' + : 'module-script-reactive-declaration' } ]); }); @@ -486,7 +489,7 @@ describe('SveltePlugin#getDiagnostics', () => { assert.deepStrictEqual(diagnostics, [ { - code: 'unused-export-let', + code: isSvelte5Plus ? 'unused_export_let' : 'unused-export-let', message: "Component has unused export property 'unused1'. If it is for external reference only, please consider using `export const unused1`", range: { @@ -496,14 +499,14 @@ describe('SveltePlugin#getDiagnostics', () => { }, end: { line: 5, - character: 27 + character: isSvelte5Plus ? 20 : 27 } }, severity: 2, source: 'svelte' }, { - code: 'unused-export-let', + code: isSvelte5Plus ? 'unused_export_let' : 'unused-export-let', message: "Component has unused export property 'unused2'. If it is for external reference only, please consider using `export const unused2`", range: { @@ -513,7 +516,7 @@ describe('SveltePlugin#getDiagnostics', () => { }, end: { line: 6, - character: 27 + character: isSvelte5Plus ? 20 : 27 } }, severity: 2, diff --git a/packages/language-server/test/plugins/typescript/features/diagnostics/fixtures/$$events/expected_svelte_5.json b/packages/language-server/test/plugins/typescript/features/diagnostics/fixtures/$$events/expected_svelte_5.json new file mode 100644 index 000000000..782e41e55 --- /dev/null +++ b/packages/language-server/test/plugins/typescript/features/diagnostics/fixtures/$$events/expected_svelte_5.json @@ -0,0 +1,58 @@ +[ + { + "code": 6385, + "message": "'createEventDispatcher' is deprecated.", + "range": { + "end": { + "character": 34, + "line": 1 + }, + "start": { + "character": 13, + "line": 1 + } + }, + "severity": 4, + "source": "ts", + "tags": [2] + }, + { + "code": 6387, + "message": "The signature '(): EventDispatcher<__sveltets_2_CustomEvents<$$Events>>' of 'createEventDispatcher' is deprecated.", + "range": { + "end": { + "character": 42, + "line": 8 + }, + "start": { + "character": 21, + "line": 8 + } + }, + "severity": 4, + "source": "ts", + "tags": [2] + }, + { + "range": { + "start": { "line": 12, "character": 20 }, + "end": { "line": 12, "character": 24 } + }, + "severity": 1, + "source": "ts", + "message": "Argument of type 'boolean' is not assignable to parameter of type 'string'.", + "code": 2345, + "tags": [] + }, + { + "range": { + "start": { "line": 13, "character": 13 }, + "end": { "line": 13, "character": 20 } + }, + "severity": 1, + "source": "ts", + "message": "Argument of type '\"click\"' is not assignable to parameter of type '\"foo\"'.", + "code": 2345, + "tags": [] + } +] diff --git a/packages/language-server/test/plugins/typescript/features/diagnostics/fixtures/$$props-usage/expected_svelte_5.json b/packages/language-server/test/plugins/typescript/features/diagnostics/fixtures/$$props-usage/expected_svelte_5.json new file mode 100644 index 000000000..f98179a38 --- /dev/null +++ b/packages/language-server/test/plugins/typescript/features/diagnostics/fixtures/$$props-usage/expected_svelte_5.json @@ -0,0 +1,32 @@ +[ + { + "range": { + "start": { "line": 10, "character": 7 }, + "end": { "line": 10, "character": 16 } + }, + "severity": 1, + "source": "ts", + "message": "Type 'boolean' is not assignable to type 'string'.", + "code": 2322, + "tags": [] + }, + { + "range": { + "start": { "line": 11, "character": 43 }, + "end": { "line": 11, "character": 54 } + }, + "severity": 1, + "source": "ts", + "message": "Object literal may only specify known properties, and '\"invalidProp\"' does not exist in type 'WithBindings<{ exported1: string; exported2?: string | undefined; exported3: string; }>'.", + "code": 2353, + "tags": [] + }, + { + "range": { "start": { "line": 12, "character": 1 }, "end": { "line": 12, "character": 6 } }, + "severity": 1, + "source": "ts", + "message": "Type '{}' is missing the following properties from type 'WithBindings<{ exported1: string; exported2?: string | undefined; exported3: string; }>': exported1, exported3", + "code": 2739, + "tags": [] + } +] diff --git a/packages/language-server/test/plugins/typescript/features/diagnostics/fixtures/$store-bind/expected_svelte_5.json b/packages/language-server/test/plugins/typescript/features/diagnostics/fixtures/$store-bind/expected_svelte_5.json new file mode 100644 index 000000000..9c6757bf6 --- /dev/null +++ b/packages/language-server/test/plugins/typescript/features/diagnostics/fixtures/$store-bind/expected_svelte_5.json @@ -0,0 +1,46 @@ +[ + { + "range": { + "start": { "line": 17, "character": 24 }, + "end": { "line": 17, "character": 34 } + }, + "severity": 1, + "source": "ts", + "message": "Type 'number' is not assignable to type 'boolean'.", + "code": 2322, + "tags": [] + }, + { + "range": { + "start": { "line": 18, "character": 16 }, + "end": { "line": 18, "character": 20 } + }, + "severity": 1, + "source": "ts", + "message": "Type 'boolean' is not assignable to type 'number'.", + "code": 2322, + "tags": [] + }, + { + "range": { + "start": { "line": 19, "character": 24 }, + "end": { "line": 19, "character": 41 } + }, + "severity": 1, + "source": "ts", + "message": "Type 'number' is not assignable to type 'boolean'.", + "code": 2322, + "tags": [] + }, + { + "range": { + "start": { "line": 20, "character": 16 }, + "end": { "line": 20, "character": 20 } + }, + "severity": 1, + "source": "ts", + "message": "Type 'Binding' is not assignable to type 'Bindable'.", + "code": 2322, + "tags": [] + } +] diff --git a/packages/language-server/test/plugins/typescript/features/diagnostics/fixtures/bind-this/expected_svelte_5.json b/packages/language-server/test/plugins/typescript/features/diagnostics/fixtures/bind-this/expected_svelte_5.json new file mode 100644 index 000000000..09171f654 --- /dev/null +++ b/packages/language-server/test/plugins/typescript/features/diagnostics/fixtures/bind-this/expected_svelte_5.json @@ -0,0 +1,98 @@ +[ + { + "range": { "start": { "line": 9, "character": 6 }, "end": { "line": 9, "character": 13 } }, + "severity": 4, + "source": "ts", + "message": "'element' is declared but its value is never read.", + "code": 6133, + "tags": [1] + }, + { + "range": { + "start": { "line": 18, "character": 2 }, + "end": { "line": 18, "character": 11 } + }, + "severity": 1, + "source": "ts", + "message": "Variable 'component' is used before being assigned.", + "code": 2454, + "tags": [] + }, + { + "range": { + "start": { "line": 40, "character": 16 }, + "end": { "line": 40, "character": 23 } + }, + "severity": 1, + "source": "ts", + "message": "Type 'HTMLDivElement' is missing the following properties from type 'HTMLInputElement': accept, alt, autocomplete, capture, and 54 more.", + "code": 2740, + "tags": [] + }, + { + "range": { + "start": { "line": 41, "character": 34 }, + "end": { "line": 41, "character": 48 } + }, + "severity": 1, + "source": "ts", + "message": "Type 'Component' is not assignable to type 'OtherComponent'.\n The types of '$$prop_def.prop' are incompatible between these types.\n Type 'boolean' is not assignable to type 'string'.", + "code": 2322, + "tags": [] + }, + { + "range": { + "start": { "line": 42, "character": 35 }, + "end": { "line": 42, "character": 57 } + }, + "severity": 1, + "source": "ts", + "message": "Type 'ComponentWithFunction1' is not assignable to type 'ComponentWithFunction2'.\n Types of property 'action' are incompatible.\n Type '(a: number) => string | number' is not assignable to type '() => string'.\n Target signature provides too few arguments. Expected 1 or more, but got 0.", + "code": 2322, + "tags": [] + }, + { + "range": { + "start": { "line": 43, "character": 1 }, + "end": { "line": 43, "character": 17 } + }, + "severity": 1, + "source": "ts", + "message": "Type '{}' is not assignable to type 'PropsWithChildren<{ prop: boolean; }, any> | undefined'.", + "code": 2322, + "tags": [] + }, + { + "range": { + "start": { "line": 43, "character": 46 }, + "end": { "line": 43, "character": 60 } + }, + "severity": 1, + "source": "ts", + "message": "Type 'Component' is not assignable to type 'OtherComponent'.", + "code": 2322, + "tags": [] + }, + { + "range": { + "start": { "line": 46, "character": 45 }, + "end": { "line": 46, "character": 65 } + }, + "severity": 1, + "source": "ts", + "message": "Type 'ComponentWithGeneric' is not assignable to type 'ComponentWithGeneric'.\n Type 'boolean' is not assignable to type 'string'.", + "code": 2322, + "tags": [] + }, + { + "range": { + "start": { "line": 47, "character": 1 }, + "end": { "line": 47, "character": 17 } + }, + "severity": 1, + "source": "ts", + "message": "Type '{}' is not assignable to type 'PropsWithChildren<{ prop: boolean; }, any> | undefined'.", + "code": 2322, + "tags": [] + } +] diff --git a/packages/language-server/test/plugins/typescript/features/diagnostics/fixtures/bindings/Legacy.svelte b/packages/language-server/test/plugins/typescript/features/diagnostics/fixtures/bindings/Legacy.svelte new file mode 100644 index 000000000..1bd159644 --- /dev/null +++ b/packages/language-server/test/plugins/typescript/features/diagnostics/fixtures/bindings/Legacy.svelte @@ -0,0 +1,6 @@ + diff --git a/packages/language-server/test/plugins/typescript/features/diagnostics/fixtures/bindings/Runes.svelte b/packages/language-server/test/plugins/typescript/features/diagnostics/fixtures/bindings/Runes.svelte new file mode 100644 index 000000000..34b9e88d7 --- /dev/null +++ b/packages/language-server/test/plugins/typescript/features/diagnostics/fixtures/bindings/Runes.svelte @@ -0,0 +1,7 @@ + diff --git a/packages/language-server/test/plugins/typescript/features/diagnostics/fixtures/bindings/expected_svelte_5.json b/packages/language-server/test/plugins/typescript/features/diagnostics/fixtures/bindings/expected_svelte_5.json new file mode 100644 index 000000000..abd096989 --- /dev/null +++ b/packages/language-server/test/plugins/typescript/features/diagnostics/fixtures/bindings/expected_svelte_5.json @@ -0,0 +1,53 @@ +[ + { + "code": 2322, + "message": "Type 'Binding' is not assignable to type 'string'.", + "range": { + "end": { + "character": 20, + "line": 25 + }, + "start": { + "character": 12, + "line": 25 + } + }, + "severity": 1, + "source": "ts", + "tags": [] + }, + { + "code": 2353, + "message": "Object literal may only specify known properties, and 'only_bind' does not exist in type '{ readonly?: string | undefined; can_bind?: Bindable; }'.", + "range": { + "end": { + "character": 21, + "line": 26 + }, + "start": { + "character": 12, + "line": 26 + } + }, + "severity": 1, + "source": "ts", + "tags": [] + }, + { + "code": 2353, + "message": "Object literal may only specify known properties, and 'only_bind' does not exist in type '{ readonly?: string | undefined; can_bind?: Bindable; }'.", + "range": { + "end": { + "character": 17, + "line": 27 + }, + "start": { + "character": 8, + "line": 27 + } + }, + "severity": 1, + "source": "ts", + "tags": [] + } +] diff --git a/packages/language-server/test/plugins/typescript/features/diagnostics/fixtures/bindings/expectedv2.json b/packages/language-server/test/plugins/typescript/features/diagnostics/fixtures/bindings/expectedv2.json new file mode 100644 index 000000000..fe51488c7 --- /dev/null +++ b/packages/language-server/test/plugins/typescript/features/diagnostics/fixtures/bindings/expectedv2.json @@ -0,0 +1 @@ +[] diff --git a/packages/language-server/test/plugins/typescript/features/diagnostics/fixtures/bindings/input.svelte b/packages/language-server/test/plugins/typescript/features/diagnostics/fixtures/bindings/input.svelte new file mode 100644 index 000000000..1dc072434 --- /dev/null +++ b/packages/language-server/test/plugins/typescript/features/diagnostics/fixtures/bindings/input.svelte @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + diff --git a/packages/language-server/test/plugins/typescript/features/diagnostics/fixtures/checkjs-nostrict/component-props-js/expected_svelte_5.json b/packages/language-server/test/plugins/typescript/features/diagnostics/fixtures/checkjs-nostrict/component-props-js/expected_svelte_5.json new file mode 100644 index 000000000..b17cb454d --- /dev/null +++ b/packages/language-server/test/plugins/typescript/features/diagnostics/fixtures/checkjs-nostrict/component-props-js/expected_svelte_5.json @@ -0,0 +1,83 @@ +[ + { + "range": { "start": { "line": 6, "character": 1 }, "end": { "line": 6, "character": 9 } }, + "severity": 1, + "source": "js", + "message": "Property 'required' is missing in type '{}' but required in type 'WithBindings<{ required: string; optional1?: string; optional2?: string; }>'.", + "code": 2741, + "tags": [] + }, + { + "range": { "start": { "line": 8, "character": 57 }, "end": { "line": 8, "character": 68 } }, + "severity": 1, + "source": "js", + "message": "Object literal may only specify known properties, and '\"doesntExist\"' does not exist in type 'WithBindings<{ required: string; optional1?: string; optional2?: string; }>'.", + "code": 2353, + "tags": [] + }, + { + "range": { "start": { "line": 9, "character": 10 }, "end": { "line": 9, "character": 18 } }, + "severity": 1, + "source": "js", + "message": "Type 'boolean' is not assignable to type 'string'.", + "code": 2322, + "tags": [] + }, + { + "range": { "start": { "line": 9, "character": 26 }, "end": { "line": 9, "character": 35 } }, + "severity": 1, + "source": "js", + "message": "Type 'boolean' is not assignable to type 'string'.", + "code": 2322, + "tags": [] + }, + { + "range": { "start": { "line": 9, "character": 43 }, "end": { "line": 9, "character": 52 } }, + "severity": 1, + "source": "js", + "message": "Type 'boolean' is not assignable to type 'string'.", + "code": 2322, + "tags": [] + }, + { + "range": { "start": { "line": 10, "character": 1 }, "end": { "line": 10, "character": 9 } }, + "severity": 1, + "source": "js", + "message": "Property 'required' is missing in type '{}' but required in type 'WithBindings<{ required: string; optional1?: string; optional2?: string; }>'.", + "code": 2741, + "tags": [] + }, + { + "range": { + "start": { "line": 12, "character": 10 }, + "end": { "line": 12, "character": 18 } + }, + "severity": 1, + "source": "js", + "message": "Type 'boolean' is not assignable to type 'string'.", + "code": 2322, + "tags": [] + }, + { + "range": { + "start": { "line": 12, "character": 26 }, + "end": { "line": 12, "character": 35 } + }, + "severity": 1, + "source": "js", + "message": "Type 'boolean' is not assignable to type 'string'.", + "code": 2322, + "tags": [] + }, + { + "range": { + "start": { "line": 12, "character": 43 }, + "end": { "line": 12, "character": 52 } + }, + "severity": 1, + "source": "js", + "message": "Type 'boolean' is not assignable to type 'string'.", + "code": 2322, + "tags": [] + } +] diff --git a/packages/language-server/test/plugins/typescript/features/diagnostics/fixtures/checkjs-nostrict/component-props-ts/expected_svelte_5.json b/packages/language-server/test/plugins/typescript/features/diagnostics/fixtures/checkjs-nostrict/component-props-ts/expected_svelte_5.json new file mode 100644 index 000000000..1468ca1c4 --- /dev/null +++ b/packages/language-server/test/plugins/typescript/features/diagnostics/fixtures/checkjs-nostrict/component-props-ts/expected_svelte_5.json @@ -0,0 +1,83 @@ +[ + { + "range": { "start": { "line": 6, "character": 1 }, "end": { "line": 6, "character": 9 } }, + "severity": 1, + "source": "ts", + "message": "Property 'required' is missing in type '{}' but required in type 'WithBindings<{ required: string; optional1?: string; optional2?: string; }>'.", + "code": 2741, + "tags": [] + }, + { + "range": { "start": { "line": 8, "character": 57 }, "end": { "line": 8, "character": 68 } }, + "severity": 1, + "source": "ts", + "message": "Object literal may only specify known properties, and '\"doesntExist\"' does not exist in type 'WithBindings<{ required: string; optional1?: string; optional2?: string; }>'.", + "code": 2353, + "tags": [] + }, + { + "range": { "start": { "line": 9, "character": 10 }, "end": { "line": 9, "character": 18 } }, + "severity": 1, + "source": "ts", + "message": "Type 'boolean' is not assignable to type 'string'.", + "code": 2322, + "tags": [] + }, + { + "range": { "start": { "line": 9, "character": 26 }, "end": { "line": 9, "character": 35 } }, + "severity": 1, + "source": "ts", + "message": "Type 'boolean' is not assignable to type 'string'.", + "code": 2322, + "tags": [] + }, + { + "range": { "start": { "line": 9, "character": 43 }, "end": { "line": 9, "character": 52 } }, + "severity": 1, + "source": "ts", + "message": "Type 'boolean' is not assignable to type 'string'.", + "code": 2322, + "tags": [] + }, + { + "range": { "start": { "line": 10, "character": 1 }, "end": { "line": 10, "character": 9 } }, + "severity": 1, + "source": "ts", + "message": "Property 'required' is missing in type '{}' but required in type 'WithBindings<{ required: string; optional1?: string; optional2?: string; }>'.", + "code": 2741, + "tags": [] + }, + { + "range": { + "start": { "line": 12, "character": 10 }, + "end": { "line": 12, "character": 18 } + }, + "severity": 1, + "source": "ts", + "message": "Type 'boolean' is not assignable to type 'string'.", + "code": 2322, + "tags": [] + }, + { + "range": { + "start": { "line": 12, "character": 26 }, + "end": { "line": 12, "character": 35 } + }, + "severity": 1, + "source": "ts", + "message": "Type 'boolean' is not assignable to type 'string'.", + "code": 2322, + "tags": [] + }, + { + "range": { + "start": { "line": 12, "character": 43 }, + "end": { "line": 12, "character": 52 } + }, + "severity": 1, + "source": "ts", + "message": "Type 'boolean' is not assignable to type 'string'.", + "code": 2322, + "tags": [] + } +] diff --git a/packages/language-server/test/plugins/typescript/features/diagnostics/fixtures/checkjs/component-props-js/expected_svelte_5.json b/packages/language-server/test/plugins/typescript/features/diagnostics/fixtures/checkjs/component-props-js/expected_svelte_5.json new file mode 100644 index 000000000..89c2f2631 --- /dev/null +++ b/packages/language-server/test/plugins/typescript/features/diagnostics/fixtures/checkjs/component-props-js/expected_svelte_5.json @@ -0,0 +1,102 @@ +[ + { + "range": { "start": { "line": 6, "character": 1 }, "end": { "line": 6, "character": 9 } }, + "severity": 1, + "source": "js", + "message": "Property 'required' is missing in type '{}' but required in type 'WithBindings<{ required: string; optional1?: string | undefined; optional2?: string | undefined; }>'.", + "code": 2741, + "tags": [] + }, + { + "range": { "start": { "line": 7, "character": 10 }, "end": { "line": 7, "character": 18 } }, + "severity": 1, + "source": "js", + "message": "Type 'undefined' is not assignable to type 'string'.", + "code": 2322, + "tags": [] + }, + { + "range": { "start": { "line": 8, "character": 57 }, "end": { "line": 8, "character": 68 } }, + "severity": 1, + "source": "js", + "message": "Object literal may only specify known properties, and '\"doesntExist\"' does not exist in type 'WithBindings<{ required: string; optional1?: string | undefined; optional2?: string | undefined; }>'.", + "code": 2353, + "tags": [] + }, + { + "range": { "start": { "line": 9, "character": 10 }, "end": { "line": 9, "character": 18 } }, + "severity": 1, + "source": "js", + "message": "Type 'boolean' is not assignable to type 'string'.", + "code": 2322, + "tags": [] + }, + { + "range": { "start": { "line": 9, "character": 26 }, "end": { "line": 9, "character": 35 } }, + "severity": 1, + "source": "js", + "message": "Type 'true' is not assignable to type 'string | undefined'.", + "code": 2322, + "tags": [] + }, + { + "range": { "start": { "line": 9, "character": 43 }, "end": { "line": 9, "character": 52 } }, + "severity": 1, + "source": "js", + "message": "Type 'true' is not assignable to type 'string | undefined'.", + "code": 2322, + "tags": [] + }, + { + "range": { "start": { "line": 10, "character": 1 }, "end": { "line": 10, "character": 9 } }, + "severity": 1, + "source": "js", + "message": "Property 'required' is missing in type '{}' but required in type 'WithBindings<{ required: string; optional1?: string | undefined; optional2?: string | undefined; }>'.", + "code": 2741, + "tags": [] + }, + { + "range": { + "start": { "line": 11, "character": 10 }, + "end": { "line": 11, "character": 18 } + }, + "severity": 1, + "source": "js", + "message": "Type 'undefined' is not assignable to type 'string'.", + "code": 2322, + "tags": [] + }, + { + "range": { + "start": { "line": 12, "character": 10 }, + "end": { "line": 12, "character": 18 } + }, + "severity": 1, + "source": "js", + "message": "Type 'boolean' is not assignable to type 'string'.", + "code": 2322, + "tags": [] + }, + { + "range": { + "start": { "line": 12, "character": 26 }, + "end": { "line": 12, "character": 35 } + }, + "severity": 1, + "source": "js", + "message": "Type 'true' is not assignable to type 'string | undefined'.", + "code": 2322, + "tags": [] + }, + { + "range": { + "start": { "line": 12, "character": 43 }, + "end": { "line": 12, "character": 52 } + }, + "severity": 1, + "source": "js", + "message": "Type 'true' is not assignable to type 'string | undefined'.", + "code": 2322, + "tags": [] + } +] diff --git a/packages/language-server/test/plugins/typescript/features/diagnostics/fixtures/checkjs/component-props-ts/expected_svelte_5.json b/packages/language-server/test/plugins/typescript/features/diagnostics/fixtures/checkjs/component-props-ts/expected_svelte_5.json new file mode 100644 index 000000000..097f3edf7 --- /dev/null +++ b/packages/language-server/test/plugins/typescript/features/diagnostics/fixtures/checkjs/component-props-ts/expected_svelte_5.json @@ -0,0 +1,102 @@ +[ + { + "range": { "start": { "line": 6, "character": 1 }, "end": { "line": 6, "character": 9 } }, + "severity": 1, + "source": "ts", + "message": "Property 'required' is missing in type '{}' but required in type 'WithBindings<{ required: string; optional1?: string | undefined; optional2?: string | undefined; }>'.", + "code": 2741, + "tags": [] + }, + { + "range": { "start": { "line": 7, "character": 10 }, "end": { "line": 7, "character": 18 } }, + "severity": 1, + "source": "ts", + "message": "Type 'undefined' is not assignable to type 'string'.", + "code": 2322, + "tags": [] + }, + { + "range": { "start": { "line": 8, "character": 57 }, "end": { "line": 8, "character": 68 } }, + "severity": 1, + "source": "ts", + "message": "Object literal may only specify known properties, and '\"doesntExist\"' does not exist in type 'WithBindings<{ required: string; optional1?: string | undefined; optional2?: string | undefined; }>'.", + "code": 2353, + "tags": [] + }, + { + "range": { "start": { "line": 9, "character": 10 }, "end": { "line": 9, "character": 18 } }, + "severity": 1, + "source": "ts", + "message": "Type 'boolean' is not assignable to type 'string'.", + "code": 2322, + "tags": [] + }, + { + "range": { "start": { "line": 9, "character": 26 }, "end": { "line": 9, "character": 35 } }, + "severity": 1, + "source": "ts", + "message": "Type 'true' is not assignable to type 'string | undefined'.", + "code": 2322, + "tags": [] + }, + { + "range": { "start": { "line": 9, "character": 43 }, "end": { "line": 9, "character": 52 } }, + "severity": 1, + "source": "ts", + "message": "Type 'true' is not assignable to type 'string | undefined'.", + "code": 2322, + "tags": [] + }, + { + "range": { "start": { "line": 10, "character": 1 }, "end": { "line": 10, "character": 9 } }, + "severity": 1, + "source": "ts", + "message": "Property 'required' is missing in type '{}' but required in type 'WithBindings<{ required: string; optional1?: string | undefined; optional2?: string | undefined; }>'.", + "code": 2741, + "tags": [] + }, + { + "range": { + "start": { "line": 11, "character": 10 }, + "end": { "line": 11, "character": 18 } + }, + "severity": 1, + "source": "ts", + "message": "Type 'undefined' is not assignable to type 'string'.", + "code": 2322, + "tags": [] + }, + { + "range": { + "start": { "line": 12, "character": 10 }, + "end": { "line": 12, "character": 18 } + }, + "severity": 1, + "source": "ts", + "message": "Type 'boolean' is not assignable to type 'string'.", + "code": 2322, + "tags": [] + }, + { + "range": { + "start": { "line": 12, "character": 26 }, + "end": { "line": 12, "character": 35 } + }, + "severity": 1, + "source": "ts", + "message": "Type 'true' is not assignable to type 'string | undefined'.", + "code": 2322, + "tags": [] + }, + { + "range": { + "start": { "line": 12, "character": 43 }, + "end": { "line": 12, "character": 52 } + }, + "severity": 1, + "source": "ts", + "message": "Type 'true' is not assignable to type 'string | undefined'.", + "code": 2322, + "tags": [] + } +] diff --git a/packages/language-server/test/plugins/typescript/features/diagnostics/fixtures/component-invalid/expected_svelte_5.json b/packages/language-server/test/plugins/typescript/features/diagnostics/fixtures/component-invalid/expected_svelte_5.json new file mode 100644 index 000000000..81e4cc4cd --- /dev/null +++ b/packages/language-server/test/plugins/typescript/features/diagnostics/fixtures/component-invalid/expected_svelte_5.json @@ -0,0 +1,57 @@ +[ + { + "range": { + "start": { "line": 19, "character": 1 }, + "end": { "line": 19, "character": 11 } + }, + "severity": 1, + "source": "ts", + "message": "Argument of type 'typeof DoesntWork' is not assignable to parameter of type 'ConstructorOfATypedSvelteComponent'.\n Type 'DoesntWork' is missing the following properties from type 'ATypedSvelteComponent': $$prop_def, $$events_def, $$slot_def, $on\n\nPossible causes:\n- You use the instance type of a component where you should use the constructor type\n- Type definitions are missing for this Svelte Component. If you are using Svelte 3.31+, use SvelteComponentTyped to add a definition:\n import type { SvelteComponentTyped } from \"svelte\";\n class ComponentName extends SvelteComponentTyped<{propertyName: string;}> {}", + "code": 2345, + "tags": [] + }, + { + "range": { + "start": { "line": 20, "character": 10 }, + "end": { "line": 20, "character": 25 } + }, + "severity": 1, + "source": "ts", + "message": "Type 'boolean' is not assignable to type 'Binding'.", + "code": 2322, + "tags": [] + }, + { + "range": { + "start": { "line": 21, "character": 24 }, + "end": { "line": 21, "character": 34 } + }, + "severity": 1, + "source": "ts", + "message": "Argument of type 'typeof DoesntWork' is not assignable to parameter of type 'ConstructorOfATypedSvelteComponent'.\n\nPossible causes:\n- You use the instance type of a component where you should use the constructor type\n- Type definitions are missing for this Svelte Component. If you are using Svelte 3.31+, use SvelteComponentTyped to add a definition:\n import type { SvelteComponentTyped } from \"svelte\";\n class ComponentName extends SvelteComponentTyped<{propertyName: string;}> {}", + "code": 2345, + "tags": [] + }, + { + "range": { + "start": { "line": 24, "character": 1 }, + "end": { "line": 24, "character": 11 } + }, + "severity": 1, + "source": "ts", + "message": "Argument of type 'typeof DoesntWork' is not assignable to parameter of type 'ConstructorOfATypedSvelteComponent'.\n\nPossible causes:\n- You use the instance type of a component where you should use the constructor type\n- Type definitions are missing for this Svelte Component. If you are using Svelte 3.31+, use SvelteComponentTyped to add a definition:\n import type { SvelteComponentTyped } from \"svelte\";\n class ComponentName extends SvelteComponentTyped<{propertyName: string;}> {}", + "code": 2345, + "tags": [] + }, + { + "range": { + "start": { "line": 27, "character": 24 }, + "end": { "line": 27, "character": 34 } + }, + "severity": 1, + "source": "ts", + "message": "Argument of type 'typeof DoesntWork' is not assignable to parameter of type 'ConstructorOfATypedSvelteComponent'.\n\nPossible causes:\n- You use the instance type of a component where you should use the constructor type\n- Type definitions are missing for this Svelte Component. If you are using Svelte 3.31+, use SvelteComponentTyped to add a definition:\n import type { SvelteComponentTyped } from \"svelte\";\n class ComponentName extends SvelteComponentTyped<{propertyName: string;}> {}", + "code": 2345, + "tags": [] + } +] diff --git a/packages/language-server/test/plugins/typescript/features/diagnostics/fixtures/custom-types/expected_svelte_5.json b/packages/language-server/test/plugins/typescript/features/diagnostics/fixtures/custom-types/expected_svelte_5.json new file mode 100644 index 000000000..ae37bf13f --- /dev/null +++ b/packages/language-server/test/plugins/typescript/features/diagnostics/fixtures/custom-types/expected_svelte_5.json @@ -0,0 +1,103 @@ +[ + { + "range": { "start": { "line": 4, "character": 26 }, "end": { "line": 4, "character": 27 } }, + "severity": 4, + "source": "ts", + "message": "Parameter 'e' implicitly has an 'any' type, but a better type may be inferred from usage.", + "code": 7044, + "tags": [] + }, + { + "range": { + "start": { "line": 22, "character": 26 }, + "end": { "line": 22, "character": 27 } + }, + "severity": 4, + "source": "ts", + "message": "Parameter 'e' implicitly has an 'any' type, but a better type may be inferred from usage.", + "code": 7044, + "tags": [] + }, + { + "range": { "start": { "line": 3, "character": 5 }, "end": { "line": 3, "character": 19 } }, + "severity": 1, + "source": "ts", + "message": "Object literal may only specify known properties, and '\"owntypefromold\"' does not exist in type 'HTMLProps<\"div\", HTMLAttributes>'.", + "code": 2353, + "tags": [] + }, + { + "range": { "start": { "line": 4, "character": 8 }, "end": { "line": 4, "character": 23 } }, + "severity": 1, + "source": "ts", + "message": "Object literal may only specify known properties, and '\"on:ownclickfromold\"' does not exist in type 'HTMLProps<\"div\", HTMLAttributes>'.", + "code": 2353, + "tags": [] + }, + { + "range": { + "start": { "line": 15, "character": 13 }, + "end": { "line": 15, "character": 22 } + }, + "severity": 1, + "source": "ts", + "message": "Type 'boolean' is not assignable to type 'string'.", + "code": 2322, + "tags": [] + }, + { + "range": { + "start": { "line": 16, "character": 13 }, + "end": { "line": 16, "character": 23 } + }, + "severity": 1, + "source": "ts", + "message": "Object literal may only specify known properties, and '\"doesnexist\"' does not exist in type '{ attribute?: string; }'.", + "code": 2353, + "tags": [] + }, + { + "range": { + "start": { "line": 19, "character": 5 }, + "end": { "line": 19, "character": 12 } + }, + "severity": 1, + "source": "ts", + "message": "Type 'boolean' is not assignable to type 'string'.", + "code": 2322, + "tags": [] + }, + { + "range": { + "start": { "line": 20, "character": 5 }, + "end": { "line": 20, "character": 19 } + }, + "severity": 1, + "source": "ts", + "message": "Object literal may only specify known properties, and '\"owntypefromold\"' does not exist in type 'HTMLProps<\"div\", HTMLAttributes>'.", + "code": 2353, + "tags": [] + }, + { + "range": { + "start": { "line": 21, "character": 34 }, + "end": { "line": 21, "character": 39 } + }, + "severity": 1, + "source": "ts", + "message": "Property 'wrong' does not exist on type '{ foo: string; }'.", + "code": 2339, + "tags": [] + }, + { + "range": { + "start": { "line": 22, "character": 8 }, + "end": { "line": 22, "character": 23 } + }, + "severity": 1, + "source": "ts", + "message": "Object literal may only specify known properties, and '\"on:ownclickfromold\"' does not exist in type 'HTMLProps<\"div\", HTMLAttributes>'.", + "code": 2353, + "tags": [] + } +] diff --git a/packages/language-server/test/plugins/typescript/features/diagnostics/fixtures/each/expected_svelte_5.json b/packages/language-server/test/plugins/typescript/features/diagnostics/fixtures/each/expected_svelte_5.json new file mode 100644 index 000000000..6c90ac01b --- /dev/null +++ b/packages/language-server/test/plugins/typescript/features/diagnostics/fixtures/each/expected_svelte_5.json @@ -0,0 +1,36 @@ +[ + { + "range": { + "start": { + "line": 29, + "character": 7 + }, + "end": { + "line": 29, + "character": 24 + } + }, + "severity": 1, + "source": "ts", + "message": "Argument of type '{}' is not assignable to parameter of type 'ArrayLike | Iterable'.", + "code": 2345, + "tags": [] + }, + { + "range": { + "start": { + "line": 33, + "character": 7 + }, + "end": { + "line": 33, + "character": 24 + } + }, + "severity": 1, + "source": "ts", + "message": "Argument of type 'number' is not assignable to parameter of type 'ArrayLike | Iterable'.", + "code": 2345, + "tags": [] + } +] diff --git a/packages/language-server/test/plugins/typescript/features/diagnostics/fixtures/parser-error/expected_svelte_5.json b/packages/language-server/test/plugins/typescript/features/diagnostics/fixtures/parser-error/expected_svelte_5.json new file mode 100644 index 000000000..c0fcc5b6d --- /dev/null +++ b/packages/language-server/test/plugins/typescript/features/diagnostics/fixtures/parser-error/expected_svelte_5.json @@ -0,0 +1,9 @@ +[ + { + "range": { "start": { "line": 1, "character": 0 }, "end": { "line": 1, "character": 0 } }, + "severity": 1, + "source": "js", + "message": "A component can have a single top-level `