Skip to content

Commit

Permalink
hack for auto import completion mapping (#317)
Browse files Browse the repository at this point in the history
  • Loading branch information
jasonlyu123 committed Jul 17, 2020
1 parent 4e11f13 commit d3a81d9
Show file tree
Hide file tree
Showing 12 changed files with 83 additions and 29 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -203,12 +203,19 @@ export class CompletionsProviderImpl implements CompletionsProvider<CompletionEn
}

const actions = detail?.codeActions;
const isImport = !!detail?.source;

if (actions) {
const edit: TextEdit[] = [];

for (const action of actions) {
for (const change of action.changes) {
edit.push(...this.codeActionChangesToTextEdit(document, fragment, change));
edit.push(...this.codeActionChangesToTextEdit(
document,
fragment,
change,
isImport
));
}
}

Expand Down Expand Up @@ -241,16 +248,18 @@ export class CompletionsProviderImpl implements CompletionsProvider<CompletionEn
doc: Document,
fragment: SvelteSnapshotFragment,
changes: ts.FileTextChanges,
isImport: boolean,
): TextEdit[] {
return changes.textChanges.map((change) =>
this.codeActionChangeToTextEdit(doc, fragment, change),
this.codeActionChangeToTextEdit(doc, fragment, change, isImport),
);
}

private codeActionChangeToTextEdit(
doc: Document,
fragment: SvelteSnapshotFragment,
change: ts.TextChange,
isImport: boolean,
): TextEdit {
change.newText = this.changeSvelteComponentName(change.newText);

Expand All @@ -264,28 +273,58 @@ export class CompletionsProviderImpl implements CompletionsProvider<CompletionEn
}

const { span } = change;
// prevent newText from being placed like this: <script>import {} from ''
if (span.start === 0) {
change.newText = ts.sys.newLine + change.newText;

const virutalRange = convertRange(fragment, span);
let range: Range;
const isNewImport = isImport && virutalRange.start.character === 0;

// Since new import always can't be mapped, we'll have special treatment here
// but only hack this when there is multiple line in script
if (isNewImport && virutalRange.start.line > 1) {
range = this.mapRangeForNewImport(fragment, virutalRange);
} else {
range = mapRangeToOriginal(fragment, virutalRange);
}

let range = mapRangeToOriginal(fragment, convertRange(fragment, span));
// If range is somehow not mapped in parent or the import is mapped wrong,
// If range is somehow not mapped in parent,
// the import is mapped wrong or is outside script tag,
// use script starting point instead.
// This happens among other things if the completion is the first import of the file.
if (
range.start.line === -1 ||
(range.start.line === 0 && range.start.character <= 1 && span.length === 0)
(range.start.line === 0 && range.start.character <= 1 && span.length === 0) ||
doc.offsetAt(range.start) > scriptTagInfo.end
) {
range = convertRange(doc, {
start: scriptTagInfo.start,
length: span.length,
});
}
// prevent newText from being placed like this: <script>import {} from ''
if (range.start.line === 0) {
change.newText = ts.sys.newLine + change.newText;
}

return TextEdit.replace(range, change.newText);
}

private mapRangeForNewImport(
fragment: SvelteSnapshotFragment,
virtualRange: Range
) {
const sourceMapableRange = this.offsetLinesAndMovetoStartOfLine(virtualRange, -1);
const mappableRange = mapRangeToOriginal(
fragment, sourceMapableRange);
return this.offsetLinesAndMovetoStartOfLine(mappableRange, 1);
}

private offsetLinesAndMovetoStartOfLine({ start, end }: Range, offsetLines: number) {
return Range.create(
Position.create(start.line + offsetLines, 0),
Position.create(end.line + offsetLines, 0)
);
}

private isSvelteComponentImport(className: string) {
return className.endsWith('__SvelteComponent_');
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -191,8 +191,8 @@ describe('CodeActionsProvider', () => {
},
},
textRange: {
pos: 129,
end: 163,
pos: 130,
end: 164,
},
},
],
Expand Down Expand Up @@ -281,8 +281,8 @@ describe('CodeActionsProvider', () => {
},
},
textRange: {
pos: 129,
end: 163,
pos: 130,
end: 164,
},
},
],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -258,7 +258,7 @@ describe('CompletionProviderImpl', () => {

assert.deepEqual(
additionalTextEdits![0]?.range,
Range.create(Position.create(0, 8), Position.create(0, 8)),
Range.create(Position.create(2, 0), Position.create(2, 0)),
);
});

