Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { RawSourceMap, SourceMapConsumer } from 'source-map';
import svelte2tsx from 'svelte2tsx';
import svelte2tsx, { IExportedNames } from 'svelte2tsx';
import ts from 'typescript';
import { Position, Range } from 'vscode-languageserver';
import {
Expand Down Expand Up @@ -82,17 +82,22 @@ export namespace DocumentSnapshot {
* @param options options that apply to the svelte document
*/
export function fromDocument(document: Document, options: SvelteSnapshotOptions) {
const { tsxMap, text, parserError, nrPrependedLines, scriptKind } = preprocessSvelteFile(
document,
options,
);
const {
tsxMap,
text,
exportedNames,
parserError,
nrPrependedLines,
scriptKind,
} = preprocessSvelteFile(document, options);

return new SvelteDocumentSnapshot(
document,
parserError,
scriptKind,
text,
nrPrependedLines,
exportedNames,
tsxMap,
);
}
Expand Down Expand Up @@ -121,6 +126,7 @@ function preprocessSvelteFile(document: Document, options: SvelteSnapshotOptions
let parserError: ParserError | null = null;
let nrPrependedLines = 0;
let text = document.getText();
let exportedNames: IExportedNames = { has: () => false };

const scriptKind = [
getScriptKindFromAttributes(document.scriptInfo?.attributes ?? {}),
Expand All @@ -137,6 +143,7 @@ function preprocessSvelteFile(document: Document, options: SvelteSnapshotOptions
});
text = tsx.code;
tsxMap = tsx.map;
exportedNames = tsx.exportedNames;
if (tsxMap) {
tsxMap.sources = [document.uri];

Expand Down Expand Up @@ -164,7 +171,7 @@ function preprocessSvelteFile(document: Document, options: SvelteSnapshotOptions
text = document.scriptInfo ? document.scriptInfo.content : '';
}

return { tsxMap, text, parserError, nrPrependedLines, scriptKind };
return { tsxMap, text, exportedNames, parserError, nrPrependedLines, scriptKind };
}

/**
Expand All @@ -181,6 +188,7 @@ export class SvelteDocumentSnapshot implements DocumentSnapshot {
public readonly scriptKind: ts.ScriptKind,
private readonly text: string,
private readonly nrPrependedLines: number,
private readonly exportedNames: IExportedNames,
private readonly tsxMap?: RawSourceMap,
) {}

Expand All @@ -204,6 +212,10 @@ export class SvelteDocumentSnapshot implements DocumentSnapshot {
return positionAt(offset, this.text);
}

hasProp(name: string): boolean {
return this.exportedNames.has(name);
}

async getFragment() {
if (!this.fragment) {
const uri = pathToUrl(this.filePath);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { Document, mapDiagnosticToOriginal, getTextInRange } from '../../../lib/
import { DiagnosticsProvider } from '../../interfaces';
import { LSAndTSDocResolver } from '../LSAndTSDocResolver';
import { convertRange, mapSeverity } from '../utils';
import { SvelteDocumentSnapshot } from '../DocumentSnapshot';

export class DiagnosticsProviderImpl implements DiagnosticsProvider {
constructor(private readonly lsAndTsDocResolver: LSAndTSDocResolver) {}
Expand Down Expand Up @@ -43,7 +44,7 @@ export class DiagnosticsProviderImpl implements DiagnosticsProvider {
}))
.map((diagnostic) => mapDiagnosticToOriginal(fragment, diagnostic))
.filter(hasNoNegativeLines)
.filter(isNoFalsePositive(document.getText()));
.filter(isNoFalsePositive(document.getText(), tsDoc));
}

private getLSAndTSDoc(document: Document) {
Expand All @@ -60,12 +61,12 @@ function hasNoNegativeLines(diagnostic: Diagnostic): boolean {
return diagnostic.range.start.line >= 0 && diagnostic.range.end.line >= 0;
}

function isNoFalsePositive(text: string) {
function isNoFalsePositive(text: string, tsDoc: SvelteDocumentSnapshot) {
return (diagnostic: Diagnostic) => {
return (
isNoJsxCannotHaveMultipleAttrsError(diagnostic) &&
isNoUnusedLabelWarningForReactiveStatement(diagnostic) &&
isNoUsedBeforeAssigned(diagnostic, text)
isNoUsedBeforeAssigned(diagnostic, text, tsDoc)
);
};
}
Expand All @@ -75,13 +76,16 @@ function isNoFalsePositive(text: string) {
* without assigning a value in strict mode. Should not throw an error here
* but on the component-user-side ("you did not set a required prop").
*/
function isNoUsedBeforeAssigned(diagnostic: Diagnostic, text: string): boolean {
function isNoUsedBeforeAssigned(
diagnostic: Diagnostic,
text: string,
tsDoc: SvelteDocumentSnapshot,
): boolean {
if (diagnostic.code !== 2454) {
return true;
}

const exportLetRegex = new RegExp(`export\\s+let\\s+${getTextInRange(diagnostic.range, text)}`);
return !exportLetRegex.test(text);
return !tsDoc.hasProp(getTextInRange(diagnostic.range, text));
}

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
<script lang="typescript">
export let noUsedBeforeDeclare: number;
export let noUsedBeforeDeclare: number, anotherUsed: boolean;
const blubb = 2;
$: bla = blubb * 2;
</script>
<p on:click on:click></p>
{bla}
{noUsedBeforeDeclare}
{noUsedBeforeDeclare}
{anotherUsed}
11 changes: 8 additions & 3 deletions packages/svelte2tsx/index.d.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
type SvelteCompiledToTsx = {
code: string,
map: import("magic-string").SourceMap
export interface SvelteCompiledToTsx {
code: string;
map: import("magic-string").SourceMap;
exportedNames: IExportedNames;
}

export interface IExportedNames {
has(name: string): boolean;
}

export default function svelte2tsx(
Expand Down
23 changes: 15 additions & 8 deletions packages/svelte2tsx/src/nodes/ExportedNames.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,18 @@
export class ExportedNames extends Map<
string,
{
type?: string;
identifierText?: string;
required?: boolean;
}
> {
// eslint-disable-next-line @typescript-eslint/interface-name-prefix
export interface IExportedNames {
has(name: string): boolean;
}

export class ExportedNames
extends Map<
string,
{
type?: string;
identifierText?: string;
required?: boolean;
}
>
implements IExportedNames {
/**
* Creates a string from the collected props
*
Expand Down
1 change: 1 addition & 0 deletions packages/svelte2tsx/src/svelte2tsx.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1032,5 +1032,6 @@ export function svelte2tsx(
return {
code: str.toString(),
map: str.generateMap({ hires: true, source: options?.filename }),
exportedNames
};
}