Issue 30577. Use AST to find position for the first directive.
R=brianwilkerson@google.com
Bug: https://github.com/dart-lang/sdk/issues/30577
Change-Id: If69df5f49228a3b698544dcf82ad0c34c1be84e8
Reviewed-on: https://dart-review.googlesource.com/54307
Commit-Queue: Konstantin Shcheglov <scheglov@google.com>
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
diff --git a/pkg/analyzer_plugin/lib/src/utilities/change_builder/change_builder_dart.dart b/pkg/analyzer_plugin/lib/src/utilities/change_builder/change_builder_dart.dart
index c429a6d..b9b3f80 100644
--- a/pkg/analyzer_plugin/lib/src/utilities/change_builder/change_builder_dart.dart
+++ b/pkg/analyzer_plugin/lib/src/utilities/change_builder/change_builder_dart.dart
@@ -1424,19 +1424,22 @@
return;
}
- // If still at the beginning of the file, skip shebang and line comments.
- _InsertionDescription desc = _getInsertDescTop();
- int offset = desc.offset;
+ // If still at the beginning of the file, add before the first declaration.
+ int offset;
+ bool insertEmptyLineAfter = false;
+ if (unit.declarations.isNotEmpty) {
+ offset = unit.declarations.first.offset;
+ insertEmptyLineAfter = true;
+ } else {
+ offset = unit.end;
+ }
for (int i = 0; i < uriList.length; i++) {
String importUri = uriList[i];
addInsertion(offset, (EditBuilder builder) {
- if (i == 0 && desc.insertEmptyLineBefore) {
- builder.writeln();
- }
builder.write("import '");
builder.write(importUri);
builder.writeln("';");
- if (i == uriList.length - 1 && desc.insertEmptyLineAfter) {
+ if (i == uriList.length - 1 && insertEmptyLineAfter) {
builder.writeln();
}
});
@@ -1444,63 +1447,6 @@
}
/**
- * Returns an insertion description describing where to insert a new directive
- * or a top-level declaration at the top of the file.
- */
- _InsertionDescription _getInsertDescTop() {
- // skip leading line comments
- int offset = 0;
- bool insertEmptyLineBefore = false;
- bool insertEmptyLineAfter = false;
- String source = unit.element.context.getContents(unit.element.source).data;
- var lineInfo = unit.lineInfo;
- // skip hash-bang
- if (offset < source.length - 2) {
- String linePrefix = _getText(source, offset, 2);
- if (linePrefix == "#!") {
- insertEmptyLineBefore = true;
- offset = lineInfo.getOffsetOfLineAfter(offset);
- // skip empty lines to first line comment
- int emptyOffset = offset;
- while (emptyOffset < source.length - 2) {
- int nextLineOffset = lineInfo.getOffsetOfLineAfter(emptyOffset);
- String line = source.substring(emptyOffset, nextLineOffset);
- if (line.trim().isEmpty) {
- emptyOffset = nextLineOffset;
- continue;
- } else if (line.startsWith("//")) {
- offset = emptyOffset;
- break;
- } else {
- break;
- }
- }
- }
- }
- // skip line comments
- while (offset < source.length - 2) {
- String linePrefix = _getText(source, offset, 2);
- if (linePrefix == "//") {
- insertEmptyLineBefore = true;
- offset = lineInfo.getOffsetOfLineAfter(offset);
- } else {
- break;
- }
- }
- // determine if empty line is required after
- int currentLine = lineInfo.getLocation(offset).lineNumber;
- if (currentLine + 1 < lineInfo.lineCount) {
- int nextLineOffset = lineInfo.getOffsetOfLine(currentLine + 1);
- String insertLine = source.substring(offset, nextLineOffset);
- if (!insertLine.trim().isEmpty) {
- insertEmptyLineAfter = true;
- }
- }
- return new _InsertionDescription(
- offset, insertEmptyLineBefore, insertEmptyLineAfter);
- }
-
- /**
* Computes the best URI to import [what] into [from].
*/
String _getLibrarySourceUri(LibraryElement from, Source what) {
@@ -1518,13 +1464,6 @@
}
/**
- * Returns the text of the given range in the unit.
- */
- String _getText(String content, int offset, int length) {
- return content.substring(offset, offset + length);
- }
-
- /**
* Create an edit to replace the return type of the innermost function
* containing the given [node] with the type `Future`. The [typeProvider] is
* used to check the current return type, because if it is already `Future` no
@@ -1687,11 +1626,3 @@
return null;
}
}
-
-class _InsertionDescription {
- final int offset;
- final bool insertEmptyLineBefore;
- final bool insertEmptyLineAfter;
- _InsertionDescription(
- this.offset, this.insertEmptyLineBefore, this.insertEmptyLineAfter);
-}
diff --git a/pkg/analyzer_plugin/test/src/utilities/change_builder/change_builder_dart_test.dart b/pkg/analyzer_plugin/test/src/utilities/change_builder/change_builder_dart_test.dart
index 4859430..d8d76f8 100644
--- a/pkg/analyzer_plugin/test/src/utilities/change_builder/change_builder_dart_test.dart
+++ b/pkg/analyzer_plugin/test/src/utilities/change_builder/change_builder_dart_test.dart
@@ -154,6 +154,50 @@
''');
}
+ test_importLibrary_noDirectives_docComment() async {
+ await _assertImportLibraries('''
+/// Documentation comment.
+/// Continues.
+void main() {}
+''', ['dart:async'], '''
+import 'dart:async';
+
+/// Documentation comment.
+/// Continues.
+void main() {}
+''');
+ }
+
+ test_importLibrary_noDirectives_hashBang() async {
+ await _assertImportLibraries('''
+#!/bin/dart
+
+void main() {}
+''', ['dart:async'], '''
+#!/bin/dart
+
+import 'dart:async';
+
+void main() {}
+''');
+ }
+
+ test_importLibrary_noDirectives_lineComment() async {
+ await _assertImportLibraries('''
+// Not documentation comment.
+// Continues.
+
+void main() {}
+''', ['dart:async'], '''
+// Not documentation comment.
+// Continues.
+
+import 'dart:async';
+
+void main() {}
+''');
+ }
+
test_importLibrary_package_afterDart() async {
await _assertImportLibraries('''
import 'dart:async';