Expand All @@ -285,7 +285,7 @@ describe('CompletionProviderImpl', () => {

assert.strictEqual(
harmonizeNewLines(additionalTextEdits![0]?.newText),
`import { blubb } from './definitions';${newLine}`,
`${newLine}import { blubb } from './definitions';${newLine}`,
);

assert.deepEqual(
Expand Down
7 changes: 7 additions & 0 deletions packages/svelte2tsx/src/svelte2tsx.ts
Original file line number Diff line number Diff line change
Expand Up @@ -792,6 +792,13 @@ function processInstanceScriptContent(str: MagicString, script: Node): InstanceS
}
}

const firstImport = tsAst.statements
.filter(ts.isImportDeclaration)
.sort((a, b) => a.end - b.end)[0];
if (firstImport) {
str.appendRight(firstImport.getStart() + astOffset, '\n');
}

return {
exportedNames,
uses$$props,
Expand Down
3 changes: 2 additions & 1 deletion packages/svelte2tsx/test/sourcemaps/repl.html
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@
chapter: await res.json()
};
}
;<></>;import Repl from '@sveltejs/svelte-repl';
;<></>;
import Repl from '@sveltejs/svelte-repl';
import { getContext } from 'svelte';
import ScreenToggle from '../../../components/ScreenToggle.svelte';
import TableOfContents from './_TableOfContents.svelte';
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
<></>;import { readable } from 'svelte/store';
<></>;
import { readable } from 'svelte/store';
function render() {


Expand All @@ -16,4 +17,4 @@ return { props: {}, slots: {} }}
export default class Input__SvelteComponent_ {
$$prop_def = __sveltets_partial(render().props)
$$slot_def = render().slots
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
<></>;import Test from './Test.svelte';
<></>;
import Test from './Test.svelte';
function render() {


Expand All @@ -10,4 +11,4 @@ return { props: {}, slots: {} }}
export default class Input__SvelteComponent_ {
$$prop_def = __sveltets_partial(render().props)
$$slot_def = render().slots
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
<></>;import { a as b } from "./test.svelte"
<></>;
import { a as b } from "./test.svelte"
import * as c from "b.ts"
function render() {

Expand All @@ -14,4 +15,4 @@ return { props: {world: world}, slots: {} }}
export default class Input__SvelteComponent_ {
$$prop_def = __sveltets_partial(render().props)
$$slot_def = render().slots
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
<></>;import Test from './Test.svelte';
<></>;
import Test from './Test.svelte';
function render() {


Expand All @@ -11,4 +12,4 @@ return { props: {}, slots: {} }}
export default class Input__SvelteComponent_ {
$$prop_def = __sveltets_partial(render().props)
$$slot_def = render().slots
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
<></>;import { writable } from 'svelte/store';
<></>;
import { writable } from 'svelte/store';
function render() {


Expand Down Expand Up @@ -36,4 +37,4 @@ return { props: {}, slots: {} }}
export default class Input__SvelteComponent_ {
$$prop_def = __sveltets_partial(render().props)
$$slot_def = render().slots
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
<></>;import { writable } from 'svelte/store';
<></>;
import { writable } from 'svelte/store';
function render() {


Expand All @@ -13,4 +14,4 @@ return { props: {}, slots: {} }}
export default class Input__SvelteComponent_ {
$$prop_def = __sveltets_partial(render().props)
$$slot_def = render().slots
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
<></>;import { writable } from 'svelte/store';
<></>;
import { writable } from 'svelte/store';
function render() {


Expand All @@ -15,4 +16,4 @@ return { props: {}, slots: {} }}
export default class Input__SvelteComponent_ {
$$prop_def = __sveltets_partial(render().props)
$$slot_def = render().slots
}
}

0 comments on commit d3a81d9

Please sign in to comment.