Skip to content

Commit

Permalink
(feat) support ts 4.7 group aware organize import (#1515)
Browse files Browse the repository at this point in the history
Also leverage group aware to not merge imports in module and instance (#1508)
  • Loading branch information
jasonlyu123 committed Jun 19, 2022
1 parent 5922491 commit e3951f8
Show file tree
Hide file tree
Showing 16 changed files with 268 additions and 101 deletions.
Expand Up @@ -118,13 +118,17 @@ export class CodeActionsProviderImpl implements CodeActionsProvider {
}
)
).semi ?? true;
const documentUseLf =
document.getText().includes('\n') && !document.getText().includes('\r\n');

const changes = lang.organizeImports(
{
fileName: tsDoc.filePath,
type: 'file',
skipDestructiveCodeActions
},
{
newLineCharacter: documentUseLf ? '\n' : ts.sys.newLine,
semicolons: useSemicolons
? ts.SemicolonPreference.Insert
: ts.SemicolonPreference.Remove
Expand Down Expand Up @@ -184,11 +188,16 @@ export class CodeActionsProviderImpl implements CodeActionsProvider {
);

if (range.end.character > 0) {
const endLine = getLineAtPosition(range.start, document.getText());
const isIndent = !endLine.substring(0, range.start.character).trim();
const endLine = getLineAtPosition(range.end, document.getText());
const isIndent = !endLine.substring(0, range.end.character).trim();

if (isIndent && endLine.trim()) {
range.end.character = 0;
if (isIndent) {
const trimmedEndLine = endLine.trim();

// imports that would be removed by the next delete edit
if (trimmedEndLine && !trimmedEndLine.startsWith('import')) {
range.end.character = 0;
}
}
}

Expand Down
Expand Up @@ -589,9 +589,7 @@ function test(useNewTransformation: boolean) {
{
edits: [
{
// eslint-disable-next-line max-len
newText:
"import A from './A';\n import { c } from './c';\n",
newText: "import { c } from './c';\n",
range: {
start: {
line: 1,
Expand All @@ -604,7 +602,7 @@ function test(useNewTransformation: boolean) {
}
},
{
newText: '',
newText: "import A from './A';\n",
range: {
start: {
line: 6,
Expand Down Expand Up @@ -666,20 +664,7 @@ function test(useNewTransformation: boolean) {
edits: [
{
newText:
"import { _,_d } from 'svelte-i18n';\n import { _e } from 'svelte-i18n1';\n",
range: {
end: {
character: 0,
line: 2
},
start: {
character: 2,
line: 1
}
}
},
{
newText: '',
"import { _d } from 'svelte-i18n';\n import { _e } from 'svelte-i18n1';\n",
range: {
end: {
character: 2,
Expand Down Expand Up @@ -917,6 +902,70 @@ function test(useNewTransformation: boolean) {
assert.deepStrictEqual(codeActions, []);
});

it('organize imports aware of groups', async () => {
const { provider, document } = setup('organize-imports-group.svelte');

const codeActions = await provider.getCodeActions(
document,
Range.create(Position.create(1, 4), Position.create(1, 5)),
{
diagnostics: [],
only: [CodeActionKind.SourceOrganizeImports]
}
);

(<TextDocumentEdit>codeActions[0]?.edit?.documentChanges?.[0])?.edits.forEach(
(edit) => (edit.newText = harmonizeNewLines(edit.newText))
);

assert.deepStrictEqual(codeActions, [
{
edit: {
documentChanges: [
{
edits: [
{
newText:
"import { } from 'svelte/transition';\n" +
" import { } from './codeaction-checkJs.svelte';\n",
range: {
end: {
character: 4,
line: 4
},
start: {
character: 4,
line: 3
}
}
},
{
newText: '',
range: {
end: {
character: 0,
line: 5
},
start: {
character: 4,
line: 4
}
}
}
],
textDocument: {
uri: getUri('organize-imports-group.svelte'),
version: null
}
}
]
},
kind: 'source.organizeImports',
title: 'Organize Imports'
}
]);
});

it('should do extract into const refactor', async () => {
const { provider, document } = setup('codeactions.svelte');

Expand Down
@@ -0,0 +1,6 @@
<script>
import { } from 'svelte';
import { } from './codeaction-checkJs.svelte';
import { } from 'svelte/transition';
</script>
3 changes: 2 additions & 1 deletion packages/svelte2tsx/src/svelte2tsx/index.ts
Expand Up @@ -372,7 +372,8 @@ export function svelte2tsx(
scriptTag,
events,
implicitStoreValues,
options.mode
options.mode,
/**hasModuleScripts */ !!moduleScriptTag
);
uses$$props = uses$$props || res.uses$$props;
uses$$restProps = uses$$restProps || res.uses$$restProps;
Expand Down
Expand Up @@ -8,9 +8,23 @@ export function handleImportDeclaration(
node: ts.ImportDeclaration,
str: MagicString,
astOffset: number,
scriptStart: number
scriptStart: number,
sourceFile: ts.SourceFile
) {
const scanner = ts.createScanner(
sourceFile.languageVersion,
/*skipTrivia*/ false,
sourceFile.languageVariant
);

const comments = ts.getLeadingCommentRanges(node.getFullText(), 0) ?? [];
if (
!comments.some((comment) => comment.hasTrailingNewLine) &&
isNewGroup(sourceFile, node, scanner)
) {
str.appendRight(node.getStart() + astOffset, '\n');
}

for (const comment of comments) {
const commentEnd = node.pos + comment.end + astOffset;
str.move(node.pos + comment.pos + astOffset, commentEnd, scriptStart + 1);
Expand All @@ -23,5 +37,34 @@ export function handleImportDeclaration(
str.move(node.getStart() + astOffset, node.end + astOffset, scriptStart + 1);
//add in a \n
const originalEndChar = str.original[node.end + astOffset - 1];

str.overwrite(node.end + astOffset - 1, node.end + astOffset, originalEndChar + '\n');
}

/**
* adopted from https://github.com/microsoft/TypeScript/blob/6e0447fdf165b1cec9fc80802abcc15bd23a268f/src/services/organizeImports.ts#L111
*/
function isNewGroup(
sourceFile: ts.SourceFile,
topLevelImportDecl: ts.ImportDeclaration,
scanner: ts.Scanner
) {
const startPos = topLevelImportDecl.getFullStart();
const endPos = topLevelImportDecl.getStart();
scanner.setText(sourceFile.text, startPos, endPos - startPos);

let numberOfNewLines = 0;
while (scanner.getTokenPos() < endPos) {
const tokenKind = scanner.scan();

if (tokenKind === ts.SyntaxKind.NewLineTrivia) {
numberOfNewLines++;

if (numberOfNewLines >= 2) {
return true;
}
}
}

return false;
}
Expand Up @@ -38,7 +38,8 @@ export function processInstanceScriptContent(
script: Node,
events: ComponentEvents,
implicitStoreValues: ImplicitStoreValues,
mode: 'ts' | 'tsx' | 'dts'
mode: 'ts' | 'tsx' | 'dts',
hasModuleScript: boolean
): InstanceScriptProcessResult {
const htmlx = str.original;
const scriptContent = htmlx.substring(script.content.start, script.content.end);
Expand Down Expand Up @@ -284,7 +285,7 @@ export function processInstanceScriptContent(
}

if (ts.isImportDeclaration(node)) {
handleImportDeclaration(node, str, astOffset, script.start);
handleImportDeclaration(node, str, astOffset, script.start, tsAst);

// Check if import is the event dispatcher
events.checkIfImportIsEventDispatcher(node);
Expand Down Expand Up @@ -376,7 +377,9 @@ export function processInstanceScriptContent(
.filter(ts.isImportDeclaration)
.sort((a, b) => a.end - b.end)[0];
if (firstImport) {
str.appendRight(firstImport.getStart() + astOffset, '\n');
// ensure it's in a newline.
// if file has module script ensure an empty line to separate imports
str.appendRight(firstImport.getStart() + astOffset, '\n' + (hasModuleScript ? '\n' : ''));
}

if (mode === 'dts') {
Expand Down

0 comments on commit e3951f8

Please sign in to comment.