[Feature] - Automatically create sort groups based on newlines (#48330)

Co-authored-by: Jake Bailey <5341706+jakebailey@users.noreply.github.com>
This commit is contained in:
Minh Quy
2022-04-05 20:53:19 +02:00
committed by GitHub
parent f654f18d86
commit 6e0447fdf1
9 changed files with 141 additions and 42 deletions

View File

@@ -15,7 +15,6 @@ namespace ts.OrganizeImports {
preferences: UserPreferences,
skipDestructiveCodeActions?: boolean
) {
const changeTracker = textChanges.ChangeTracker.fromContext({ host, formatContext, preferences });
const coalesceAndOrganizeImports = (importGroup: readonly ImportDeclaration[]) => stableSort(
@@ -23,8 +22,8 @@ namespace ts.OrganizeImports {
(s1, s2) => compareImportsOrRequireStatements(s1, s2));
// All of the old ImportDeclarations in the file, in syntactic order.
const topLevelImportDecls = sourceFile.statements.filter(isImportDeclaration);
organizeImportsWorker(topLevelImportDecls, coalesceAndOrganizeImports);
const topLevelImportGroupDecls = groupImportsByNewlineContiguous(sourceFile, sourceFile.statements.filter(isImportDeclaration));
topLevelImportGroupDecls.forEach(importGroupDecl => organizeImportsWorker(importGroupDecl, coalesceAndOrganizeImports));
// All of the old ExportDeclarations in the file, in syntactic order.
const topLevelExportDecls = sourceFile.statements.filter(isExportDeclaration);
@@ -33,8 +32,8 @@ namespace ts.OrganizeImports {
for (const ambientModule of sourceFile.statements.filter(isAmbientModule)) {
if (!ambientModule.body) continue;
const ambientModuleImportDecls = ambientModule.body.statements.filter(isImportDeclaration);
organizeImportsWorker(ambientModuleImportDecls, coalesceAndOrganizeImports);
const ambientModuleImportGroupDecls = groupImportsByNewlineContiguous(sourceFile, ambientModule.body.statements.filter(isImportDeclaration));
ambientModuleImportGroupDecls.forEach(importGroupDecl => organizeImportsWorker(importGroupDecl, coalesceAndOrganizeImports));
const ambientModuleExportDecls = ambientModule.body.statements.filter(isExportDeclaration);
organizeImportsWorker(ambientModuleExportDecls, coalesceExports);
@@ -88,6 +87,48 @@ namespace ts.OrganizeImports {
}
}
function groupImportsByNewlineContiguous(sourceFile: SourceFile, importDecls: ImportDeclaration[]): ImportDeclaration[][] {
const scanner = createScanner(sourceFile.languageVersion, /*skipTrivia*/ false, sourceFile.languageVariant);
const groupImports: ImportDeclaration[][] = [];
let groupIndex = 0;
for (const topLevelImportDecl of importDecls) {
if (isNewGroup(sourceFile, topLevelImportDecl, scanner)) {
groupIndex++;
}
if (!groupImports[groupIndex]) {
groupImports[groupIndex] = [];
}
groupImports[groupIndex].push(topLevelImportDecl);
}
return groupImports;
}
// a new group is created if an import includes at least two new line
// new line from multi-line comment doesn't count
function isNewGroup(sourceFile: SourceFile, topLevelImportDecl: ImportDeclaration, scanner: 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 === SyntaxKind.NewLineTrivia) {
numberOfNewLines++;
if (numberOfNewLines >= 2) {
return true;
}
}
}
return false;
}
function removeUnusedImports(oldImports: readonly ImportDeclaration[], sourceFile: SourceFile, program: Program, skipDestructiveCodeActions: boolean | undefined) {
// As a precaution, consider unused import detection to be destructive (GH #43051)
if (skipDestructiveCodeActions) {

View File

@@ -679,23 +679,6 @@ import "lib1";
{ path: "/lib1.ts", content: "" },
{ path: "/lib2.ts", content: "" });
testOrganizeImports("SortComments",
/*skipDestructiveCodeActions*/ false,
{
path: "/test.ts",
content: `
// Header
import "lib3";
// Comment2
import "lib2";
// Comment1
import "lib1";
`,
},
{ path: "/lib1.ts", content: "" },
{ path: "/lib2.ts", content: "" },
{ path: "/lib3.ts", content: "" });
testOrganizeImports("AmbientModule",
/*skipDestructiveCodeActions*/ false,
{