| OLD | NEW |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 } |
| OLD | NEW |