diff --git a/src/services/organizeImports.ts b/src/services/organizeImports.ts
index d01f2eae5f6d6..7533a54893397 100644
--- a/src/services/organizeImports.ts
+++ b/src/services/organizeImports.ts
@@ -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) {
diff --git a/src/testRunner/unittests/services/organizeImports.ts b/src/testRunner/unittests/services/organizeImports.ts
index f3b222bb76791..4ddd1b608d003 100644
--- a/src/testRunner/unittests/services/organizeImports.ts
+++ b/src/testRunner/unittests/services/organizeImports.ts
@@ -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,
{
diff --git a/tests/baselines/reference/organizeImports/SortComments.ts b/tests/baselines/reference/organizeImports/SortComments.ts
deleted file mode 100644
index 761bca1a2127b..0000000000000
--- a/tests/baselines/reference/organizeImports/SortComments.ts
+++ /dev/null
@@ -1,17 +0,0 @@
-// ==ORIGINAL==
-
-// Header
-import "lib3";
-// Comment2
-import "lib2";
-// Comment1
-import "lib1";
-
-// ==ORGANIZED==
-
-// Header
-// Comment1
-import "lib1";
-// Comment2
-import "lib2";
-import "lib3";
diff --git a/tests/baselines/reference/organizeImports/TopLevelAndAmbientModule.ts b/tests/baselines/reference/organizeImports/TopLevelAndAmbientModule.ts
index d6f3158efe859..8bbab4f4ff5d8 100644
--- a/tests/baselines/reference/organizeImports/TopLevelAndAmbientModule.ts
+++ b/tests/baselines/reference/organizeImports/TopLevelAndAmbientModule.ts
@@ -17,7 +17,6 @@ D();
// ==ORGANIZED==
-import "lib";
import D from "lib";
declare module "mod" {
@@ -26,5 +25,6 @@ declare module "mod" {
function F(f1: {} = F1, f2: {} = F2) {}
}
+import "lib";
D();
diff --git a/tests/cases/fourslash/organizeImports6.ts b/tests/cases/fourslash/organizeImports6.ts
index f5fa3b8269d9d..75e1491c1d19c 100644
--- a/tests/cases/fourslash/organizeImports6.ts
+++ b/tests/cases/fourslash/organizeImports6.ts
@@ -16,6 +16,12 @@
//// anotherThing;
verify.organizeImports(
-`import * as anotherThing from "someopath"; /* small comment */ // single line one.
+`/* some comment here
+* and there
+*/
+import * as anotherThing from "someopath"; /* small comment */ // single line one.
+/* some comment here
+* and there
+*/
-anotherThing;`);
\ No newline at end of file
+anotherThing;`);
diff --git a/tests/cases/fourslash/organizeImportsGroup_CommentInNewline.ts b/tests/cases/fourslash/organizeImportsGroup_CommentInNewline.ts
new file mode 100644
index 0000000000000..8a20bf185e97a
--- /dev/null
+++ b/tests/cases/fourslash/organizeImportsGroup_CommentInNewline.ts
@@ -0,0 +1,21 @@
+///
+
+////// polyfill
+////import c from "C";
+////// not polyfill
+////import d from "D";
+////import a from "A";
+////import b from "B";
+////
+////console.log(a, b, c, d)
+
+verify.organizeImports(
+`// polyfill
+import c from "C";
+// not polyfill
+import a from "A";
+import b from "B";
+import d from "D";
+
+console.log(a, b, c, d)`
+);
diff --git a/tests/cases/fourslash/organizeImportsGroup_MultiNewlines.ts b/tests/cases/fourslash/organizeImportsGroup_MultiNewlines.ts
new file mode 100644
index 0000000000000..cce8b8f603fa5
--- /dev/null
+++ b/tests/cases/fourslash/organizeImportsGroup_MultiNewlines.ts
@@ -0,0 +1,21 @@
+///
+
+////import c from "C";
+////
+////
+////import d from "D";
+////import a from "A";
+////import b from "B";
+////
+////console.log(a, b, c, d)
+
+verify.organizeImports(
+`import c from "C";
+
+
+import a from "A";
+import b from "B";
+import d from "D";
+
+console.log(a, b, c, d)`
+);
diff --git a/tests/cases/fourslash/organizeImportsGroup_MultilineCommentInNewline.ts b/tests/cases/fourslash/organizeImportsGroup_MultilineCommentInNewline.ts
new file mode 100644
index 0000000000000..04fff1675ac30
--- /dev/null
+++ b/tests/cases/fourslash/organizeImportsGroup_MultilineCommentInNewline.ts
@@ -0,0 +1,25 @@
+///
+
+////// polyfill
+////import c from "C";
+/////*
+////* demo
+////*/
+////import d from "D";
+////import a from "A";
+////import b from "B";
+////
+////console.log(a, b, c, d)
+
+verify.organizeImports(
+`// polyfill
+import c from "C";
+/*
+* demo
+*/
+import a from "A";
+import b from "B";
+import d from "D";
+
+console.log(a, b, c, d)`
+);
diff --git a/tests/cases/fourslash/organizeImportsGroup_Newline.ts b/tests/cases/fourslash/organizeImportsGroup_Newline.ts
new file mode 100644
index 0000000000000..9f904ef376904
--- /dev/null
+++ b/tests/cases/fourslash/organizeImportsGroup_Newline.ts
@@ -0,0 +1,19 @@
+///
+
+////import c from "C";
+////
+////import d from "D";
+////import a from "A"; // not count
+////import b from "B";
+////
+////console.log(a, b, c, d)
+
+verify.organizeImports(
+`import c from "C";
+
+import a from "A"; // not count
+import b from "B";
+import d from "D";
+
+console.log(a, b, c, d)`
+);