Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(139)

Side by Side Diff: pkg/analysis_server/lib/src/computer/import_elements_computer.dart

Issue 3002643002: Fix insertion of imports when there are no existing directives (issue 30430) (Closed)
Patch Set: address comments Created 3 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | pkg/analysis_server/test/src/computer/import_elements_computer_test.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 import 'dart:async'; 5 import 'dart:async';
6 6
7 import 'package:analysis_server/protocol/protocol_generated.dart'; 7 import 'package:analysis_server/protocol/protocol_generated.dart';
8 import 'package:analyzer/dart/analysis/results.dart'; 8 import 'package:analyzer/dart/analysis/results.dart';
9 import 'package:analyzer/dart/ast/ast.dart'; 9 import 'package:analyzer/dart/ast/ast.dart';
10 import 'package:analyzer/dart/ast/ast_factory.dart'; 10 import 'package:analyzer/dart/ast/ast_factory.dart';
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
70 if (matchingImports.isEmpty) { 70 if (matchingImports.isEmpty) {
71 // 71 //
72 // The required library is not being imported with a matching prefix, 72 // The required library is not being imported with a matching prefix,
73 // so we need to add an import. 73 // so we need to add an import.
74 // 74 //
75 File importedFile = resourceProvider.getFile(importedElements.path); 75 File importedFile = resourceProvider.getFile(importedElements.path);
76 Uri uri = sourceFactory.restoreUri(importedFile.createSource()); 76 Uri uri = sourceFactory.restoreUri(importedFile.createSource());
77 Source importedSource = importedFile.createSource(uri); 77 Source importedSource = importedFile.createSource(uri);
78 String importUri = 78 String importUri =
79 _getLibrarySourceUri(libraryElement, importedSource); 79 _getLibrarySourceUri(libraryElement, importedSource);
80 int offset = _offsetForInsertion(importUri); 80 _InsertionDescription description =
81 builder.addInsertion(offset, (DartEditBuilder builder) { 81 _getInsertionDescription(importUri);
82 builder.writeln(); 82 builder.addInsertion(description.offset, (DartEditBuilder builder) {
83 for (int i = 0; i < description.newLinesBefore; i++) {
84 builder.writeln();
85 }
83 builder.write("import '"); 86 builder.write("import '");
84 builder.write(importUri); 87 builder.write(importUri);
85 builder.write("'"); 88 builder.write("'");
86 if (importedElements.prefix.isNotEmpty) { 89 if (importedElements.prefix.isNotEmpty) {
87 builder.write(' as '); 90 builder.write(' as ');
88 builder.write(importedElements.prefix); 91 builder.write(importedElements.prefix);
89 } 92 }
90 builder.write(';'); 93 builder.write(';');
94 for (int i = 0; i < description.newLinesAfter; i++) {
95 builder.writeln();
96 }
91 }); 97 });
92 } else { 98 } else {
93 // 99 //
94 // There are some imports of the library with a matching prefix. We 100 // There are some imports of the library with a matching prefix. We
95 // need to determine whether the names are already visible or whether 101 // need to determine whether the names are already visible or whether
96 // we need to make edits to make them visible. 102 // we need to make edits to make them visible.
97 // 103 //
98 // Compute the edits that need to be made. 104 // Compute the edits that need to be made.
99 // 105 //
100 Map<ImportDirective, _ImportUpdate> updateMap = 106 Map<ImportDirective, _ImportUpdate> updateMap =
(...skipping 201 matching lines...) Expand 10 before | Expand all | Expand 10 after
302 List<ImportDirective> matchingImports = <ImportDirective>[]; 308 List<ImportDirective> matchingImports = <ImportDirective>[];
303 for (ImportDirective existingImport in existingImports) { 309 for (ImportDirective existingImport in existingImports) {
304 if (_matches(existingImport, importedElements)) { 310 if (_matches(existingImport, importedElements)) {
305 matchingImports.add(existingImport); 311 matchingImports.add(existingImport);
306 } 312 }
307 } 313 }
308 return matchingImports; 314 return matchingImports;
309 } 315 }
310 316
311 /** 317 /**
318 * Return the offset at which an import of the given [importUri] should be
319 * inserted.
320 *
321 * Partially copied from DartFileEditBuilderImpl.
322 */
323 _InsertionDescription _getInsertionDescription(String importUri) {
324 CompilationUnit unit = libraryResult.unit;
325 LibraryDirective libraryDirective;
326 List<ImportDirective> importDirectives = <ImportDirective>[];
327 List<Directive> otherDirectives = <Directive>[];
328 for (Directive directive in unit.directives) {
329 if (directive is LibraryDirective) {
330 libraryDirective = directive;
331 } else if (directive is ImportDirective) {
332 importDirectives.add(directive);
333 } else {
334 otherDirectives.add(directive);
335 }
336 }
337 if (importDirectives.isEmpty) {
338 if (libraryDirective == null) {
339 if (otherDirectives.isEmpty) {
340 // TODO(brianwilkerson) Insert after any non-doc comments.
341 return new _InsertionDescription(0, after: 2);
342 }
343 return new _InsertionDescription(otherDirectives[0].offset, after: 2);
344 }
345 return new _InsertionDescription(libraryDirective.end, before: 2);
346 }
347 // TODO(brianwilkerson) Fix this to find the right location.
348 // See DartFileEditBuilderImpl._addLibraryImports for inspiration.
349 return new _InsertionDescription(importDirectives.last.end, before: 1);
350 }
351
352 /**
312 * Computes the best URI to import [what] into [from]. 353 * Computes the best URI to import [what] into [from].
313 * 354 *
314 * Copied from DartFileEditBuilderImpl. 355 * Copied from DartFileEditBuilderImpl.
315 */ 356 */
316 String _getLibrarySourceUri(LibraryElement from, Source what) { 357 String _getLibrarySourceUri(LibraryElement from, Source what) {
317 String whatPath = what.fullName; 358 String whatPath = what.fullName;
318 // check if an absolute URI (such as 'dart:' or 'package:') 359 // check if an absolute URI (such as 'dart:' or 'package:')
319 Uri whatUri = what.uri; 360 Uri whatUri = what.uri;
320 String whatUriScheme = whatUri.scheme; 361 String whatUriScheme = whatUri.scheme;
321 if (whatUriScheme != '' && whatUriScheme != 'file') { 362 if (whatUriScheme != '' && whatUriScheme != 'file') {
322 return whatUri.toString(); 363 return whatUri.toString();
323 } 364 }
324 // compute a relative URI 365 // compute a relative URI
325 Context context = resourceProvider.pathContext; 366 Context context = resourceProvider.pathContext;
326 String fromFolder = context.dirname(from.source.fullName); 367 String fromFolder = context.dirname(from.source.fullName);
327 String relativeFile = context.relative(whatPath, from: fromFolder); 368 String relativeFile = context.relative(whatPath, from: fromFolder);
328 return context.split(relativeFile).join('/'); 369 return context.split(relativeFile).join('/');
329 } 370 }
330 371
331 /** 372 /**
332 * Return `true` if the given [import] matches the given specification of 373 * Return `true` if the given [import] matches the given specification of
333 * [importedElements]. They will match if they import the same library using 374 * [importedElements]. They will match if they import the same library using
334 * the same prefix. 375 * the same prefix.
335 */ 376 */
336 bool _matches(ImportDirective import, ImportedElements importedElements) { 377 bool _matches(ImportDirective import, ImportedElements importedElements) {
337 return (import.element as ImportElement).importedLibrary.source.fullName == 378 return (import.element as ImportElement).importedLibrary.source.fullName ==
338 importedElements.path && 379 importedElements.path &&
339 (import.prefix?.name ?? '') == importedElements.prefix; 380 (import.prefix?.name ?? '') == importedElements.prefix;
340 } 381 }
341
342 /**
343 * Return the offset at which an import of the given [importUri] should be
344 * inserted.
345 *
346 * Partially copied from DartFileEditBuilderImpl.
347 */
348 int _offsetForInsertion(String importUri) {
349 // TODO(brianwilkerson) Fix this to find the right location.
350 // See DartFileEditBuilderImpl._addLibraryImports for inspiration.
351 CompilationUnit unit = libraryResult.unit;
352 LibraryDirective libraryDirective;
353 List<ImportDirective> importDirectives = <ImportDirective>[];
354 for (Directive directive in unit.directives) {
355 if (directive is LibraryDirective) {
356 libraryDirective = directive;
357 } else if (directive is ImportDirective) {
358 importDirectives.add(directive);
359 }
360 }
361 if (importDirectives.isEmpty) {
362 if (libraryDirective == null) {
363 return 0;
364 }
365 return libraryDirective.end;
366 }
367 return importDirectives.last.end;
368 }
369 } 382 }
370 383
371 /** 384 /**
372 * Information about how a given import directive needs to be updated in order 385 * Information about how a given import directive needs to be updated in order
373 * to make the required names visible. 386 * to make the required names visible.
374 */ 387 */
375 class _ImportUpdate { 388 class _ImportUpdate {
376 /** 389 /**
377 * The import directive to be updated. 390 * The import directive to be updated.
378 */ 391 */
(...skipping 22 matching lines...) Expand all
401 namesToShow.add(name); 414 namesToShow.add(name);
402 } 415 }
403 416
404 /** 417 /**
405 * Record that the given [name] needs to be removed from hide combinators. 418 * Record that the given [name] needs to be removed from hide combinators.
406 */ 419 */
407 void unhide(String name) { 420 void unhide(String name) {
408 namesToUnhide.add(name); 421 namesToUnhide.add(name);
409 } 422 }
410 } 423 }
424
425 class _InsertionDescription {
426 final int newLinesBefore;
427 final int offset;
428 final int newLinesAfter;
429
430 _InsertionDescription(this.offset, {int before: 0, int after: 0})
431 : this.newLinesBefore = before,
432 this.newLinesAfter = after;
433 }
OLDNEW
« no previous file with comments | « no previous file | pkg/analysis_server/test/src/computer/import_elements_computer_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698