Merge analyzer branch into master Some work on the Dart analyzer was done on a branch, to avoid disrupting others, and is landed with this commit. It is a merge, in order to preserve the history of work on that branch.
diff --git a/CHANGELOG.md b/CHANGELOG.md index 7ea8989..c3a62fd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md
@@ -1,3 +1,14 @@ +## + +### Tool Changes + +#### Analyzer + +* Support for `declarations-casts` has been removed and the `implicit-casts` + option now has the combined semantics of both options. This means that users + that disable `implicit-casts` might now see errors that were not previously + being reported. + ## 2.2.0-dev.XX.0 (Add new changes here, and they will be copied to the change section for the next dev version)
diff --git a/pkg/analysis_server/lib/lsp_protocol/protocol_generated.dart b/pkg/analysis_server/lib/lsp_protocol/protocol_generated.dart index e1e4b90..200607c 100644 --- a/pkg/analysis_server/lib/lsp_protocol/protocol_generated.dart +++ b/pkg/analysis_server/lib/lsp_protocol/protocol_generated.dart
@@ -6,9 +6,18 @@ // To regenerate the file, use the script // "pkg/analysis_server/tool/lsp_spec/generate_all.dart". +// ignore_for_file: deprecated_member_use +// ignore_for_file: unnecessary_brace_in_string_interps + import 'dart:core' hide deprecated; import 'dart:core' as core show deprecated; +import 'dart:convert' show JsonEncoder; import 'package:analysis_server/lsp_protocol/protocol_special.dart'; +import 'package:analysis_server/src/protocol/protocol_internal.dart' + show listEqual, mapEqual; +import 'package:analyzer/src/generated/utilities_general.dart'; + +const jsonEncoder = const JsonEncoder.withIndent(' '); class ApplyWorkspaceEditParams implements ToJsonable { ApplyWorkspaceEditParams(this.label, this.edit) { @@ -16,10 +25,10 @@ throw 'edit is required but was not provided'; } } - factory ApplyWorkspaceEditParams.fromJson(Map<String, dynamic> json) { + static ApplyWorkspaceEditParams fromJson(Map<String, dynamic> json) { final label = json['label']; final edit = - json['edit'] != null ? new WorkspaceEdit.fromJson(json['edit']) : null; + json['edit'] != null ? WorkspaceEdit.fromJson(json['edit']) : null; return new ApplyWorkspaceEditParams(label, edit); } @@ -44,6 +53,25 @@ obj.containsKey('edit') && WorkspaceEdit.canParse(obj['edit']); } + + @override + bool operator ==(other) { + if (other is ApplyWorkspaceEditParams) { + return label == other.label && edit == other.edit && true; + } + return false; + } + + @override + int get hashCode { + int hash = 0; + hash = JenkinsSmiHash.combine(hash, label.hashCode); + hash = JenkinsSmiHash.combine(hash, edit.hashCode); + return JenkinsSmiHash.finish(hash); + } + + @override + String toString() => jsonEncoder.convert(toJson()); } class ApplyWorkspaceEditResponse implements ToJsonable { @@ -52,7 +80,7 @@ throw 'applied is required but was not provided'; } } - factory ApplyWorkspaceEditResponse.fromJson(Map<String, dynamic> json) { + static ApplyWorkspaceEditResponse fromJson(Map<String, dynamic> json) { final applied = json['applied']; return new ApplyWorkspaceEditResponse(applied); } @@ -72,6 +100,24 @@ obj.containsKey('applied') && obj['applied'] is bool; } + + @override + bool operator ==(other) { + if (other is ApplyWorkspaceEditResponse) { + return applied == other.applied && true; + } + return false; + } + + @override + int get hashCode { + int hash = 0; + hash = JenkinsSmiHash.combine(hash, applied.hashCode); + return JenkinsSmiHash.finish(hash); + } + + @override + String toString() => jsonEncoder.convert(toJson()); } class CancelParams implements ToJsonable { @@ -80,12 +126,12 @@ throw 'id is required but was not provided'; } } - factory CancelParams.fromJson(Map<String, dynamic> json) { + static CancelParams fromJson(Map<String, dynamic> json) { final id = json['id'] is num ? new Either2<num, String>.t1(json['id']) : (json['id'] is String ? new Either2<num, String>.t2(json['id']) - : (throw '''${json['id']} was not one of (number, string)''')); + : (throw '''${json['id']} was not one of (num, String)''')); return new CancelParams(id); } @@ -103,16 +149,34 @@ obj.containsKey('id') && (obj['id'] is num || obj['id'] is String); } + + @override + bool operator ==(other) { + if (other is CancelParams) { + return id == other.id && true; + } + return false; + } + + @override + int get hashCode { + int hash = 0; + hash = JenkinsSmiHash.combine(hash, id.hashCode); + return JenkinsSmiHash.finish(hash); + } + + @override + String toString() => jsonEncoder.convert(toJson()); } class ClientCapabilities implements ToJsonable { ClientCapabilities(this.workspace, this.textDocument, this.experimental); - factory ClientCapabilities.fromJson(Map<String, dynamic> json) { + static ClientCapabilities fromJson(Map<String, dynamic> json) { final workspace = json['workspace'] != null - ? new WorkspaceClientCapabilities.fromJson(json['workspace']) + ? WorkspaceClientCapabilities.fromJson(json['workspace']) : null; final textDocument = json['textDocument'] != null - ? new TextDocumentClientCapabilities.fromJson(json['textDocument']) + ? TextDocumentClientCapabilities.fromJson(json['textDocument']) : null; final experimental = json['experimental']; return new ClientCapabilities(workspace, textDocument, experimental); @@ -144,6 +208,29 @@ static bool canParse(Object obj) { return obj is Map<String, dynamic>; } + + @override + bool operator ==(other) { + if (other is ClientCapabilities) { + return workspace == other.workspace && + textDocument == other.textDocument && + experimental == other.experimental && + true; + } + return false; + } + + @override + int get hashCode { + int hash = 0; + hash = JenkinsSmiHash.combine(hash, workspace.hashCode); + hash = JenkinsSmiHash.combine(hash, textDocument.hashCode); + hash = JenkinsSmiHash.combine(hash, experimental.hashCode); + return JenkinsSmiHash.finish(hash); + } + + @override + String toString() => jsonEncoder.convert(toJson()); } /// A code action represents a change that can be performed in code, e.g. to fix @@ -157,17 +244,18 @@ throw 'title is required but was not provided'; } } - factory CodeAction.fromJson(Map<String, dynamic> json) { + static CodeAction fromJson(Map<String, dynamic> json) { final title = json['title']; - final kind = json['kind']; + final kind = + json['kind'] != null ? CodeActionKind.fromJson(json['kind']) : null; final diagnostics = json['diagnostics'] - ?.map((item) => item != null ? new Diagnostic.fromJson(item) : null) + ?.map((item) => item != null ? Diagnostic.fromJson(item) : null) ?.cast<Diagnostic>() ?.toList(); final edit = - json['edit'] != null ? new WorkspaceEdit.fromJson(json['edit']) : null; + json['edit'] != null ? WorkspaceEdit.fromJson(json['edit']) : null; final command = - json['command'] != null ? new Command.fromJson(json['command']) : null; + json['command'] != null ? Command.fromJson(json['command']) : null; return new CodeAction(title, kind, diagnostics, edit, command); } @@ -184,7 +272,7 @@ /// The kind of the code action. /// /// Used to filter code actions. - final String kind; + final CodeActionKind kind; /// A short, human-readable, title for this code action. final String title; @@ -212,6 +300,34 @@ obj.containsKey('title') && obj['title'] is String; } + + @override + bool operator ==(other) { + if (other is CodeAction) { + return title == other.title && + kind == other.kind && + listEqual(diagnostics, other.diagnostics, + (Diagnostic a, Diagnostic b) => a == b) && + edit == other.edit && + command == other.command && + true; + } + return false; + } + + @override + int get hashCode { + int hash = 0; + hash = JenkinsSmiHash.combine(hash, title.hashCode); + hash = JenkinsSmiHash.combine(hash, kind.hashCode); + hash = JenkinsSmiHash.combine(hash, diagnostics.hashCode); + hash = JenkinsSmiHash.combine(hash, edit.hashCode); + hash = JenkinsSmiHash.combine(hash, command.hashCode); + return JenkinsSmiHash.finish(hash); + } + + @override + String toString() => jsonEncoder.convert(toJson()); } /// Contains additional diagnostic information about the context in which a code @@ -222,12 +338,15 @@ throw 'diagnostics is required but was not provided'; } } - factory CodeActionContext.fromJson(Map<String, dynamic> json) { + static CodeActionContext fromJson(Map<String, dynamic> json) { final diagnostics = json['diagnostics'] - ?.map((item) => item != null ? new Diagnostic.fromJson(item) : null) + ?.map((item) => item != null ? Diagnostic.fromJson(item) : null) ?.cast<Diagnostic>() ?.toList(); - final only = json['only']?.map((item) => item)?.cast<String>()?.toList(); + final only = json['only'] + ?.map((item) => item != null ? CodeActionKind.fromJson(item) : null) + ?.cast<CodeActionKind>() + ?.toList(); return new CodeActionContext(diagnostics, only); } @@ -238,7 +357,7 @@ /// /// Actions not of this kind are filtered out by the client before being /// shown. So servers can omit computing them. - final List<String> only; + final List<CodeActionKind> only; Map<String, dynamic> toJson() { Map<String, dynamic> __result = {}; @@ -257,15 +376,47 @@ (obj['diagnostics'].length == 0 || obj['diagnostics'].every((item) => Diagnostic.canParse(item)))); } + + @override + bool operator ==(other) { + if (other is CodeActionContext) { + return listEqual(diagnostics, other.diagnostics, + (Diagnostic a, Diagnostic b) => a == b) && + listEqual(only, other.only, + (CodeActionKind a, CodeActionKind b) => a == b) && + true; + } + return false; + } + + @override + int get hashCode { + int hash = 0; + hash = JenkinsSmiHash.combine(hash, diagnostics.hashCode); + hash = JenkinsSmiHash.combine(hash, only.hashCode); + return JenkinsSmiHash.finish(hash); + } + + @override + String toString() => jsonEncoder.convert(toJson()); } /// A set of predefined code action kinds -abstract class CodeActionKind { +class CodeActionKind { + const CodeActionKind(this._value); + const CodeActionKind.fromJson(this._value); + + final String _value; + + static bool canParse(Object obj) { + return obj is String; + } + /// Base kind for quickfix actions: 'quickfix' - static const QuickFix = 'quickfix'; + static const QuickFix = const CodeActionKind('quickfix'); /// Base kind for refactoring actions: 'refactor' - static const Refactor = 'refactor'; + static const Refactor = const CodeActionKind('refactor'); /// Base kind for refactoring extraction actions: 'refactor.extract' /// @@ -276,7 +427,7 @@ /// - Extract variable /// - Extract interface from class /// - ... - static const RefactorExtract = 'refactor.extract'; + static const RefactorExtract = const CodeActionKind('refactor.extract'); /// Base kind for refactoring inline actions: 'refactor.inline' /// @@ -286,7 +437,7 @@ /// - Inline variable /// - Inline constant /// - ... - static const RefactorInline = 'refactor.inline'; + static const RefactorInline = const CodeActionKind('refactor.inline'); /// Base kind for refactoring rewrite actions: 'refactor.rewrite' /// @@ -298,23 +449,36 @@ /// - Make method static /// - Move method to base class /// - ... - static const RefactorRewrite = 'refactor.rewrite'; + static const RefactorRewrite = const CodeActionKind('refactor.rewrite'); /// Base kind for source actions: `source` /// /// Source code actions apply to the entire file. - static const Source = 'source'; + static const Source = const CodeActionKind('source'); /// Base kind for an organize imports source action: `source.organizeImports` - static const SourceOrganizeImports = 'source.organizeImports'; + static const SourceOrganizeImports = + const CodeActionKind('source.organizeImports'); + + Object toJson() => _value; + + @override + String toString() => _value.toString(); + + @override + get hashCode => _value.hashCode; + + bool operator ==(o) => o is CodeActionKind && o._value == _value; } /// Code Action options. class CodeActionOptions implements ToJsonable { CodeActionOptions(this.codeActionKinds); - factory CodeActionOptions.fromJson(Map<String, dynamic> json) { - final codeActionKinds = - json['codeActionKinds']?.map((item) => item)?.cast<String>()?.toList(); + static CodeActionOptions fromJson(Map<String, dynamic> json) { + final codeActionKinds = json['codeActionKinds'] + ?.map((item) => item != null ? CodeActionKind.fromJson(item) : null) + ?.cast<CodeActionKind>() + ?.toList(); return new CodeActionOptions(codeActionKinds); } @@ -322,7 +486,7 @@ /// /// The list of kinds may be generic, such as `CodeActionKind.Refactor`, or /// the server may list out every specific kind they provide. - final List<String> codeActionKinds; + final List<CodeActionKind> codeActionKinds; Map<String, dynamic> toJson() { Map<String, dynamic> __result = {}; @@ -335,6 +499,26 @@ static bool canParse(Object obj) { return obj is Map<String, dynamic>; } + + @override + bool operator ==(other) { + if (other is CodeActionOptions) { + return listEqual(codeActionKinds, other.codeActionKinds, + (CodeActionKind a, CodeActionKind b) => a == b) && + true; + } + return false; + } + + @override + int get hashCode { + int hash = 0; + hash = JenkinsSmiHash.combine(hash, codeActionKinds.hashCode); + return JenkinsSmiHash.finish(hash); + } + + @override + String toString() => jsonEncoder.convert(toJson()); } /// Params for the CodeActionRequest @@ -350,14 +534,13 @@ throw 'context is required but was not provided'; } } - factory CodeActionParams.fromJson(Map<String, dynamic> json) { + static CodeActionParams fromJson(Map<String, dynamic> json) { final textDocument = json['textDocument'] != null - ? new TextDocumentIdentifier.fromJson(json['textDocument']) + ? TextDocumentIdentifier.fromJson(json['textDocument']) : null; - final range = - json['range'] != null ? new Range.fromJson(json['range']) : null; + final range = json['range'] != null ? Range.fromJson(json['range']) : null; final context = json['context'] != null - ? new CodeActionContext.fromJson(json['context']) + ? CodeActionContext.fromJson(json['context']) : null; return new CodeActionParams(textDocument, range, context); } @@ -390,18 +573,43 @@ obj.containsKey('context') && CodeActionContext.canParse(obj['context']); } + + @override + bool operator ==(other) { + if (other is CodeActionParams) { + return textDocument == other.textDocument && + range == other.range && + context == other.context && + true; + } + return false; + } + + @override + int get hashCode { + int hash = 0; + hash = JenkinsSmiHash.combine(hash, textDocument.hashCode); + hash = JenkinsSmiHash.combine(hash, range.hashCode); + hash = JenkinsSmiHash.combine(hash, context.hashCode); + return JenkinsSmiHash.finish(hash); + } + + @override + String toString() => jsonEncoder.convert(toJson()); } class CodeActionRegistrationOptions implements TextDocumentRegistrationOptions, CodeActionOptions, ToJsonable { CodeActionRegistrationOptions(this.documentSelector, this.codeActionKinds); - factory CodeActionRegistrationOptions.fromJson(Map<String, dynamic> json) { + static CodeActionRegistrationOptions fromJson(Map<String, dynamic> json) { final documentSelector = json['documentSelector'] - ?.map((item) => item != null ? new DocumentFilter.fromJson(item) : null) + ?.map((item) => item != null ? DocumentFilter.fromJson(item) : null) ?.cast<DocumentFilter>() ?.toList(); - final codeActionKinds = - json['codeActionKinds']?.map((item) => item)?.cast<String>()?.toList(); + final codeActionKinds = json['codeActionKinds'] + ?.map((item) => item != null ? CodeActionKind.fromJson(item) : null) + ?.cast<CodeActionKind>() + ?.toList(); return new CodeActionRegistrationOptions(documentSelector, codeActionKinds); } @@ -409,7 +617,7 @@ /// /// The list of kinds may be generic, such as `CodeActionKind.Refactor`, or /// the server may list out every specific kind they provide. - final List<String> codeActionKinds; + final List<CodeActionKind> codeActionKinds; /// A document selector to identify the scope of the registration. If set to /// null the document selector provided on the client side will be used. @@ -432,6 +640,28 @@ obj['documentSelector'] .every((item) => DocumentFilter.canParse(item)))); } + + @override + bool operator ==(other) { + if (other is CodeActionRegistrationOptions) { + return documentSelector == other.documentSelector && + listEqual(codeActionKinds, other.codeActionKinds, + (CodeActionKind a, CodeActionKind b) => a == b) && + true; + } + return false; + } + + @override + int get hashCode { + int hash = 0; + hash = JenkinsSmiHash.combine(hash, documentSelector.hashCode); + hash = JenkinsSmiHash.combine(hash, codeActionKinds.hashCode); + return JenkinsSmiHash.finish(hash); + } + + @override + String toString() => jsonEncoder.convert(toJson()); } /// A code lens represents a command that should be shown along with source @@ -446,11 +676,10 @@ throw 'range is required but was not provided'; } } - factory CodeLens.fromJson(Map<String, dynamic> json) { - final range = - json['range'] != null ? new Range.fromJson(json['range']) : null; + static CodeLens fromJson(Map<String, dynamic> json) { + final range = json['range'] != null ? Range.fromJson(json['range']) : null; final command = - json['command'] != null ? new Command.fromJson(json['command']) : null; + json['command'] != null ? Command.fromJson(json['command']) : null; final data = json['data']; return new CodeLens(range, command, data); } @@ -483,12 +712,35 @@ obj.containsKey('range') && Range.canParse(obj['range']); } + + @override + bool operator ==(other) { + if (other is CodeLens) { + return range == other.range && + command == other.command && + data == other.data && + true; + } + return false; + } + + @override + int get hashCode { + int hash = 0; + hash = JenkinsSmiHash.combine(hash, range.hashCode); + hash = JenkinsSmiHash.combine(hash, command.hashCode); + hash = JenkinsSmiHash.combine(hash, data.hashCode); + return JenkinsSmiHash.finish(hash); + } + + @override + String toString() => jsonEncoder.convert(toJson()); } /// Code Lens options. class CodeLensOptions implements ToJsonable { CodeLensOptions(this.resolveProvider); - factory CodeLensOptions.fromJson(Map<String, dynamic> json) { + static CodeLensOptions fromJson(Map<String, dynamic> json) { final resolveProvider = json['resolveProvider']; return new CodeLensOptions(resolveProvider); } @@ -507,6 +759,24 @@ static bool canParse(Object obj) { return obj is Map<String, dynamic>; } + + @override + bool operator ==(other) { + if (other is CodeLensOptions) { + return resolveProvider == other.resolveProvider && true; + } + return false; + } + + @override + int get hashCode { + int hash = 0; + hash = JenkinsSmiHash.combine(hash, resolveProvider.hashCode); + return JenkinsSmiHash.finish(hash); + } + + @override + String toString() => jsonEncoder.convert(toJson()); } class CodeLensParams implements ToJsonable { @@ -515,9 +785,9 @@ throw 'textDocument is required but was not provided'; } } - factory CodeLensParams.fromJson(Map<String, dynamic> json) { + static CodeLensParams fromJson(Map<String, dynamic> json) { final textDocument = json['textDocument'] != null - ? new TextDocumentIdentifier.fromJson(json['textDocument']) + ? TextDocumentIdentifier.fromJson(json['textDocument']) : null; return new CodeLensParams(textDocument); } @@ -537,15 +807,33 @@ obj.containsKey('textDocument') && TextDocumentIdentifier.canParse(obj['textDocument']); } + + @override + bool operator ==(other) { + if (other is CodeLensParams) { + return textDocument == other.textDocument && true; + } + return false; + } + + @override + int get hashCode { + int hash = 0; + hash = JenkinsSmiHash.combine(hash, textDocument.hashCode); + return JenkinsSmiHash.finish(hash); + } + + @override + String toString() => jsonEncoder.convert(toJson()); } class CodeLensRegistrationOptions implements TextDocumentRegistrationOptions, ToJsonable { CodeLensRegistrationOptions(this.resolveProvider, this.documentSelector); - factory CodeLensRegistrationOptions.fromJson(Map<String, dynamic> json) { + static CodeLensRegistrationOptions fromJson(Map<String, dynamic> json) { final resolveProvider = json['resolveProvider']; final documentSelector = json['documentSelector'] - ?.map((item) => item != null ? new DocumentFilter.fromJson(item) : null) + ?.map((item) => item != null ? DocumentFilter.fromJson(item) : null) ?.cast<DocumentFilter>() ?.toList(); return new CodeLensRegistrationOptions(resolveProvider, documentSelector); @@ -575,6 +863,27 @@ obj['documentSelector'] .every((item) => DocumentFilter.canParse(item)))); } + + @override + bool operator ==(other) { + if (other is CodeLensRegistrationOptions) { + return resolveProvider == other.resolveProvider && + documentSelector == other.documentSelector && + true; + } + return false; + } + + @override + int get hashCode { + int hash = 0; + hash = JenkinsSmiHash.combine(hash, resolveProvider.hashCode); + hash = JenkinsSmiHash.combine(hash, documentSelector.hashCode); + return JenkinsSmiHash.finish(hash); + } + + @override + String toString() => jsonEncoder.convert(toJson()); } /// Represents a color in RGBA space. @@ -593,7 +902,7 @@ throw 'alpha is required but was not provided'; } } - factory Color.fromJson(Map<String, dynamic> json) { + static Color fromJson(Map<String, dynamic> json) { final red = json['red']; final green = json['green']; final blue = json['blue']; @@ -601,9 +910,16 @@ return new Color(red, green, blue, alpha); } + /// The alpha component of this color in the range [0-1]. final num alpha; + + /// The blue component of this color in the range [0-1]. final num blue; + + /// The green component of this color in the range [0-1]. final num green; + + /// The red component of this color in the range [0-1]. final num red; Map<String, dynamic> toJson() { @@ -626,6 +942,31 @@ obj.containsKey('alpha') && obj['alpha'] is num; } + + @override + bool operator ==(other) { + if (other is Color) { + return red == other.red && + green == other.green && + blue == other.blue && + alpha == other.alpha && + true; + } + return false; + } + + @override + int get hashCode { + int hash = 0; + hash = JenkinsSmiHash.combine(hash, red.hashCode); + hash = JenkinsSmiHash.combine(hash, green.hashCode); + hash = JenkinsSmiHash.combine(hash, blue.hashCode); + hash = JenkinsSmiHash.combine(hash, alpha.hashCode); + return JenkinsSmiHash.finish(hash); + } + + @override + String toString() => jsonEncoder.convert(toJson()); } class ColorInformation implements ToJsonable { @@ -637,11 +978,9 @@ throw 'color is required but was not provided'; } } - factory ColorInformation.fromJson(Map<String, dynamic> json) { - final range = - json['range'] != null ? new Range.fromJson(json['range']) : null; - final color = - json['color'] != null ? new Color.fromJson(json['color']) : null; + static ColorInformation fromJson(Map<String, dynamic> json) { + final range = json['range'] != null ? Range.fromJson(json['range']) : null; + final color = json['color'] != null ? Color.fromJson(json['color']) : null; return new ColorInformation(range, color); } @@ -665,6 +1004,25 @@ obj.containsKey('color') && Color.canParse(obj['color']); } + + @override + bool operator ==(other) { + if (other is ColorInformation) { + return range == other.range && color == other.color && true; + } + return false; + } + + @override + int get hashCode { + int hash = 0; + hash = JenkinsSmiHash.combine(hash, range.hashCode); + hash = JenkinsSmiHash.combine(hash, color.hashCode); + return JenkinsSmiHash.finish(hash); + } + + @override + String toString() => jsonEncoder.convert(toJson()); } class ColorPresentation implements ToJsonable { @@ -673,13 +1031,12 @@ throw 'label is required but was not provided'; } } - factory ColorPresentation.fromJson(Map<String, dynamic> json) { + static ColorPresentation fromJson(Map<String, dynamic> json) { final label = json['label']; - final textEdit = json['textEdit'] != null - ? new TextEdit.fromJson(json['textEdit']) - : null; + final textEdit = + json['textEdit'] != null ? TextEdit.fromJson(json['textEdit']) : null; final additionalTextEdits = json['additionalTextEdits'] - ?.map((item) => item != null ? new TextEdit.fromJson(item) : null) + ?.map((item) => item != null ? TextEdit.fromJson(item) : null) ?.cast<TextEdit>() ?.toList(); return new ColorPresentation(label, textEdit, additionalTextEdits); @@ -717,6 +1074,30 @@ obj.containsKey('label') && obj['label'] is String; } + + @override + bool operator ==(other) { + if (other is ColorPresentation) { + return label == other.label && + textEdit == other.textEdit && + listEqual(additionalTextEdits, other.additionalTextEdits, + (TextEdit a, TextEdit b) => a == b) && + true; + } + return false; + } + + @override + int get hashCode { + int hash = 0; + hash = JenkinsSmiHash.combine(hash, label.hashCode); + hash = JenkinsSmiHash.combine(hash, textEdit.hashCode); + hash = JenkinsSmiHash.combine(hash, additionalTextEdits.hashCode); + return JenkinsSmiHash.finish(hash); + } + + @override + String toString() => jsonEncoder.convert(toJson()); } class ColorPresentationParams implements ToJsonable { @@ -731,14 +1112,12 @@ throw 'range is required but was not provided'; } } - factory ColorPresentationParams.fromJson(Map<String, dynamic> json) { + static ColorPresentationParams fromJson(Map<String, dynamic> json) { final textDocument = json['textDocument'] != null - ? new TextDocumentIdentifier.fromJson(json['textDocument']) + ? TextDocumentIdentifier.fromJson(json['textDocument']) : null; - final color = - json['color'] != null ? new Color.fromJson(json['color']) : null; - final range = - json['range'] != null ? new Range.fromJson(json['range']) : null; + final color = json['color'] != null ? Color.fromJson(json['color']) : null; + final range = json['range'] != null ? Range.fromJson(json['range']) : null; return new ColorPresentationParams(textDocument, color, range); } @@ -769,10 +1148,37 @@ obj.containsKey('range') && Range.canParse(obj['range']); } + + @override + bool operator ==(other) { + if (other is ColorPresentationParams) { + return textDocument == other.textDocument && + color == other.color && + range == other.range && + true; + } + return false; + } + + @override + int get hashCode { + int hash = 0; + hash = JenkinsSmiHash.combine(hash, textDocument.hashCode); + hash = JenkinsSmiHash.combine(hash, color.hashCode); + hash = JenkinsSmiHash.combine(hash, range.hashCode); + return JenkinsSmiHash.finish(hash); + } + + @override + String toString() => jsonEncoder.convert(toJson()); } /// Color provider options. class ColorProviderOptions implements ToJsonable { + static ColorProviderOptions fromJson(Map<String, dynamic> json) { + return new ColorProviderOptions(); + } + Map<String, dynamic> toJson() { Map<String, dynamic> __result = {}; return __result; @@ -781,6 +1187,23 @@ static bool canParse(Object obj) { return obj is Map<String, dynamic>; } + + @override + bool operator ==(other) { + if (other is ColorProviderOptions) { + return true; + } + return false; + } + + @override + int get hashCode { + int hash = 0; + return JenkinsSmiHash.finish(hash); + } + + @override + String toString() => jsonEncoder.convert(toJson()); } class Command implements ToJsonable { @@ -792,7 +1215,7 @@ throw 'command is required but was not provided'; } } - factory Command.fromJson(Map<String, dynamic> json) { + static Command fromJson(Map<String, dynamic> json) { final title = json['title']; final command = json['command']; final arguments = @@ -827,6 +1250,30 @@ obj.containsKey('command') && obj['command'] is String; } + + @override + bool operator ==(other) { + if (other is Command) { + return title == other.title && + command == other.command && + listEqual( + arguments, other.arguments, (dynamic a, dynamic b) => a == b) && + true; + } + return false; + } + + @override + int get hashCode { + int hash = 0; + hash = JenkinsSmiHash.combine(hash, title.hashCode); + hash = JenkinsSmiHash.combine(hash, command.hashCode); + hash = JenkinsSmiHash.combine(hash, arguments.hashCode); + return JenkinsSmiHash.finish(hash); + } + + @override + String toString() => jsonEncoder.convert(toJson()); } /// Contains additional information about the context in which a completion @@ -837,9 +1284,9 @@ throw 'triggerKind is required but was not provided'; } } - factory CompletionContext.fromJson(Map<String, dynamic> json) { + static CompletionContext fromJson(Map<String, dynamic> json) { final triggerKind = json['triggerKind'] != null - ? new CompletionTriggerKind.fromJson(json['triggerKind']) + ? CompletionTriggerKind.fromJson(json['triggerKind']) : null; final triggerCharacter = json['triggerCharacter']; return new CompletionContext(triggerKind, triggerCharacter); @@ -865,8 +1312,29 @@ static bool canParse(Object obj) { return obj is Map<String, dynamic> && obj.containsKey('triggerKind') && - CompletionTriggerKind.canParse(obj['triggerKind']); + obj['triggerKind'] is num; } + + @override + bool operator ==(other) { + if (other is CompletionContext) { + return triggerKind == other.triggerKind && + triggerCharacter == other.triggerCharacter && + true; + } + return false; + } + + @override + int get hashCode { + int hash = 0; + hash = JenkinsSmiHash.combine(hash, triggerKind.hashCode); + hash = JenkinsSmiHash.combine(hash, triggerCharacter.hashCode); + return JenkinsSmiHash.finish(hash); + } + + @override + String toString() => jsonEncoder.convert(toJson()); } class CompletionItem implements ToJsonable { @@ -890,39 +1358,39 @@ throw 'label is required but was not provided'; } } - factory CompletionItem.fromJson(Map<String, dynamic> json) { + static CompletionItem fromJson(Map<String, dynamic> json) { final label = json['label']; - final kind = json['kind'] != null - ? new CompletionItemKind.fromJson(json['kind']) - : null; + final kind = + json['kind'] != null ? CompletionItemKind.fromJson(json['kind']) : null; final detail = json['detail']; final documentation = json['documentation'] is String ? new Either2<String, MarkupContent>.t1(json['documentation']) : (MarkupContent.canParse(json['documentation']) ? new Either2<String, MarkupContent>.t2( json['documentation'] != null - ? new MarkupContent.fromJson(json['documentation']) + ? MarkupContent.fromJson(json['documentation']) : null) - : (throw '''${json['documentation']} was not one of (string, MarkupContent)''')); + : (json['documentation'] == null + ? null + : (throw '''${json['documentation']} was not one of (String, MarkupContent)'''))); final deprecated = json['deprecated']; final preselect = json['preselect']; final sortText = json['sortText']; final filterText = json['filterText']; final insertText = json['insertText']; final insertTextFormat = json['insertTextFormat'] != null - ? new InsertTextFormat.fromJson(json['insertTextFormat']) + ? InsertTextFormat.fromJson(json['insertTextFormat']) : null; - final textEdit = json['textEdit'] != null - ? new TextEdit.fromJson(json['textEdit']) - : null; + final textEdit = + json['textEdit'] != null ? TextEdit.fromJson(json['textEdit']) : null; final additionalTextEdits = json['additionalTextEdits'] - ?.map((item) => item != null ? new TextEdit.fromJson(item) : null) + ?.map((item) => item != null ? TextEdit.fromJson(item) : null) ?.cast<TextEdit>() ?.toList(); final commitCharacters = json['commitCharacters']?.map((item) => item)?.cast<String>()?.toList(); final command = - json['command'] != null ? new Command.fromJson(json['command']) : null; + json['command'] != null ? Command.fromJson(json['command']) : null; final data = json['data']; return new CompletionItem( label, @@ -1047,9 +1515,7 @@ if (filterText != null) { __result['filterText'] = filterText; } - // ignore: deprecated_member_use if (insertText != null) { - // ignore: deprecated_member_use __result['insertText'] = insertText; } if (insertTextFormat != null) { @@ -1078,6 +1544,55 @@ obj.containsKey('label') && obj['label'] is String; } + + @override + bool operator ==(other) { + if (other is CompletionItem) { + return label == other.label && + kind == other.kind && + detail == other.detail && + documentation == other.documentation && + deprecated == other.deprecated && + preselect == other.preselect && + sortText == other.sortText && + filterText == other.filterText && + insertText == other.insertText && + insertTextFormat == other.insertTextFormat && + textEdit == other.textEdit && + listEqual(additionalTextEdits, other.additionalTextEdits, + (TextEdit a, TextEdit b) => a == b) && + listEqual(commitCharacters, other.commitCharacters, + (String a, String b) => a == b) && + command == other.command && + data == other.data && + true; + } + return false; + } + + @override + int get hashCode { + int hash = 0; + hash = JenkinsSmiHash.combine(hash, label.hashCode); + hash = JenkinsSmiHash.combine(hash, kind.hashCode); + hash = JenkinsSmiHash.combine(hash, detail.hashCode); + hash = JenkinsSmiHash.combine(hash, documentation.hashCode); + hash = JenkinsSmiHash.combine(hash, deprecated.hashCode); + hash = JenkinsSmiHash.combine(hash, preselect.hashCode); + hash = JenkinsSmiHash.combine(hash, sortText.hashCode); + hash = JenkinsSmiHash.combine(hash, filterText.hashCode); + hash = JenkinsSmiHash.combine(hash, insertText.hashCode); + hash = JenkinsSmiHash.combine(hash, insertTextFormat.hashCode); + hash = JenkinsSmiHash.combine(hash, textEdit.hashCode); + hash = JenkinsSmiHash.combine(hash, additionalTextEdits.hashCode); + hash = JenkinsSmiHash.combine(hash, commitCharacters.hashCode); + hash = JenkinsSmiHash.combine(hash, command.hashCode); + hash = JenkinsSmiHash.combine(hash, data.hashCode); + return JenkinsSmiHash.finish(hash); + } + + @override + String toString() => jsonEncoder.convert(toJson()); } /// The kind of a completion entry. @@ -1085,7 +1600,7 @@ const CompletionItemKind._(this._value); const CompletionItemKind.fromJson(this._value); - final Object _value; + final num _value; static bool canParse(Object obj) { switch (obj) { @@ -1167,10 +1682,10 @@ throw 'items is required but was not provided'; } } - factory CompletionList.fromJson(Map<String, dynamic> json) { + static CompletionList fromJson(Map<String, dynamic> json) { final isIncomplete = json['isIncomplete']; final items = json['items'] - ?.map((item) => item != null ? new CompletionItem.fromJson(item) : null) + ?.map((item) => item != null ? CompletionItem.fromJson(item) : null) ?.cast<CompletionItem>() ?.toList(); return new CompletionList(isIncomplete, items); @@ -1200,12 +1715,34 @@ (obj['items'].length == 0 || obj['items'].every((item) => CompletionItem.canParse(item)))); } + + @override + bool operator ==(other) { + if (other is CompletionList) { + return isIncomplete == other.isIncomplete && + listEqual(items, other.items, + (CompletionItem a, CompletionItem b) => a == b) && + true; + } + return false; + } + + @override + int get hashCode { + int hash = 0; + hash = JenkinsSmiHash.combine(hash, isIncomplete.hashCode); + hash = JenkinsSmiHash.combine(hash, items.hashCode); + return JenkinsSmiHash.finish(hash); + } + + @override + String toString() => jsonEncoder.convert(toJson()); } /// Completion options. class CompletionOptions implements ToJsonable { CompletionOptions(this.resolveProvider, this.triggerCharacters); - factory CompletionOptions.fromJson(Map<String, dynamic> json) { + static CompletionOptions fromJson(Map<String, dynamic> json) { final resolveProvider = json['resolveProvider']; final triggerCharacters = json['triggerCharacters'] ?.map((item) => item) @@ -1235,6 +1772,28 @@ static bool canParse(Object obj) { return obj is Map<String, dynamic>; } + + @override + bool operator ==(other) { + if (other is CompletionOptions) { + return resolveProvider == other.resolveProvider && + listEqual(triggerCharacters, other.triggerCharacters, + (String a, String b) => a == b) && + true; + } + return false; + } + + @override + int get hashCode { + int hash = 0; + hash = JenkinsSmiHash.combine(hash, resolveProvider.hashCode); + hash = JenkinsSmiHash.combine(hash, triggerCharacters.hashCode); + return JenkinsSmiHash.finish(hash); + } + + @override + String toString() => jsonEncoder.convert(toJson()); } class CompletionParams implements TextDocumentPositionParams, ToJsonable { @@ -1246,22 +1805,21 @@ throw 'position is required but was not provided'; } } - factory CompletionParams.fromJson(Map<String, dynamic> json) { + static CompletionParams fromJson(Map<String, dynamic> json) { final context = json['context'] != null - ? new CompletionContext.fromJson(json['context']) + ? CompletionContext.fromJson(json['context']) : null; final textDocument = json['textDocument'] != null - ? new TextDocumentIdentifier.fromJson(json['textDocument']) + ? TextDocumentIdentifier.fromJson(json['textDocument']) : null; - final position = json['position'] != null - ? new Position.fromJson(json['position']) - : null; + final position = + json['position'] != null ? Position.fromJson(json['position']) : null; return new CompletionParams(context, textDocument, position); } - /// The completion context. This is only available if the client specifies - /// to send this using - /// `ClientCapabilities.textDocument.completion.contextSupport === true` + /// The completion context. This is only available if the client specifies to + /// send this using `ClientCapabilities.textDocument.completion.contextSupport + /// === true` final CompletionContext context; /// The position inside the text document. @@ -1289,20 +1847,43 @@ obj.containsKey('position') && Position.canParse(obj['position']); } + + @override + bool operator ==(other) { + if (other is CompletionParams) { + return context == other.context && + textDocument == other.textDocument && + position == other.position && + true; + } + return false; + } + + @override + int get hashCode { + int hash = 0; + hash = JenkinsSmiHash.combine(hash, context.hashCode); + hash = JenkinsSmiHash.combine(hash, textDocument.hashCode); + hash = JenkinsSmiHash.combine(hash, position.hashCode); + return JenkinsSmiHash.finish(hash); + } + + @override + String toString() => jsonEncoder.convert(toJson()); } class CompletionRegistrationOptions implements TextDocumentRegistrationOptions, ToJsonable { CompletionRegistrationOptions( this.triggerCharacters, this.resolveProvider, this.documentSelector); - factory CompletionRegistrationOptions.fromJson(Map<String, dynamic> json) { + static CompletionRegistrationOptions fromJson(Map<String, dynamic> json) { final triggerCharacters = json['triggerCharacters'] ?.map((item) => item) ?.cast<String>() ?.toList(); final resolveProvider = json['resolveProvider']; final documentSelector = json['documentSelector'] - ?.map((item) => item != null ? new DocumentFilter.fromJson(item) : null) + ?.map((item) => item != null ? DocumentFilter.fromJson(item) : null) ?.cast<DocumentFilter>() ?.toList(); return new CompletionRegistrationOptions( @@ -1318,11 +1899,11 @@ final bool resolveProvider; /// Most tools trigger completion request automatically without explicitly - /// requesting it using a keyboard shortcut (e.g. Ctrl+Space). Typically - /// they do so when the user starts to type an identifier. For example if - /// the user types `c` in a JavaScript file code complete will automatically - /// pop up present `console` besides others as a completion item. Characters - /// that make up identifiers don't need to be listed here. + /// requesting it using a keyboard shortcut (e.g. Ctrl+Space). Typically they + /// do so when the user starts to type an identifier. For example if the user + /// types `c` in a JavaScript file code complete will automatically pop up + /// present `console` besides others as a completion item. Characters that + /// make up identifiers don't need to be listed here. /// /// If code complete should automatically be trigger on characters not being /// valid inside an identifier (for example `.` in JavaScript) list them in @@ -1349,6 +1930,30 @@ obj['documentSelector'] .every((item) => DocumentFilter.canParse(item)))); } + + @override + bool operator ==(other) { + if (other is CompletionRegistrationOptions) { + return listEqual(triggerCharacters, other.triggerCharacters, + (String a, String b) => a == b) && + resolveProvider == other.resolveProvider && + documentSelector == other.documentSelector && + true; + } + return false; + } + + @override + int get hashCode { + int hash = 0; + hash = JenkinsSmiHash.combine(hash, triggerCharacters.hashCode); + hash = JenkinsSmiHash.combine(hash, resolveProvider.hashCode); + hash = JenkinsSmiHash.combine(hash, documentSelector.hashCode); + return JenkinsSmiHash.finish(hash); + } + + @override + String toString() => jsonEncoder.convert(toJson()); } /// How a completion was triggered @@ -1356,7 +1961,7 @@ const CompletionTriggerKind._(this._value); const CompletionTriggerKind.fromJson(this._value); - final Object _value; + final num _value; static bool canParse(Object obj) { switch (obj) { @@ -1376,8 +1981,7 @@ /// `triggerCharacters` properties of the `CompletionRegistrationOptions`. static const TriggerCharacter = const CompletionTriggerKind._(2); - /// Completion was re-triggered as the current completion list is - /// incomplete. + /// Completion was re-triggered as the current completion list is incomplete. static const TriggerForIncompleteCompletions = const CompletionTriggerKind._(3); @@ -1394,7 +1998,7 @@ class ConfigurationItem implements ToJsonable { ConfigurationItem(this.scopeUri, this.section); - factory ConfigurationItem.fromJson(Map<String, dynamic> json) { + static ConfigurationItem fromJson(Map<String, dynamic> json) { final scopeUri = json['scopeUri']; final section = json['section']; return new ConfigurationItem(scopeUri, section); @@ -1420,6 +2024,25 @@ static bool canParse(Object obj) { return obj is Map<String, dynamic>; } + + @override + bool operator ==(other) { + if (other is ConfigurationItem) { + return scopeUri == other.scopeUri && section == other.section && true; + } + return false; + } + + @override + int get hashCode { + int hash = 0; + hash = JenkinsSmiHash.combine(hash, scopeUri.hashCode); + hash = JenkinsSmiHash.combine(hash, section.hashCode); + return JenkinsSmiHash.finish(hash); + } + + @override + String toString() => jsonEncoder.convert(toJson()); } class ConfigurationParams implements ToJsonable { @@ -1428,10 +2051,9 @@ throw 'items is required but was not provided'; } } - factory ConfigurationParams.fromJson(Map<String, dynamic> json) { + static ConfigurationParams fromJson(Map<String, dynamic> json) { final items = json['items'] - ?.map((item) => - item != null ? new ConfigurationItem.fromJson(item) : null) + ?.map((item) => item != null ? ConfigurationItem.fromJson(item) : null) ?.cast<ConfigurationItem>() ?.toList(); return new ConfigurationParams(items); @@ -1453,23 +2075,50 @@ obj['items'] .every((item) => ConfigurationItem.canParse(item)))); } + + @override + bool operator ==(other) { + if (other is ConfigurationParams) { + return listEqual(items, other.items, + (ConfigurationItem a, ConfigurationItem b) => a == b) && + true; + } + return false; + } + + @override + int get hashCode { + int hash = 0; + hash = JenkinsSmiHash.combine(hash, items.hashCode); + return JenkinsSmiHash.finish(hash); + } + + @override + String toString() => jsonEncoder.convert(toJson()); } /// Create file operation -class CreateFile implements FileOperation, ToJsonable { - CreateFile(this.uri, this.options) { +class CreateFile implements ToJsonable { + CreateFile(this.kind, this.uri, this.options) { + if (kind == null) { + throw 'kind is required but was not provided'; + } if (uri == null) { throw 'uri is required but was not provided'; } } - factory CreateFile.fromJson(Map<String, dynamic> json) { + static CreateFile fromJson(Map<String, dynamic> json) { + final kind = json['kind']; final uri = json['uri']; final options = json['options'] != null - ? new CreateFileOptions.fromJson(json['options']) + ? CreateFileOptions.fromJson(json['options']) : null; - return new CreateFile(uri, options); + return new CreateFile(kind, uri, options); } + /// A create + final String kind; + /// Additional options final CreateFileOptions options; @@ -1478,6 +2127,7 @@ Map<String, dynamic> toJson() { Map<String, dynamic> __result = {}; + __result['kind'] = kind ?? (throw 'kind is required but was not set'); __result['uri'] = uri ?? (throw 'uri is required but was not set'); if (options != null) { __result['options'] = options; @@ -1487,15 +2137,40 @@ static bool canParse(Object obj) { return obj is Map<String, dynamic> && + obj.containsKey('kind') && + obj['kind'] is String && obj.containsKey('uri') && obj['uri'] is String; } + + @override + bool operator ==(other) { + if (other is CreateFile) { + return kind == other.kind && + uri == other.uri && + options == other.options && + true; + } + return false; + } + + @override + int get hashCode { + int hash = 0; + hash = JenkinsSmiHash.combine(hash, kind.hashCode); + hash = JenkinsSmiHash.combine(hash, uri.hashCode); + hash = JenkinsSmiHash.combine(hash, options.hashCode); + return JenkinsSmiHash.finish(hash); + } + + @override + String toString() => jsonEncoder.convert(toJson()); } /// Options to create a file. class CreateFileOptions implements ToJsonable { CreateFileOptions(this.overwrite, this.ignoreIfExists); - factory CreateFileOptions.fromJson(Map<String, dynamic> json) { + static CreateFileOptions fromJson(Map<String, dynamic> json) { final overwrite = json['overwrite']; final ignoreIfExists = json['ignoreIfExists']; return new CreateFileOptions(overwrite, ignoreIfExists); @@ -1521,23 +2196,51 @@ static bool canParse(Object obj) { return obj is Map<String, dynamic>; } + + @override + bool operator ==(other) { + if (other is CreateFileOptions) { + return overwrite == other.overwrite && + ignoreIfExists == other.ignoreIfExists && + true; + } + return false; + } + + @override + int get hashCode { + int hash = 0; + hash = JenkinsSmiHash.combine(hash, overwrite.hashCode); + hash = JenkinsSmiHash.combine(hash, ignoreIfExists.hashCode); + return JenkinsSmiHash.finish(hash); + } + + @override + String toString() => jsonEncoder.convert(toJson()); } /// Delete file operation -class DeleteFile implements FileOperation, ToJsonable { - DeleteFile(this.uri, this.options) { +class DeleteFile implements ToJsonable { + DeleteFile(this.kind, this.uri, this.options) { + if (kind == null) { + throw 'kind is required but was not provided'; + } if (uri == null) { throw 'uri is required but was not provided'; } } - factory DeleteFile.fromJson(Map<String, dynamic> json) { + static DeleteFile fromJson(Map<String, dynamic> json) { + final kind = json['kind']; final uri = json['uri']; final options = json['options'] != null - ? new DeleteFileOptions.fromJson(json['options']) + ? DeleteFileOptions.fromJson(json['options']) : null; - return new DeleteFile(uri, options); + return new DeleteFile(kind, uri, options); } + /// A delete + final String kind; + /// Delete options. final DeleteFileOptions options; @@ -1546,6 +2249,7 @@ Map<String, dynamic> toJson() { Map<String, dynamic> __result = {}; + __result['kind'] = kind ?? (throw 'kind is required but was not set'); __result['uri'] = uri ?? (throw 'uri is required but was not set'); if (options != null) { __result['options'] = options; @@ -1555,15 +2259,40 @@ static bool canParse(Object obj) { return obj is Map<String, dynamic> && + obj.containsKey('kind') && + obj['kind'] is String && obj.containsKey('uri') && obj['uri'] is String; } + + @override + bool operator ==(other) { + if (other is DeleteFile) { + return kind == other.kind && + uri == other.uri && + options == other.options && + true; + } + return false; + } + + @override + int get hashCode { + int hash = 0; + hash = JenkinsSmiHash.combine(hash, kind.hashCode); + hash = JenkinsSmiHash.combine(hash, uri.hashCode); + hash = JenkinsSmiHash.combine(hash, options.hashCode); + return JenkinsSmiHash.finish(hash); + } + + @override + String toString() => jsonEncoder.convert(toJson()); } /// Delete file options class DeleteFileOptions implements ToJsonable { DeleteFileOptions(this.recursive, this.ignoreIfNotExists); - factory DeleteFileOptions.fromJson(Map<String, dynamic> json) { + static DeleteFileOptions fromJson(Map<String, dynamic> json) { final recursive = json['recursive']; final ignoreIfNotExists = json['ignoreIfNotExists']; return new DeleteFileOptions(recursive, ignoreIfNotExists); @@ -1589,6 +2318,27 @@ static bool canParse(Object obj) { return obj is Map<String, dynamic>; } + + @override + bool operator ==(other) { + if (other is DeleteFileOptions) { + return recursive == other.recursive && + ignoreIfNotExists == other.ignoreIfNotExists && + true; + } + return false; + } + + @override + int get hashCode { + int hash = 0; + hash = JenkinsSmiHash.combine(hash, recursive.hashCode); + hash = JenkinsSmiHash.combine(hash, ignoreIfNotExists.hashCode); + return JenkinsSmiHash.finish(hash); + } + + @override + String toString() => jsonEncoder.convert(toJson()); } class Diagnostic implements ToJsonable { @@ -1601,23 +2351,17 @@ throw 'message is required but was not provided'; } } - factory Diagnostic.fromJson(Map<String, dynamic> json) { - final range = - json['range'] != null ? new Range.fromJson(json['range']) : null; + static Diagnostic fromJson(Map<String, dynamic> json) { + final range = json['range'] != null ? Range.fromJson(json['range']) : null; final severity = json['severity'] != null - ? new DiagnosticSeverity.fromJson(json['severity']) + ? DiagnosticSeverity.fromJson(json['severity']) : null; - final code = json['code'] is num - ? new Either2<num, String>.t1(json['code']) - : (json['code'] is String - ? new Either2<num, String>.t2(json['code']) - : (throw '''${json['code']} was not one of (number, string)''')); + final code = json['code']; final source = json['source']; final message = json['message']; final relatedInformation = json['relatedInformation'] - ?.map((item) => item != null - ? new DiagnosticRelatedInformation.fromJson(item) - : null) + ?.map((item) => + item != null ? DiagnosticRelatedInformation.fromJson(item) : null) ?.cast<DiagnosticRelatedInformation>() ?.toList(); return new Diagnostic( @@ -1625,7 +2369,7 @@ } /// The diagnostic's code, which might appear in the user interface. - final Either2<num, String> code; + final String code; /// The diagnostic's message. final String message; @@ -1633,9 +2377,8 @@ /// The range at which the message applies. final Range range; - /// An array of related diagnostic information, e.g. when symbol-names - /// within a scope collide all definitions can be marked via this - /// property. + /// An array of related diagnostic information, e.g. when symbol-names within + /// a scope collide all definitions can be marked via this property. final List<DiagnosticRelatedInformation> relatedInformation; /// The diagnostic's severity. Can be omitted. If omitted it is up to the @@ -1673,11 +2416,45 @@ obj.containsKey('message') && obj['message'] is String; } + + @override + bool operator ==(other) { + if (other is Diagnostic) { + return range == other.range && + severity == other.severity && + code == other.code && + source == other.source && + message == other.message && + listEqual( + relatedInformation, + other.relatedInformation, + (DiagnosticRelatedInformation a, + DiagnosticRelatedInformation b) => + a == b) && + true; + } + return false; + } + + @override + int get hashCode { + int hash = 0; + hash = JenkinsSmiHash.combine(hash, range.hashCode); + hash = JenkinsSmiHash.combine(hash, severity.hashCode); + hash = JenkinsSmiHash.combine(hash, code.hashCode); + hash = JenkinsSmiHash.combine(hash, source.hashCode); + hash = JenkinsSmiHash.combine(hash, message.hashCode); + hash = JenkinsSmiHash.combine(hash, relatedInformation.hashCode); + return JenkinsSmiHash.finish(hash); + } + + @override + String toString() => jsonEncoder.convert(toJson()); } -/// Represents a related message and source code location for a diagnostic. -/// This should be used to point to code locations that cause or related to -/// a diagnostics, e.g when duplicating a symbol in a scope. +/// Represents a related message and source code location for a diagnostic. This +/// should be used to point to code locations that cause or related to a +/// diagnostics, e.g when duplicating a symbol in a scope. class DiagnosticRelatedInformation implements ToJsonable { DiagnosticRelatedInformation(this.location, this.message) { if (location == null) { @@ -1687,10 +2464,9 @@ throw 'message is required but was not provided'; } } - factory DiagnosticRelatedInformation.fromJson(Map<String, dynamic> json) { - final location = json['location'] != null - ? new Location.fromJson(json['location']) - : null; + static DiagnosticRelatedInformation fromJson(Map<String, dynamic> json) { + final location = + json['location'] != null ? Location.fromJson(json['location']) : null; final message = json['message']; return new DiagnosticRelatedInformation(location, message); } @@ -1717,13 +2493,32 @@ obj.containsKey('message') && obj['message'] is String; } + + @override + bool operator ==(other) { + if (other is DiagnosticRelatedInformation) { + return location == other.location && message == other.message && true; + } + return false; + } + + @override + int get hashCode { + int hash = 0; + hash = JenkinsSmiHash.combine(hash, location.hashCode); + hash = JenkinsSmiHash.combine(hash, message.hashCode); + return JenkinsSmiHash.finish(hash); + } + + @override + String toString() => jsonEncoder.convert(toJson()); } class DiagnosticSeverity { const DiagnosticSeverity._(this._value); const DiagnosticSeverity.fromJson(this._value); - final Object _value; + final num _value; static bool canParse(Object obj) { switch (obj) { @@ -1765,7 +2560,7 @@ throw 'settings is required but was not provided'; } } - factory DidChangeConfigurationParams.fromJson(Map<String, dynamic> json) { + static DidChangeConfigurationParams fromJson(Map<String, dynamic> json) { final settings = json['settings']; return new DidChangeConfigurationParams(settings); } @@ -1783,6 +2578,24 @@ static bool canParse(Object obj) { return obj is Map<String, dynamic> && obj.containsKey('settings') && true; } + + @override + bool operator ==(other) { + if (other is DidChangeConfigurationParams) { + return settings == other.settings && true; + } + return false; + } + + @override + int get hashCode { + int hash = 0; + hash = JenkinsSmiHash.combine(hash, settings.hashCode); + return JenkinsSmiHash.finish(hash); + } + + @override + String toString() => jsonEncoder.convert(toJson()); } class DidChangeTextDocumentParams implements ToJsonable { @@ -1794,27 +2607,25 @@ throw 'contentChanges is required but was not provided'; } } - factory DidChangeTextDocumentParams.fromJson(Map<String, dynamic> json) { + static DidChangeTextDocumentParams fromJson(Map<String, dynamic> json) { final textDocument = json['textDocument'] != null - ? new VersionedTextDocumentIdentifier.fromJson(json['textDocument']) + ? VersionedTextDocumentIdentifier.fromJson(json['textDocument']) : null; final contentChanges = json['contentChanges'] - ?.map((item) => item != null - ? new TextDocumentContentChangeEvent.fromJson(item) - : null) + ?.map((item) => + item != null ? TextDocumentContentChangeEvent.fromJson(item) : null) ?.cast<TextDocumentContentChangeEvent>() ?.toList(); return new DidChangeTextDocumentParams(textDocument, contentChanges); } - /// The actual content changes. The content changes describe single - /// state changes to the document. So if there are two content changes - /// c1 and c2 for a document in state S then c1 move the document to S' - /// and c2 to S''. + /// The actual content changes. The content changes describe single state + /// changes to the document. So if there are two content changes c1 and c2 for + /// a document in state S then c1 move the document to S' and c2 to S''. final List<TextDocumentContentChangeEvent> contentChanges; - /// The document that did change. The version number points to the - /// version after all provided content changes have been applied. + /// The document that did change. The version number points to the version + /// after all provided content changes have been applied. final VersionedTextDocumentIdentifier textDocument; Map<String, dynamic> toJson() { @@ -1836,6 +2647,32 @@ obj['contentChanges'].every( (item) => TextDocumentContentChangeEvent.canParse(item)))); } + + @override + bool operator ==(other) { + if (other is DidChangeTextDocumentParams) { + return textDocument == other.textDocument && + listEqual( + contentChanges, + other.contentChanges, + (TextDocumentContentChangeEvent a, + TextDocumentContentChangeEvent b) => + a == b) && + true; + } + return false; + } + + @override + int get hashCode { + int hash = 0; + hash = JenkinsSmiHash.combine(hash, textDocument.hashCode); + hash = JenkinsSmiHash.combine(hash, contentChanges.hashCode); + return JenkinsSmiHash.finish(hash); + } + + @override + String toString() => jsonEncoder.convert(toJson()); } class DidChangeWatchedFilesParams implements ToJsonable { @@ -1844,9 +2681,9 @@ throw 'changes is required but was not provided'; } } - factory DidChangeWatchedFilesParams.fromJson(Map<String, dynamic> json) { + static DidChangeWatchedFilesParams fromJson(Map<String, dynamic> json) { final changes = json['changes'] - ?.map((item) => item != null ? new FileEvent.fromJson(item) : null) + ?.map((item) => item != null ? FileEvent.fromJson(item) : null) ?.cast<FileEvent>() ?.toList(); return new DidChangeWatchedFilesParams(changes); @@ -1869,6 +2706,26 @@ (obj['changes'].length == 0 || obj['changes'].every((item) => FileEvent.canParse(item)))); } + + @override + bool operator ==(other) { + if (other is DidChangeWatchedFilesParams) { + return listEqual( + changes, other.changes, (FileEvent a, FileEvent b) => a == b) && + true; + } + return false; + } + + @override + int get hashCode { + int hash = 0; + hash = JenkinsSmiHash.combine(hash, changes.hashCode); + return JenkinsSmiHash.finish(hash); + } + + @override + String toString() => jsonEncoder.convert(toJson()); } /// Describe options to be used when registering for text document change @@ -1879,11 +2736,10 @@ throw 'watchers is required but was not provided'; } } - factory DidChangeWatchedFilesRegistrationOptions.fromJson( + static DidChangeWatchedFilesRegistrationOptions fromJson( Map<String, dynamic> json) { final watchers = json['watchers'] - ?.map((item) => - item != null ? new FileSystemWatcher.fromJson(item) : null) + ?.map((item) => item != null ? FileSystemWatcher.fromJson(item) : null) ?.cast<FileSystemWatcher>() ?.toList(); return new DidChangeWatchedFilesRegistrationOptions(watchers); @@ -1907,6 +2763,26 @@ obj['watchers'] .every((item) => FileSystemWatcher.canParse(item)))); } + + @override + bool operator ==(other) { + if (other is DidChangeWatchedFilesRegistrationOptions) { + return listEqual(watchers, other.watchers, + (FileSystemWatcher a, FileSystemWatcher b) => a == b) && + true; + } + return false; + } + + @override + int get hashCode { + int hash = 0; + hash = JenkinsSmiHash.combine(hash, watchers.hashCode); + return JenkinsSmiHash.finish(hash); + } + + @override + String toString() => jsonEncoder.convert(toJson()); } class DidChangeWorkspaceFoldersParams implements ToJsonable { @@ -1915,9 +2791,9 @@ throw 'event is required but was not provided'; } } - factory DidChangeWorkspaceFoldersParams.fromJson(Map<String, dynamic> json) { + static DidChangeWorkspaceFoldersParams fromJson(Map<String, dynamic> json) { final event = json['event'] != null - ? new WorkspaceFoldersChangeEvent.fromJson(json['event']) + ? WorkspaceFoldersChangeEvent.fromJson(json['event']) : null; return new DidChangeWorkspaceFoldersParams(event); } @@ -1936,6 +2812,24 @@ obj.containsKey('event') && WorkspaceFoldersChangeEvent.canParse(obj['event']); } + + @override + bool operator ==(other) { + if (other is DidChangeWorkspaceFoldersParams) { + return event == other.event && true; + } + return false; + } + + @override + int get hashCode { + int hash = 0; + hash = JenkinsSmiHash.combine(hash, event.hashCode); + return JenkinsSmiHash.finish(hash); + } + + @override + String toString() => jsonEncoder.convert(toJson()); } class DidCloseTextDocumentParams implements ToJsonable { @@ -1944,9 +2838,9 @@ throw 'textDocument is required but was not provided'; } } - factory DidCloseTextDocumentParams.fromJson(Map<String, dynamic> json) { + static DidCloseTextDocumentParams fromJson(Map<String, dynamic> json) { final textDocument = json['textDocument'] != null - ? new TextDocumentIdentifier.fromJson(json['textDocument']) + ? TextDocumentIdentifier.fromJson(json['textDocument']) : null; return new DidCloseTextDocumentParams(textDocument); } @@ -1966,6 +2860,24 @@ obj.containsKey('textDocument') && TextDocumentIdentifier.canParse(obj['textDocument']); } + + @override + bool operator ==(other) { + if (other is DidCloseTextDocumentParams) { + return textDocument == other.textDocument && true; + } + return false; + } + + @override + int get hashCode { + int hash = 0; + hash = JenkinsSmiHash.combine(hash, textDocument.hashCode); + return JenkinsSmiHash.finish(hash); + } + + @override + String toString() => jsonEncoder.convert(toJson()); } class DidOpenTextDocumentParams implements ToJsonable { @@ -1974,9 +2886,9 @@ throw 'textDocument is required but was not provided'; } } - factory DidOpenTextDocumentParams.fromJson(Map<String, dynamic> json) { + static DidOpenTextDocumentParams fromJson(Map<String, dynamic> json) { final textDocument = json['textDocument'] != null - ? new TextDocumentItem.fromJson(json['textDocument']) + ? TextDocumentItem.fromJson(json['textDocument']) : null; return new DidOpenTextDocumentParams(textDocument); } @@ -1996,6 +2908,24 @@ obj.containsKey('textDocument') && TextDocumentItem.canParse(obj['textDocument']); } + + @override + bool operator ==(other) { + if (other is DidOpenTextDocumentParams) { + return textDocument == other.textDocument && true; + } + return false; + } + + @override + int get hashCode { + int hash = 0; + hash = JenkinsSmiHash.combine(hash, textDocument.hashCode); + return JenkinsSmiHash.finish(hash); + } + + @override + String toString() => jsonEncoder.convert(toJson()); } class DidSaveTextDocumentParams implements ToJsonable { @@ -2004,16 +2934,16 @@ throw 'textDocument is required but was not provided'; } } - factory DidSaveTextDocumentParams.fromJson(Map<String, dynamic> json) { + static DidSaveTextDocumentParams fromJson(Map<String, dynamic> json) { final textDocument = json['textDocument'] != null - ? new TextDocumentIdentifier.fromJson(json['textDocument']) + ? TextDocumentIdentifier.fromJson(json['textDocument']) : null; final text = json['text']; return new DidSaveTextDocumentParams(textDocument, text); } - /// Optional the content when saved. Depends on the includeText value - /// when the save notification was requested. + /// Optional the content when saved. Depends on the includeText value when the + /// save notification was requested. final String text; /// The document that was saved. @@ -2034,11 +2964,30 @@ obj.containsKey('textDocument') && TextDocumentIdentifier.canParse(obj['textDocument']); } + + @override + bool operator ==(other) { + if (other is DidSaveTextDocumentParams) { + return textDocument == other.textDocument && text == other.text && true; + } + return false; + } + + @override + int get hashCode { + int hash = 0; + hash = JenkinsSmiHash.combine(hash, textDocument.hashCode); + hash = JenkinsSmiHash.combine(hash, text.hashCode); + return JenkinsSmiHash.finish(hash); + } + + @override + String toString() => jsonEncoder.convert(toJson()); } class DocumentFilter implements ToJsonable { DocumentFilter(this.language, this.scheme, this.pattern); - factory DocumentFilter.fromJson(Map<String, dynamic> json) { + static DocumentFilter fromJson(Map<String, dynamic> json) { final language = json['language']; final scheme = json['scheme']; final pattern = json['pattern']; @@ -2071,6 +3020,29 @@ static bool canParse(Object obj) { return obj is Map<String, dynamic>; } + + @override + bool operator ==(other) { + if (other is DocumentFilter) { + return language == other.language && + scheme == other.scheme && + pattern == other.pattern && + true; + } + return false; + } + + @override + int get hashCode { + int hash = 0; + hash = JenkinsSmiHash.combine(hash, language.hashCode); + hash = JenkinsSmiHash.combine(hash, scheme.hashCode); + hash = JenkinsSmiHash.combine(hash, pattern.hashCode); + return JenkinsSmiHash.finish(hash); + } + + @override + String toString() => jsonEncoder.convert(toJson()); } class DocumentFormattingParams implements ToJsonable { @@ -2082,12 +3054,12 @@ throw 'options is required but was not provided'; } } - factory DocumentFormattingParams.fromJson(Map<String, dynamic> json) { + static DocumentFormattingParams fromJson(Map<String, dynamic> json) { final textDocument = json['textDocument'] != null - ? new TextDocumentIdentifier.fromJson(json['textDocument']) + ? TextDocumentIdentifier.fromJson(json['textDocument']) : null; final options = json['options'] != null - ? new FormattingOptions.fromJson(json['options']) + ? FormattingOptions.fromJson(json['options']) : null; return new DocumentFormattingParams(textDocument, options); } @@ -2114,22 +3086,42 @@ obj.containsKey('options') && FormattingOptions.canParse(obj['options']); } + + @override + bool operator ==(other) { + if (other is DocumentFormattingParams) { + return textDocument == other.textDocument && + options == other.options && + true; + } + return false; + } + + @override + int get hashCode { + int hash = 0; + hash = JenkinsSmiHash.combine(hash, textDocument.hashCode); + hash = JenkinsSmiHash.combine(hash, options.hashCode); + return JenkinsSmiHash.finish(hash); + } + + @override + String toString() => jsonEncoder.convert(toJson()); } /// A document highlight is a range inside a text document which deserves -/// special attention. Usually a document highlight is visualized by -/// changing the background color of its range. +/// special attention. Usually a document highlight is visualized by changing +/// the background color of its range. class DocumentHighlight implements ToJsonable { DocumentHighlight(this.range, this.kind) { if (range == null) { throw 'range is required but was not provided'; } } - factory DocumentHighlight.fromJson(Map<String, dynamic> json) { - final range = - json['range'] != null ? new Range.fromJson(json['range']) : null; + static DocumentHighlight fromJson(Map<String, dynamic> json) { + final range = json['range'] != null ? Range.fromJson(json['range']) : null; final kind = json['kind'] != null - ? new DocumentHighlightKind.fromJson(json['kind']) + ? DocumentHighlightKind.fromJson(json['kind']) : null; return new DocumentHighlight(range, kind); } @@ -2154,6 +3146,25 @@ obj.containsKey('range') && Range.canParse(obj['range']); } + + @override + bool operator ==(other) { + if (other is DocumentHighlight) { + return range == other.range && kind == other.kind && true; + } + return false; + } + + @override + int get hashCode { + int hash = 0; + hash = JenkinsSmiHash.combine(hash, range.hashCode); + hash = JenkinsSmiHash.combine(hash, kind.hashCode); + return JenkinsSmiHash.finish(hash); + } + + @override + String toString() => jsonEncoder.convert(toJson()); } /// A document highlight kind. @@ -2161,7 +3172,7 @@ const DocumentHighlightKind._(this._value); const DocumentHighlightKind.fromJson(this._value); - final Object _value; + final num _value; static bool canParse(Object obj) { switch (obj) { @@ -2193,18 +3204,16 @@ bool operator ==(o) => o is DocumentHighlightKind && o._value == _value; } -/// A document link is a range in a text document that links to an -/// internal or external resource, like another text document or a web -/// site. +/// A document link is a range in a text document that links to an internal or +/// external resource, like another text document or a web site. class DocumentLink implements ToJsonable { DocumentLink(this.range, this.target, this.data) { if (range == null) { throw 'range is required but was not provided'; } } - factory DocumentLink.fromJson(Map<String, dynamic> json) { - final range = - json['range'] != null ? new Range.fromJson(json['range']) : null; + static DocumentLink fromJson(Map<String, dynamic> json) { + final range = json['range'] != null ? Range.fromJson(json['range']) : null; final target = json['target']; final data = json['data']; return new DocumentLink(range, target, data); @@ -2217,8 +3226,7 @@ /// The range this link applies to. final Range range; - /// The uri this link points to. If missing a resolve request is sent - /// later. + /// The uri this link points to. If missing a resolve request is sent later. final String target; Map<String, dynamic> toJson() { @@ -2238,12 +3246,35 @@ obj.containsKey('range') && Range.canParse(obj['range']); } + + @override + bool operator ==(other) { + if (other is DocumentLink) { + return range == other.range && + target == other.target && + data == other.data && + true; + } + return false; + } + + @override + int get hashCode { + int hash = 0; + hash = JenkinsSmiHash.combine(hash, range.hashCode); + hash = JenkinsSmiHash.combine(hash, target.hashCode); + hash = JenkinsSmiHash.combine(hash, data.hashCode); + return JenkinsSmiHash.finish(hash); + } + + @override + String toString() => jsonEncoder.convert(toJson()); } /// Document link options. class DocumentLinkOptions implements ToJsonable { DocumentLinkOptions(this.resolveProvider); - factory DocumentLinkOptions.fromJson(Map<String, dynamic> json) { + static DocumentLinkOptions fromJson(Map<String, dynamic> json) { final resolveProvider = json['resolveProvider']; return new DocumentLinkOptions(resolveProvider); } @@ -2262,6 +3293,24 @@ static bool canParse(Object obj) { return obj is Map<String, dynamic>; } + + @override + bool operator ==(other) { + if (other is DocumentLinkOptions) { + return resolveProvider == other.resolveProvider && true; + } + return false; + } + + @override + int get hashCode { + int hash = 0; + hash = JenkinsSmiHash.combine(hash, resolveProvider.hashCode); + return JenkinsSmiHash.finish(hash); + } + + @override + String toString() => jsonEncoder.convert(toJson()); } class DocumentLinkParams implements ToJsonable { @@ -2270,9 +3319,9 @@ throw 'textDocument is required but was not provided'; } } - factory DocumentLinkParams.fromJson(Map<String, dynamic> json) { + static DocumentLinkParams fromJson(Map<String, dynamic> json) { final textDocument = json['textDocument'] != null - ? new TextDocumentIdentifier.fromJson(json['textDocument']) + ? TextDocumentIdentifier.fromJson(json['textDocument']) : null; return new DocumentLinkParams(textDocument); } @@ -2292,24 +3341,41 @@ obj.containsKey('textDocument') && TextDocumentIdentifier.canParse(obj['textDocument']); } + + @override + bool operator ==(other) { + if (other is DocumentLinkParams) { + return textDocument == other.textDocument && true; + } + return false; + } + + @override + int get hashCode { + int hash = 0; + hash = JenkinsSmiHash.combine(hash, textDocument.hashCode); + return JenkinsSmiHash.finish(hash); + } + + @override + String toString() => jsonEncoder.convert(toJson()); } class DocumentLinkRegistrationOptions implements TextDocumentRegistrationOptions, ToJsonable { DocumentLinkRegistrationOptions(this.resolveProvider, this.documentSelector); - factory DocumentLinkRegistrationOptions.fromJson(Map<String, dynamic> json) { + static DocumentLinkRegistrationOptions fromJson(Map<String, dynamic> json) { final resolveProvider = json['resolveProvider']; final documentSelector = json['documentSelector'] - ?.map((item) => item != null ? new DocumentFilter.fromJson(item) : null) + ?.map((item) => item != null ? DocumentFilter.fromJson(item) : null) ?.cast<DocumentFilter>() ?.toList(); return new DocumentLinkRegistrationOptions( resolveProvider, documentSelector); } - /// A document selector to identify the scope of the registration. If - /// set to null the document selector provided on the client side will - /// be used. + /// A document selector to identify the scope of the registration. If set to + /// null the document selector provided on the client side will be used. final List<DocumentFilter> documentSelector; /// Document links have a resolve provider as well. @@ -2332,6 +3398,27 @@ obj['documentSelector'] .every((item) => DocumentFilter.canParse(item)))); } + + @override + bool operator ==(other) { + if (other is DocumentLinkRegistrationOptions) { + return resolveProvider == other.resolveProvider && + documentSelector == other.documentSelector && + true; + } + return false; + } + + @override + int get hashCode { + int hash = 0; + hash = JenkinsSmiHash.combine(hash, resolveProvider.hashCode); + hash = JenkinsSmiHash.combine(hash, documentSelector.hashCode); + return JenkinsSmiHash.finish(hash); + } + + @override + String toString() => jsonEncoder.convert(toJson()); } /// Format document on type options. @@ -2342,7 +3429,7 @@ throw 'firstTriggerCharacter is required but was not provided'; } } - factory DocumentOnTypeFormattingOptions.fromJson(Map<String, dynamic> json) { + static DocumentOnTypeFormattingOptions fromJson(Map<String, dynamic> json) { final firstTriggerCharacter = json['firstTriggerCharacter']; final moreTriggerCharacter = json['moreTriggerCharacter'] ?.map((item) => item) @@ -2373,6 +3460,28 @@ obj.containsKey('firstTriggerCharacter') && obj['firstTriggerCharacter'] is String; } + + @override + bool operator ==(other) { + if (other is DocumentOnTypeFormattingOptions) { + return firstTriggerCharacter == other.firstTriggerCharacter && + listEqual(moreTriggerCharacter, other.moreTriggerCharacter, + (String a, String b) => a == b) && + true; + } + return false; + } + + @override + int get hashCode { + int hash = 0; + hash = JenkinsSmiHash.combine(hash, firstTriggerCharacter.hashCode); + hash = JenkinsSmiHash.combine(hash, moreTriggerCharacter.hashCode); + return JenkinsSmiHash.finish(hash); + } + + @override + String toString() => jsonEncoder.convert(toJson()); } class DocumentOnTypeFormattingParams implements ToJsonable { @@ -2391,16 +3500,15 @@ throw 'options is required but was not provided'; } } - factory DocumentOnTypeFormattingParams.fromJson(Map<String, dynamic> json) { + static DocumentOnTypeFormattingParams fromJson(Map<String, dynamic> json) { final textDocument = json['textDocument'] != null - ? new TextDocumentIdentifier.fromJson(json['textDocument']) + ? TextDocumentIdentifier.fromJson(json['textDocument']) : null; - final position = json['position'] != null - ? new Position.fromJson(json['position']) - : null; + final position = + json['position'] != null ? Position.fromJson(json['position']) : null; final ch = json['ch']; final options = json['options'] != null - ? new FormattingOptions.fromJson(json['options']) + ? FormattingOptions.fromJson(json['options']) : null; return new DocumentOnTypeFormattingParams( textDocument, position, ch, options); @@ -2441,6 +3549,31 @@ obj.containsKey('options') && FormattingOptions.canParse(obj['options']); } + + @override + bool operator ==(other) { + if (other is DocumentOnTypeFormattingParams) { + return textDocument == other.textDocument && + position == other.position && + ch == other.ch && + options == other.options && + true; + } + return false; + } + + @override + int get hashCode { + int hash = 0; + hash = JenkinsSmiHash.combine(hash, textDocument.hashCode); + hash = JenkinsSmiHash.combine(hash, position.hashCode); + hash = JenkinsSmiHash.combine(hash, ch.hashCode); + hash = JenkinsSmiHash.combine(hash, options.hashCode); + return JenkinsSmiHash.finish(hash); + } + + @override + String toString() => jsonEncoder.convert(toJson()); } class DocumentOnTypeFormattingRegistrationOptions @@ -2451,7 +3584,7 @@ throw 'firstTriggerCharacter is required but was not provided'; } } - factory DocumentOnTypeFormattingRegistrationOptions.fromJson( + static DocumentOnTypeFormattingRegistrationOptions fromJson( Map<String, dynamic> json) { final firstTriggerCharacter = json['firstTriggerCharacter']; final moreTriggerCharacter = json['moreTriggerCharacter'] @@ -2459,16 +3592,15 @@ ?.cast<String>() ?.toList(); final documentSelector = json['documentSelector'] - ?.map((item) => item != null ? new DocumentFilter.fromJson(item) : null) + ?.map((item) => item != null ? DocumentFilter.fromJson(item) : null) ?.cast<DocumentFilter>() ?.toList(); return new DocumentOnTypeFormattingRegistrationOptions( firstTriggerCharacter, moreTriggerCharacter, documentSelector); } - /// A document selector to identify the scope of the registration. If - /// set to null the document selector provided on the client side will - /// be used. + /// A document selector to identify the scope of the registration. If set to + /// null the document selector provided on the client side will be used. final List<DocumentFilter> documentSelector; /// A character on which formatting should be triggered, like `}`. @@ -2498,6 +3630,30 @@ obj['documentSelector'] .every((item) => DocumentFilter.canParse(item)))); } + + @override + bool operator ==(other) { + if (other is DocumentOnTypeFormattingRegistrationOptions) { + return firstTriggerCharacter == other.firstTriggerCharacter && + listEqual(moreTriggerCharacter, other.moreTriggerCharacter, + (String a, String b) => a == b) && + documentSelector == other.documentSelector && + true; + } + return false; + } + + @override + int get hashCode { + int hash = 0; + hash = JenkinsSmiHash.combine(hash, firstTriggerCharacter.hashCode); + hash = JenkinsSmiHash.combine(hash, moreTriggerCharacter.hashCode); + hash = JenkinsSmiHash.combine(hash, documentSelector.hashCode); + return JenkinsSmiHash.finish(hash); + } + + @override + String toString() => jsonEncoder.convert(toJson()); } class DocumentRangeFormattingParams implements ToJsonable { @@ -2512,14 +3668,13 @@ throw 'options is required but was not provided'; } } - factory DocumentRangeFormattingParams.fromJson(Map<String, dynamic> json) { + static DocumentRangeFormattingParams fromJson(Map<String, dynamic> json) { final textDocument = json['textDocument'] != null - ? new TextDocumentIdentifier.fromJson(json['textDocument']) + ? TextDocumentIdentifier.fromJson(json['textDocument']) : null; - final range = - json['range'] != null ? new Range.fromJson(json['range']) : null; + final range = json['range'] != null ? Range.fromJson(json['range']) : null; final options = json['options'] != null - ? new FormattingOptions.fromJson(json['options']) + ? FormattingOptions.fromJson(json['options']) : null; return new DocumentRangeFormattingParams(textDocument, range, options); } @@ -2552,13 +3707,35 @@ obj.containsKey('options') && FormattingOptions.canParse(obj['options']); } + + @override + bool operator ==(other) { + if (other is DocumentRangeFormattingParams) { + return textDocument == other.textDocument && + range == other.range && + options == other.options && + true; + } + return false; + } + + @override + int get hashCode { + int hash = 0; + hash = JenkinsSmiHash.combine(hash, textDocument.hashCode); + hash = JenkinsSmiHash.combine(hash, range.hashCode); + hash = JenkinsSmiHash.combine(hash, options.hashCode); + return JenkinsSmiHash.finish(hash); + } + + @override + String toString() => jsonEncoder.convert(toJson()); } -/// Represents programming constructs like variables, classes, -/// interfaces etc. that appear in a document. Document symbols can be -/// hierarchical and they have two ranges: one that encloses its -/// definition and one that points to its most interesting range, e.g. -/// the range of an identifier. +/// Represents programming constructs like variables, classes, interfaces etc. +/// that appear in a document. Document symbols can be hierarchical and they +/// have two ranges: one that encloses its definition and one that points to its +/// most interesting range, e.g. the range of an identifier. class DocumentSymbol implements ToJsonable { DocumentSymbol(this.name, this.detail, this.kind, this.deprecated, this.range, this.selectionRange, this.children) { @@ -2575,19 +3752,18 @@ throw 'selectionRange is required but was not provided'; } } - factory DocumentSymbol.fromJson(Map<String, dynamic> json) { + static DocumentSymbol fromJson(Map<String, dynamic> json) { final name = json['name']; final detail = json['detail']; final kind = - json['kind'] != null ? new SymbolKind.fromJson(json['kind']) : null; + json['kind'] != null ? SymbolKind.fromJson(json['kind']) : null; final deprecated = json['deprecated']; - final range = - json['range'] != null ? new Range.fromJson(json['range']) : null; + final range = json['range'] != null ? Range.fromJson(json['range']) : null; final selectionRange = json['selectionRange'] != null - ? new Range.fromJson(json['selectionRange']) + ? Range.fromJson(json['selectionRange']) : null; final children = json['children'] - ?.map((item) => item != null ? new DocumentSymbol.fromJson(item) : null) + ?.map((item) => item != null ? DocumentSymbol.fromJson(item) : null) ?.cast<DocumentSymbol>() ?.toList(); return new DocumentSymbol( @@ -2609,15 +3785,14 @@ /// The name of this symbol. final String name; - /// The range enclosing this symbol not including leading/trailing - /// whitespace but everything else like comments. This information is - /// typically used to determine if the clients cursor is inside the - /// symbol to reveal in the symbol in the UI. + /// The range enclosing this symbol not including leading/trailing whitespace + /// but everything else like comments. This information is typically used to + /// determine if the clients cursor is inside the symbol to reveal in the + /// symbol in the UI. final Range range; - /// The range that should be selected and revealed when this symbol is - /// being picked, e.g the name of a function. Must be contained by the - /// `range`. + /// The range that should be selected and revealed when this symbol is being + /// picked, e.g the name of a function. Must be contained by the `range`. final Range selectionRange; Map<String, dynamic> toJson() { @@ -2650,6 +3825,38 @@ obj.containsKey('selectionRange') && Range.canParse(obj['selectionRange']); } + + @override + bool operator ==(other) { + if (other is DocumentSymbol) { + return name == other.name && + detail == other.detail && + kind == other.kind && + deprecated == other.deprecated && + range == other.range && + selectionRange == other.selectionRange && + listEqual(children, other.children, + (DocumentSymbol a, DocumentSymbol b) => a == b) && + true; + } + return false; + } + + @override + int get hashCode { + int hash = 0; + hash = JenkinsSmiHash.combine(hash, name.hashCode); + hash = JenkinsSmiHash.combine(hash, detail.hashCode); + hash = JenkinsSmiHash.combine(hash, kind.hashCode); + hash = JenkinsSmiHash.combine(hash, deprecated.hashCode); + hash = JenkinsSmiHash.combine(hash, range.hashCode); + hash = JenkinsSmiHash.combine(hash, selectionRange.hashCode); + hash = JenkinsSmiHash.combine(hash, children.hashCode); + return JenkinsSmiHash.finish(hash); + } + + @override + String toString() => jsonEncoder.convert(toJson()); } class DocumentSymbolParams implements ToJsonable { @@ -2658,9 +3865,9 @@ throw 'textDocument is required but was not provided'; } } - factory DocumentSymbolParams.fromJson(Map<String, dynamic> json) { + static DocumentSymbolParams fromJson(Map<String, dynamic> json) { final textDocument = json['textDocument'] != null - ? new TextDocumentIdentifier.fromJson(json['textDocument']) + ? TextDocumentIdentifier.fromJson(json['textDocument']) : null; return new DocumentSymbolParams(textDocument); } @@ -2680,19 +3887,59 @@ obj.containsKey('textDocument') && TextDocumentIdentifier.canParse(obj['textDocument']); } + + @override + bool operator ==(other) { + if (other is DocumentSymbolParams) { + return textDocument == other.textDocument && true; + } + return false; + } + + @override + int get hashCode { + int hash = 0; + hash = JenkinsSmiHash.combine(hash, textDocument.hashCode); + return JenkinsSmiHash.finish(hash); + } + + @override + String toString() => jsonEncoder.convert(toJson()); } -abstract class ErrorCodes { - static const InternalError = -32603; - static const InvalidParams = -32602; - static const InvalidRequest = -32600; - static const MethodNotFound = -32601; - static const ParseError = -32700; - static const RequestCancelled = -32800; - static const ServerNotInitialized = -32002; - static const UnknownErrorCode = -32001; - static const serverErrorEnd = -32000; - static const serverErrorStart = -32099; +class ErrorCodes { + const ErrorCodes(this._value); + const ErrorCodes.fromJson(this._value); + + final num _value; + + static bool canParse(Object obj) { + return obj is num; + } + + /// Defined by JSON RPC + static const ParseError = const ErrorCodes(-32700); + static const InvalidRequest = const ErrorCodes(-32600); + static const MethodNotFound = const ErrorCodes(-32601); + static const InvalidParams = const ErrorCodes(-32602); + static const InternalError = const ErrorCodes(-32603); + static const serverErrorStart = const ErrorCodes(-32099); + static const serverErrorEnd = const ErrorCodes(-32000); + static const ServerNotInitialized = const ErrorCodes(-32002); + static const UnknownErrorCode = const ErrorCodes(-32001); + + /// Defined by the protocol. + static const RequestCancelled = const ErrorCodes(-32800); + + Object toJson() => _value; + + @override + String toString() => _value.toString(); + + @override + get hashCode => _value.hashCode; + + bool operator ==(o) => o is ErrorCodes && o._value == _value; } /// Execute command options. @@ -2702,7 +3949,7 @@ throw 'commands is required but was not provided'; } } - factory ExecuteCommandOptions.fromJson(Map<String, dynamic> json) { + static ExecuteCommandOptions fromJson(Map<String, dynamic> json) { final commands = json['commands']?.map((item) => item)?.cast<String>()?.toList(); return new ExecuteCommandOptions(commands); @@ -2725,6 +3972,26 @@ (obj['commands'].length == 0 || obj['commands'].every((item) => item is String))); } + + @override + bool operator ==(other) { + if (other is ExecuteCommandOptions) { + return listEqual( + commands, other.commands, (String a, String b) => a == b) && + true; + } + return false; + } + + @override + int get hashCode { + int hash = 0; + hash = JenkinsSmiHash.combine(hash, commands.hashCode); + return JenkinsSmiHash.finish(hash); + } + + @override + String toString() => jsonEncoder.convert(toJson()); } class ExecuteCommandParams implements ToJsonable { @@ -2733,7 +4000,7 @@ throw 'command is required but was not provided'; } } - factory ExecuteCommandParams.fromJson(Map<String, dynamic> json) { + static ExecuteCommandParams fromJson(Map<String, dynamic> json) { final command = json['command']; final arguments = json['arguments']?.map((item) => item)?.cast<dynamic>()?.toList(); @@ -2761,6 +4028,28 @@ obj.containsKey('command') && obj['command'] is String; } + + @override + bool operator ==(other) { + if (other is ExecuteCommandParams) { + return command == other.command && + listEqual( + arguments, other.arguments, (dynamic a, dynamic b) => a == b) && + true; + } + return false; + } + + @override + int get hashCode { + int hash = 0; + hash = JenkinsSmiHash.combine(hash, command.hashCode); + hash = JenkinsSmiHash.combine(hash, arguments.hashCode); + return JenkinsSmiHash.finish(hash); + } + + @override + String toString() => jsonEncoder.convert(toJson()); } /// Execute command registration options. @@ -2770,8 +4059,7 @@ throw 'commands is required but was not provided'; } } - factory ExecuteCommandRegistrationOptions.fromJson( - Map<String, dynamic> json) { + static ExecuteCommandRegistrationOptions fromJson(Map<String, dynamic> json) { final commands = json['commands']?.map((item) => item)?.cast<String>()?.toList(); return new ExecuteCommandRegistrationOptions(commands); @@ -2794,13 +4082,33 @@ (obj['commands'].length == 0 || obj['commands'].every((item) => item is String))); } + + @override + bool operator ==(other) { + if (other is ExecuteCommandRegistrationOptions) { + return listEqual( + commands, other.commands, (String a, String b) => a == b) && + true; + } + return false; + } + + @override + int get hashCode { + int hash = 0; + hash = JenkinsSmiHash.combine(hash, commands.hashCode); + return JenkinsSmiHash.finish(hash); + } + + @override + String toString() => jsonEncoder.convert(toJson()); } class FailureHandlingKind { const FailureHandlingKind._(this._value); const FailureHandlingKind.fromJson(this._value); - final Object _value; + final String _value; static bool canParse(Object obj) { switch (obj) { @@ -2813,25 +4121,23 @@ return false; } - /// Applying the workspace change is simply aborted if one of the - /// changes provided fails. All operations executed before the - /// failing operation stay executed. + /// Applying the workspace change is simply aborted if one of the changes + /// provided fails. All operations executed before the failing operation stay + /// executed. static const Abort = const FailureHandlingKind._('abort'); - /// All operations are executed transactional. That means they - /// either all succeed or no changes at all are applied to the - /// workspace. + /// All operations are executed transactional. That means they either all + /// succeed or no changes at all are applied to the workspace. static const Transactional = const FailureHandlingKind._('transactional'); - /// If the workspace edit contains only textual file changes they - /// are executed transactional. If resource changes (create, rename - /// or delete file) are part of the change the failure handling - /// startegy is abort. + /// If the workspace edit contains only textual file changes they are executed + /// transactional. If resource changes (create, rename or delete file) are + /// part of the change the failure handling strategy is abort. static const TextOnlyTransactional = const FailureHandlingKind._('textOnlyTransactional'); - /// The client tries to undo the operations already executed. But - /// there is no guaruntee that this is succeeding. + /// The client tries to undo the operations already executed. But there is no + /// guarantee that this is succeeding. static const Undo = const FailureHandlingKind._('undo'); Object toJson() => _value; @@ -2850,7 +4156,7 @@ const FileChangeType._(this._value); const FileChangeType.fromJson(this._value); - final Object _value; + final num _value; static bool canParse(Object obj) { switch (obj) { @@ -2892,7 +4198,7 @@ throw 'type is required but was not provided'; } } - factory FileEvent.fromJson(Map<String, dynamic> json) { + static FileEvent fromJson(Map<String, dynamic> json) { final uri = json['uri']; final type = json['type']; return new FileEvent(uri, type); @@ -2918,6 +4224,25 @@ obj.containsKey('type') && obj['type'] is num; } + + @override + bool operator ==(other) { + if (other is FileEvent) { + return uri == other.uri && type == other.type && true; + } + return false; + } + + @override + int get hashCode { + int hash = 0; + hash = JenkinsSmiHash.combine(hash, uri.hashCode); + hash = JenkinsSmiHash.combine(hash, type.hashCode); + return JenkinsSmiHash.finish(hash); + } + + @override + String toString() => jsonEncoder.convert(toJson()); } class FileSystemWatcher implements ToJsonable { @@ -2926,19 +4251,17 @@ throw 'globPattern is required but was not provided'; } } - factory FileSystemWatcher.fromJson(Map<String, dynamic> json) { + static FileSystemWatcher fromJson(Map<String, dynamic> json) { final globPattern = json['globPattern']; - final kind = - json['kind'] != null ? new WatchKind.fromJson(json['kind']) : null; + final kind = json['kind'] != null ? WatchKind.fromJson(json['kind']) : null; return new FileSystemWatcher(globPattern, kind); } /// The glob pattern to watch final String globPattern; - /// The kind of events of interest. If omitted it defaults to - /// WatchKind.Create | WatchKind.Change | WatchKind.Delete which - /// is 7. + /// The kind of events of interest. If omitted it defaults to WatchKind.Create + /// | WatchKind.Change | WatchKind.Delete which is 7. final WatchKind kind; Map<String, dynamic> toJson() { @@ -2956,6 +4279,25 @@ obj.containsKey('globPattern') && obj['globPattern'] is String; } + + @override + bool operator ==(other) { + if (other is FileSystemWatcher) { + return globPattern == other.globPattern && kind == other.kind && true; + } + return false; + } + + @override + int get hashCode { + int hash = 0; + hash = JenkinsSmiHash.combine(hash, globPattern.hashCode); + hash = JenkinsSmiHash.combine(hash, kind.hashCode); + return JenkinsSmiHash.finish(hash); + } + + @override + String toString() => jsonEncoder.convert(toJson()); } /// Represents a folding range. @@ -2969,34 +4311,32 @@ throw 'endLine is required but was not provided'; } } - factory FoldingRange.fromJson(Map<String, dynamic> json) { + static FoldingRange fromJson(Map<String, dynamic> json) { final startLine = json['startLine']; final startCharacter = json['startCharacter']; final endLine = json['endLine']; final endCharacter = json['endCharacter']; - final kind = json['kind'] != null - ? new FoldingRangeKind.fromJson(json['kind']) - : null; + final kind = + json['kind'] != null ? FoldingRangeKind.fromJson(json['kind']) : null; return new FoldingRange( startLine, startCharacter, endLine, endCharacter, kind); } - /// The zero-based character offset before the folded range ends. - /// If not defined, defaults to the length of the end line. + /// The zero-based character offset before the folded range ends. If not + /// defined, defaults to the length of the end line. final num endCharacter; /// The zero-based line number where the folded range ends. final num endLine; - /// Describes the kind of the folding range such as `comment' or - /// 'region'. The kind is used to categorize folding ranges and - /// used by commands like 'Fold all comments'. See - /// [FoldingRangeKind] for an enumeration of standardized kinds. + /// Describes the kind of the folding range such as `comment' or 'region'. The + /// kind is used to categorize folding ranges and used by commands like 'Fold + /// all comments'. See [FoldingRangeKind] for an enumeration of standardized + /// kinds. final FoldingRangeKind kind; - /// The zero-based character offset from where the folded range - /// starts. If not defined, defaults to the length of the start - /// line. + /// The zero-based character offset from where the folded range starts. If not + /// defined, defaults to the length of the start line. final num startCharacter; /// The zero-based line number from where the folded range starts. @@ -3027,6 +4367,33 @@ obj.containsKey('endLine') && obj['endLine'] is num; } + + @override + bool operator ==(other) { + if (other is FoldingRange) { + return startLine == other.startLine && + startCharacter == other.startCharacter && + endLine == other.endLine && + endCharacter == other.endCharacter && + kind == other.kind && + true; + } + return false; + } + + @override + int get hashCode { + int hash = 0; + hash = JenkinsSmiHash.combine(hash, startLine.hashCode); + hash = JenkinsSmiHash.combine(hash, startCharacter.hashCode); + hash = JenkinsSmiHash.combine(hash, endLine.hashCode); + hash = JenkinsSmiHash.combine(hash, endCharacter.hashCode); + hash = JenkinsSmiHash.combine(hash, kind.hashCode); + return JenkinsSmiHash.finish(hash); + } + + @override + String toString() => jsonEncoder.convert(toJson()); } /// Enum of known range kinds @@ -3034,26 +4401,26 @@ const FoldingRangeKind._(this._value); const FoldingRangeKind.fromJson(this._value); - final Object _value; + final String _value; static bool canParse(Object obj) { switch (obj) { - case 'comment': - case 'imports': - case 'region': + case r'comment': + case r'imports': + case r'region': return true; } return false; } /// Folding range for a comment - static const Comment = const FoldingRangeKind._('comment'); + static const Comment = const FoldingRangeKind._(r'comment'); /// Folding range for a imports or includes - static const Imports = const FoldingRangeKind._('imports'); + static const Imports = const FoldingRangeKind._(r'imports'); /// Folding range for a region (e.g. `#region`) - static const Region = const FoldingRangeKind._('region'); + static const Region = const FoldingRangeKind._(r'region'); Object toJson() => _value; @@ -3072,9 +4439,9 @@ throw 'textDocument is required but was not provided'; } } - factory FoldingRangeParams.fromJson(Map<String, dynamic> json) { + static FoldingRangeParams fromJson(Map<String, dynamic> json) { final textDocument = json['textDocument'] != null - ? new TextDocumentIdentifier.fromJson(json['textDocument']) + ? TextDocumentIdentifier.fromJson(json['textDocument']) : null; return new FoldingRangeParams(textDocument); } @@ -3094,10 +4461,32 @@ obj.containsKey('textDocument') && TextDocumentIdentifier.canParse(obj['textDocument']); } + + @override + bool operator ==(other) { + if (other is FoldingRangeParams) { + return textDocument == other.textDocument && true; + } + return false; + } + + @override + int get hashCode { + int hash = 0; + hash = JenkinsSmiHash.combine(hash, textDocument.hashCode); + return JenkinsSmiHash.finish(hash); + } + + @override + String toString() => jsonEncoder.convert(toJson()); } /// Folding range provider options. class FoldingRangeProviderOptions implements ToJsonable { + static FoldingRangeProviderOptions fromJson(Map<String, dynamic> json) { + return new FoldingRangeProviderOptions(); + } + Map<String, dynamic> toJson() { Map<String, dynamic> __result = {}; return __result; @@ -3106,6 +4495,23 @@ static bool canParse(Object obj) { return obj is Map<String, dynamic>; } + + @override + bool operator ==(other) { + if (other is FoldingRangeProviderOptions) { + return true; + } + return false; + } + + @override + int get hashCode { + int hash = 0; + return JenkinsSmiHash.finish(hash); + } + + @override + String toString() => jsonEncoder.convert(toJson()); } /// Value-object describing what options formatting should use. @@ -3118,7 +4524,7 @@ throw 'insertSpaces is required but was not provided'; } } - factory FormattingOptions.fromJson(Map<String, dynamic> json) { + static FormattingOptions fromJson(Map<String, dynamic> json) { final tabSize = json['tabSize']; final insertSpaces = json['insertSpaces']; return new FormattingOptions(tabSize, insertSpaces); @@ -3146,6 +4552,27 @@ obj.containsKey('insertSpaces') && obj['insertSpaces'] is bool; } + + @override + bool operator ==(other) { + if (other is FormattingOptions) { + return tabSize == other.tabSize && + insertSpaces == other.insertSpaces && + true; + } + return false; + } + + @override + int get hashCode { + int hash = 0; + hash = JenkinsSmiHash.combine(hash, tabSize.hashCode); + hash = JenkinsSmiHash.combine(hash, insertSpaces.hashCode); + return JenkinsSmiHash.finish(hash); + } + + @override + String toString() => jsonEncoder.convert(toJson()); } /// The result of a hover request. @@ -3155,38 +4582,23 @@ throw 'contents is required but was not provided'; } } - factory Hover.fromJson(Map<String, dynamic> json) { - final contents = MarkedString.canParse(json['contents']) - ? new Either3<MarkedString, List<MarkedString>, MarkupContent>.t1( - json['contents'] != null - ? new MarkedString.fromJson(json['contents']) + static Hover fromJson(Map<String, dynamic> json) { + final contents = json['contents'] is String + ? new Either2<String, MarkupContent>.t1(json['contents']) + : (MarkupContent.canParse(json['contents']) + ? new Either2<String, MarkupContent>.t2(json['contents'] != null + ? MarkupContent.fromJson(json['contents']) : null) - : ((json['contents'] is List && - (json['contents'].length == 0 || - json['contents'] - .every((item) => MarkedString.canParse(item)))) - ? new Either3<MarkedString, List<MarkedString>, MarkupContent>.t2(json['contents'] - ?.map((item) => - item != null ? new MarkedString.fromJson(item) : null) - ?.cast<MarkedString>() - ?.toList()) - : (MarkupContent.canParse(json['contents']) - ? new Either3<MarkedString, List<MarkedString>, MarkupContent>.t3( - json['contents'] != null - ? new MarkupContent.fromJson(json['contents']) - : null) - : (throw '''${json['contents']} was not one of (MarkedString, MarkedString[], MarkupContent)'''))); - final range = - json['range'] != null ? new Range.fromJson(json['range']) : null; + : (throw '''${json['contents']} was not one of (String, MarkupContent)''')); + final range = json['range'] != null ? Range.fromJson(json['range']) : null; return new Hover(contents, range); } /// The hover's content - final Either3<MarkedString, List<MarkedString>, MarkupContent> contents; + final Either2<String, MarkupContent> contents; - /// An optional range is a range inside a text document that is - /// used to visualize a hover, e.g. by changing the background - /// color. + /// An optional range is a range inside a text document that is used to + /// visualize a hover, e.g. by changing the background color. final Range range; Map<String, dynamic> toJson() { @@ -3202,37 +4614,57 @@ static bool canParse(Object obj) { return obj is Map<String, dynamic> && obj.containsKey('contents') && - (MarkedString.canParse(obj['contents']) || - (obj['contents'] is List && - (obj['contents'].length == 0 || - obj['contents'] - .every((item) => MarkedString.canParse(item)))) || - MarkupContent.canParse(obj['contents'])); + (obj['contents'] is String || MarkupContent.canParse(obj['contents'])); } + + @override + bool operator ==(other) { + if (other is Hover) { + return contents == other.contents && range == other.range && true; + } + return false; + } + + @override + int get hashCode { + int hash = 0; + hash = JenkinsSmiHash.combine(hash, contents.hashCode); + hash = JenkinsSmiHash.combine(hash, range.hashCode); + return JenkinsSmiHash.finish(hash); + } + + @override + String toString() => jsonEncoder.convert(toJson()); } class InitializeParams implements ToJsonable { - InitializeParams(this.processId, this.rootPath, this.rootUri, - this.initializationOptions, this.capabilities, this.workspaceFolders) { + InitializeParams( + this.processId, + this.rootPath, + this.rootUri, + this.initializationOptions, + this.capabilities, + this.trace, + this.workspaceFolders) { if (capabilities == null) { throw 'capabilities is required but was not provided'; } } - factory InitializeParams.fromJson(Map<String, dynamic> json) { + static InitializeParams fromJson(Map<String, dynamic> json) { final processId = json['processId']; final rootPath = json['rootPath']; final rootUri = json['rootUri']; final initializationOptions = json['initializationOptions']; final capabilities = json['capabilities'] != null - ? new ClientCapabilities.fromJson(json['capabilities']) + ? ClientCapabilities.fromJson(json['capabilities']) : null; + final trace = json['trace']; final workspaceFolders = json['workspaceFolders'] - ?.map( - (item) => item != null ? new WorkspaceFolder.fromJson(item) : null) + ?.map((item) => item != null ? WorkspaceFolder.fromJson(item) : null) ?.cast<WorkspaceFolder>() ?.toList(); return new InitializeParams(processId, rootPath, rootUri, - initializationOptions, capabilities, workspaceFolders); + initializationOptions, capabilities, trace, workspaceFolders); } /// The capabilities provided by the client (editor or tool) @@ -3241,10 +4673,10 @@ /// User provided initialization options. final dynamic initializationOptions; - /// The process Id of the parent process that started the - /// server. Is null if the process has not been started by - /// another process. If the parent process is not alive then the - /// server should exit (see exit notification) its process. + /// The process Id of the parent process that started the server. Is null if + /// the process has not been started by another process. If the parent process + /// is not alive then the server should exit (see exit notification) its + /// process. final num processId; /// The rootPath of the workspace. Is null if no folder is open. @@ -3252,14 +4684,17 @@ @core.deprecated final String rootPath; - /// The rootUri of the workspace. Is null if no folder is open. - /// If both `rootPath` and `rootUri` are set `rootUri` wins. + /// The rootUri of the workspace. Is null if no folder is open. If both + /// `rootPath` and `rootUri` are set `rootUri` wins. final String rootUri; - /// The workspace folders configured in the client when the - /// server starts. This property is only available if the client - /// supports workspace folders. It can be `null` if the client - /// supports workspace folders but none are configured. + /// The initial trace setting. If omitted trace is disabled ('off'). + final String trace; + + /// The workspace folders configured in the client when the server starts. + /// This property is only available if the client supports workspace folders. + /// It can be `null` if the client supports workspace folders but none are + /// configured. /// /// Since 3.6.0 final List<WorkspaceFolder> workspaceFolders; @@ -3267,9 +4702,7 @@ Map<String, dynamic> toJson() { Map<String, dynamic> __result = {}; __result['processId'] = processId; - // ignore: deprecated_member_use if (rootPath != null) { - // ignore: deprecated_member_use __result['rootPath'] = rootPath; } __result['rootUri'] = rootUri; @@ -3278,6 +4711,9 @@ } __result['capabilities'] = capabilities ?? (throw 'capabilities is required but was not set'); + if (trace != null) { + __result['trace'] = trace; + } if (workspaceFolders != null) { __result['workspaceFolders'] = workspaceFolders; } @@ -3293,6 +4729,38 @@ obj.containsKey('capabilities') && ClientCapabilities.canParse(obj['capabilities']); } + + @override + bool operator ==(other) { + if (other is InitializeParams) { + return processId == other.processId && + rootPath == other.rootPath && + rootUri == other.rootUri && + initializationOptions == other.initializationOptions && + capabilities == other.capabilities && + trace == other.trace && + listEqual(workspaceFolders, other.workspaceFolders, + (WorkspaceFolder a, WorkspaceFolder b) => a == b) && + true; + } + return false; + } + + @override + int get hashCode { + int hash = 0; + hash = JenkinsSmiHash.combine(hash, processId.hashCode); + hash = JenkinsSmiHash.combine(hash, rootPath.hashCode); + hash = JenkinsSmiHash.combine(hash, rootUri.hashCode); + hash = JenkinsSmiHash.combine(hash, initializationOptions.hashCode); + hash = JenkinsSmiHash.combine(hash, capabilities.hashCode); + hash = JenkinsSmiHash.combine(hash, trace.hashCode); + hash = JenkinsSmiHash.combine(hash, workspaceFolders.hashCode); + return JenkinsSmiHash.finish(hash); + } + + @override + String toString() => jsonEncoder.convert(toJson()); } class InitializeResult implements ToJsonable { @@ -3301,9 +4769,9 @@ throw 'capabilities is required but was not provided'; } } - factory InitializeResult.fromJson(Map<String, dynamic> json) { + static InitializeResult fromJson(Map<String, dynamic> json) { final capabilities = json['capabilities'] != null - ? new ServerCapabilities.fromJson(json['capabilities']) + ? ServerCapabilities.fromJson(json['capabilities']) : null; return new InitializeResult(capabilities); } @@ -3323,9 +4791,31 @@ obj.containsKey('capabilities') && ServerCapabilities.canParse(obj['capabilities']); } + + @override + bool operator ==(other) { + if (other is InitializeResult) { + return capabilities == other.capabilities && true; + } + return false; + } + + @override + int get hashCode { + int hash = 0; + hash = JenkinsSmiHash.combine(hash, capabilities.hashCode); + return JenkinsSmiHash.finish(hash); + } + + @override + String toString() => jsonEncoder.convert(toJson()); } class InitializedParams implements ToJsonable { + static InitializedParams fromJson(Map<String, dynamic> json) { + return new InitializedParams(); + } + Map<String, dynamic> toJson() { Map<String, dynamic> __result = {}; return __result; @@ -3334,15 +4824,32 @@ static bool canParse(Object obj) { return obj is Map<String, dynamic>; } + + @override + bool operator ==(other) { + if (other is InitializedParams) { + return true; + } + return false; + } + + @override + int get hashCode { + int hash = 0; + return JenkinsSmiHash.finish(hash); + } + + @override + String toString() => jsonEncoder.convert(toJson()); } -/// Defines whether the insert text in a completion item should be -/// interpreted as plain text or a snippet. +/// Defines whether the insert text in a completion item should be interpreted +/// as plain text or a snippet. class InsertTextFormat { const InsertTextFormat._(this._value); const InsertTextFormat.fromJson(this._value); - final Object _value; + final num _value; static bool canParse(Object obj) { switch (obj) { @@ -3353,17 +4860,15 @@ return false; } - /// The primary text to be inserted is treated as a plain - /// string. + /// The primary text to be inserted is treated as a plain string. static const PlainText = const InsertTextFormat._(1); /// The primary text to be inserted is treated as a snippet. /// - /// A snippet can define tab stops and placeholders with `$1`, - /// `$2` and `${3:foo}`. `$0` defines the final tab stop, it - /// defaults to the end of the snippet. Placeholders with - /// equal identifiers are linked, that is typing in one will - /// update others too. + /// A snippet can define tab stops and placeholders with `$1`, `$2` and + /// `${3:foo}`. `$0` defines the final tab stop, it defaults to the end of the + /// snippet. Placeholders with equal identifiers are linked, that is typing in + /// one will update others too. static const Snippet = const InsertTextFormat._(2); Object toJson() => _value; @@ -3386,10 +4891,9 @@ throw 'range is required but was not provided'; } } - factory Location.fromJson(Map<String, dynamic> json) { + static Location fromJson(Map<String, dynamic> json) { final uri = json['uri']; - final range = - json['range'] != null ? new Range.fromJson(json['range']) : null; + final range = json['range'] != null ? Range.fromJson(json['range']) : null; return new Location(uri, range); } @@ -3410,6 +4914,25 @@ obj.containsKey('range') && Range.canParse(obj['range']); } + + @override + bool operator ==(other) { + if (other is Location) { + return uri == other.uri && range == other.range && true; + } + return false; + } + + @override + int get hashCode { + int hash = 0; + hash = JenkinsSmiHash.combine(hash, uri.hashCode); + hash = JenkinsSmiHash.combine(hash, range.hashCode); + return JenkinsSmiHash.finish(hash); + } + + @override + String toString() => jsonEncoder.convert(toJson()); } class LogMessageParams implements ToJsonable { @@ -3421,9 +4944,9 @@ throw 'message is required but was not provided'; } } - factory LogMessageParams.fromJson(Map<String, dynamic> json) { + static LogMessageParams fromJson(Map<String, dynamic> json) { final type = - json['type'] != null ? new MessageType.fromJson(json['type']) : null; + json['type'] != null ? MessageType.fromJson(json['type']) : null; final message = json['message']; return new LogMessageParams(type, message); } @@ -3449,55 +4972,37 @@ obj.containsKey('message') && obj['message'] is String; } + + @override + bool operator ==(other) { + if (other is LogMessageParams) { + return type == other.type && message == other.message && true; + } + return false; + } + + @override + int get hashCode { + int hash = 0; + hash = JenkinsSmiHash.combine(hash, type.hashCode); + hash = JenkinsSmiHash.combine(hash, message.hashCode); + return JenkinsSmiHash.finish(hash); + } + + @override + String toString() => jsonEncoder.convert(toJson()); } -class MarkedString implements ToJsonable { - MarkedString(this.language, this.value) { - if (language == null) { - throw 'language is required but was not provided'; - } - if (value == null) { - throw 'value is required but was not provided'; - } - } - factory MarkedString.fromJson(Map<String, dynamic> json) { - final language = json['language']; - final value = json['value']; - return new MarkedString(language, value); - } - - final String language; - final String value; - - Map<String, dynamic> toJson() { - Map<String, dynamic> __result = {}; - __result['language'] = - language ?? (throw 'language is required but was not set'); - __result['value'] = value ?? (throw 'value is required but was not set'); - return __result; - } - - static bool canParse(Object obj) { - return obj is Map<String, dynamic> && - obj.containsKey('language') && - obj['language'] is String && - obj.containsKey('value') && - obj['value'] is String; - } -} - -/// A `MarkupContent` literal represents a string value which -/// content is interpreted base on its kind flag. Currently the -/// protocol supports `plaintext` and `markdown` as markup -/// kinds. +/// A `MarkupContent` literal represents a string value which content is +/// interpreted base on its kind flag. Currently the protocol supports +/// `plaintext` and `markdown` as markup kinds. /// -/// If the kind is `markdown` then the value can contain fenced -/// code blocks like in GitHub issues. See +/// If the kind is `markdown` then the value can contain fenced code blocks like +/// in GitHub issues. See /// https://help.github.com/articles/creating-and-highlighting-code-blocks/#syntax-highlighting /// -/// Here is an example how such a string can be constructed -/// using JavaScript / TypeScript: ```ts let markdown: -/// MarkdownContent = { +/// Here is an example how such a string can be constructed using JavaScript / +/// TypeScript: ```ts let markdown: MarkdownContent = { /// /// kind: MarkupKind.Markdown, /// value: [ @@ -3508,9 +5013,8 @@ /// '```' /// ].join('\n') }; ``` /// -/// *Please Note* that clients might sanitize the return -/// markdown. A client could decide to remove HTML from the -/// markdown to avoid script execution. +/// *Please Note* that clients might sanitize the return markdown. A client +/// could decide to remove HTML from the markdown to avoid script execution. class MarkupContent implements ToJsonable { MarkupContent(this.kind, this.value) { if (kind == null) { @@ -3520,9 +5024,9 @@ throw 'value is required but was not provided'; } } - factory MarkupContent.fromJson(Map<String, dynamic> json) { + static MarkupContent fromJson(Map<String, dynamic> json) { final kind = - json['kind'] != null ? new MarkupKind.fromJson(json['kind']) : null; + json['kind'] != null ? MarkupKind.fromJson(json['kind']) : null; final value = json['value']; return new MarkupContent(kind, value); } @@ -3543,38 +5047,56 @@ static bool canParse(Object obj) { return obj is Map<String, dynamic> && obj.containsKey('kind') && - MarkupKind.canParse(obj['kind']) && + obj['kind'] is String && obj.containsKey('value') && obj['value'] is String; } + + @override + bool operator ==(other) { + if (other is MarkupContent) { + return kind == other.kind && value == other.value && true; + } + return false; + } + + @override + int get hashCode { + int hash = 0; + hash = JenkinsSmiHash.combine(hash, kind.hashCode); + hash = JenkinsSmiHash.combine(hash, value.hashCode); + return JenkinsSmiHash.finish(hash); + } + + @override + String toString() => jsonEncoder.convert(toJson()); } -/// Describes the content type that a client supports in various -/// result literals like `Hover`, `ParameterInfo` or -/// `CompletionItem`. +/// Describes the content type that a client supports in various result literals +/// like `Hover`, `ParameterInfo` or `CompletionItem`. /// -/// Please note that `MarkupKinds` must not start with a `$`. -/// This kinds are reserved for internal usage. +/// Please note that `MarkupKinds` must not start with a `$`. This kinds are +/// reserved for internal usage. class MarkupKind { const MarkupKind._(this._value); const MarkupKind.fromJson(this._value); - final Object _value; + final String _value; static bool canParse(Object obj) { switch (obj) { - case 'plaintext': - case 'markdown': + case r'plaintext': + case r'markdown': return true; } return false; } /// Plain text is supported as a content format - static const PlainText = const MarkupKind._('plaintext'); + static const PlainText = const MarkupKind._(r'plaintext'); /// Markdown is supported as a content format - static const Markdown = const MarkupKind._('markdown'); + static const Markdown = const MarkupKind._(r'markdown'); Object toJson() => _value; @@ -3593,7 +5115,7 @@ throw 'jsonrpc is required but was not provided'; } } - factory Message.fromJson(Map<String, dynamic> json) { + static Message fromJson(Map<String, dynamic> json) { final jsonrpc = json['jsonrpc']; return new Message(jsonrpc); } @@ -3612,6 +5134,24 @@ obj.containsKey('jsonrpc') && obj['jsonrpc'] is String; } + + @override + bool operator ==(other) { + if (other is Message) { + return jsonrpc == other.jsonrpc && true; + } + return false; + } + + @override + int get hashCode { + int hash = 0; + hash = JenkinsSmiHash.combine(hash, jsonrpc.hashCode); + return JenkinsSmiHash.finish(hash); + } + + @override + String toString() => jsonEncoder.convert(toJson()); } class MessageActionItem implements ToJsonable { @@ -3620,7 +5160,7 @@ throw 'title is required but was not provided'; } } - factory MessageActionItem.fromJson(Map<String, dynamic> json) { + static MessageActionItem fromJson(Map<String, dynamic> json) { final title = json['title']; return new MessageActionItem(title); } @@ -3639,13 +5179,31 @@ obj.containsKey('title') && obj['title'] is String; } + + @override + bool operator ==(other) { + if (other is MessageActionItem) { + return title == other.title && true; + } + return false; + } + + @override + int get hashCode { + int hash = 0; + hash = JenkinsSmiHash.combine(hash, title.hashCode); + return JenkinsSmiHash.finish(hash); + } + + @override + String toString() => jsonEncoder.convert(toJson()); } class MessageType { const MessageType._(this._value); const MessageType.fromJson(this._value); - final Object _value; + final num _value; static bool canParse(Object obj) { switch (obj) { @@ -3681,7 +5239,214 @@ bool operator ==(o) => o is MessageType && o._value == _value; } -class NotificationMessage implements Message, ToJsonable { +/// Valid LSP methods known at the time of code generation from the spec. +class Method { + const Method._(this._value); + const Method.fromJson(this._value); + + final String _value; + + static bool canParse(Object obj) { + switch (obj) { + case r'$/cancelRequest': + case r'initialize': + case r'initialized': + case r'shutdown': + case r'exit': + case r'window/showMessage': + case r'window/showMessageRequest': + case r'window/logMessage': + case r'telemetry/event': + case r'client/registerCapability': + case r'client/unregisterCapability': + case r'workspace/didChangeWatchedFiles': + case r'workspace/symbol': + case r'workspace/executeCommand': + case r'workspace/applyEdit': + case r'textDocument/didOpen': + case r'textDocument/didChange': + case r'textDocument/willSave': + case r'textDocument/willSaveWaitUntil': + case r'textDocument/didClose': + case r'textDocument/publishDiagnostics': + case r'textDocument/completion': + case r'completionItem/resolve': + case r'textDocument/hover': + case r'textDocument/signatureHelp': + case r'textDocument/definition': + case r'textDocument/typeDefinition': + case r'textDocument/implementation': + case r'textDocument/references': + case r'textDocument/documentHighlight': + case r'textDocument/documentSymbol': + case r'textDocument/codeAction': + case r'textDocument/codeLens': + case r'codeLens/resolve': + case r'textDocument/documentLink': + case r'documentLink/resolve': + case r'textDocument/formatting': + case r'textDocument/onTypeFormatting': + case r'textDocument/rename': + case r'textDocument/prepareRename': + return true; + } + return false; + } + + /// Constant for the '$/cancelRequest' method. + static const cancelRequest = const Method._(r'$/cancelRequest'); + + /// Constant for the 'initialize' method. + static const initialize = const Method._(r'initialize'); + + /// Constant for the 'initialized' method. + static const initialized = const Method._(r'initialized'); + + /// Constant for the 'shutdown' method. + static const shutdown = const Method._(r'shutdown'); + + /// Constant for the 'exit' method. + static const exit = const Method._(r'exit'); + + /// Constant for the 'window/showMessage' method. + static const window_showMessage = const Method._(r'window/showMessage'); + + /// Constant for the 'window/showMessageRequest' method. + static const window_showMessageRequest = + const Method._(r'window/showMessageRequest'); + + /// Constant for the 'window/logMessage' method. + static const window_logMessage = const Method._(r'window/logMessage'); + + /// Constant for the 'telemetry/event' method. + static const telemetry_event = const Method._(r'telemetry/event'); + + /// Constant for the 'client/registerCapability' method. + static const client_registerCapability = + const Method._(r'client/registerCapability'); + + /// Constant for the 'client/unregisterCapability' method. + static const client_unregisterCapability = + const Method._(r'client/unregisterCapability'); + + /// Constant for the 'workspace/didChangeWatchedFiles' method. + static const workspace_didChangeWatchedFiles = + const Method._(r'workspace/didChangeWatchedFiles'); + + /// Constant for the 'workspace/symbol' method. + static const workspace_symbol = const Method._(r'workspace/symbol'); + + /// Constant for the 'workspace/executeCommand' method. + static const workspace_executeCommand = + const Method._(r'workspace/executeCommand'); + + /// Constant for the 'workspace/applyEdit' method. + static const workspace_applyEdit = const Method._(r'workspace/applyEdit'); + + /// Constant for the 'textDocument/didOpen' method. + static const textDocument_didOpen = const Method._(r'textDocument/didOpen'); + + /// Constant for the 'textDocument/didChange' method. + static const textDocument_didChange = + const Method._(r'textDocument/didChange'); + + /// Constant for the 'textDocument/willSave' method. + static const textDocument_willSave = const Method._(r'textDocument/willSave'); + + /// Constant for the 'textDocument/willSaveWaitUntil' method. + static const textDocument_willSaveWaitUntil = + const Method._(r'textDocument/willSaveWaitUntil'); + + /// Constant for the 'textDocument/didClose' method. + static const textDocument_didClose = const Method._(r'textDocument/didClose'); + + /// Constant for the 'textDocument/publishDiagnostics' method. + static const textDocument_publishDiagnostics = + const Method._(r'textDocument/publishDiagnostics'); + + /// Constant for the 'textDocument/completion' method. + static const textDocument_completion = + const Method._(r'textDocument/completion'); + + /// Constant for the 'completionItem/resolve' method. + static const completionItem_resolve = + const Method._(r'completionItem/resolve'); + + /// Constant for the 'textDocument/hover' method. + static const textDocument_hover = const Method._(r'textDocument/hover'); + + /// Constant for the 'textDocument/signatureHelp' method. + static const textDocument_signatureHelp = + const Method._(r'textDocument/signatureHelp'); + + /// Constant for the 'textDocument/definition' method. + static const textDocument_definition = + const Method._(r'textDocument/definition'); + + /// Constant for the 'textDocument/typeDefinition' method. + static const textDocument_typeDefinition = + const Method._(r'textDocument/typeDefinition'); + + /// Constant for the 'textDocument/implementation' method. + static const textDocument_implementation = + const Method._(r'textDocument/implementation'); + + /// Constant for the 'textDocument/references' method. + static const textDocument_references = + const Method._(r'textDocument/references'); + + /// Constant for the 'textDocument/documentHighlight' method. + static const textDocument_documentHighlight = + const Method._(r'textDocument/documentHighlight'); + + /// Constant for the 'textDocument/documentSymbol' method. + static const textDocument_documentSymbol = + const Method._(r'textDocument/documentSymbol'); + + /// Constant for the 'textDocument/codeAction' method. + static const textDocument_codeAction = + const Method._(r'textDocument/codeAction'); + + /// Constant for the 'textDocument/codeLens' method. + static const textDocument_codeLens = const Method._(r'textDocument/codeLens'); + + /// Constant for the 'codeLens/resolve' method. + static const codeLens_resolve = const Method._(r'codeLens/resolve'); + + /// Constant for the 'textDocument/documentLink' method. + static const textDocument_documentLink = + const Method._(r'textDocument/documentLink'); + + /// Constant for the 'documentLink/resolve' method. + static const documentLink_resolve = const Method._(r'documentLink/resolve'); + + /// Constant for the 'textDocument/formatting' method. + static const textDocument_formatting = + const Method._(r'textDocument/formatting'); + + /// Constant for the 'textDocument/onTypeFormatting' method. + static const textDocument_onTypeFormatting = + const Method._(r'textDocument/onTypeFormatting'); + + /// Constant for the 'textDocument/rename' method. + static const textDocument_rename = const Method._(r'textDocument/rename'); + + /// Constant for the 'textDocument/prepareRename' method. + static const textDocument_prepareRename = + const Method._(r'textDocument/prepareRename'); + + Object toJson() => _value; + + @override + String toString() => _value.toString(); + + @override + get hashCode => _value.hashCode; + + bool operator ==(o) => o is Method && o._value == _value; +} + +class NotificationMessage implements Message, IncomingMessage, ToJsonable { NotificationMessage(this.method, this.params, this.jsonrpc) { if (method == null) { throw 'method is required but was not provided'; @@ -3690,14 +5455,10 @@ throw 'jsonrpc is required but was not provided'; } } - factory NotificationMessage.fromJson(Map<String, dynamic> json) { - final method = json['method']; - final params = (json['params'] is List && - (json['params'].length == 0 || - json['params'].every((item) => true))) - ? new Either2<List<dynamic>, dynamic>.t1( - json['params']?.map((item) => item)?.cast<dynamic>()?.toList()) - : (new Either2<List<dynamic>, dynamic>.t2(json['params'])); + static NotificationMessage fromJson(Map<String, dynamic> json) { + final method = + json['method'] != null ? Method.fromJson(json['method']) : null; + final params = json['params']; final jsonrpc = json['jsonrpc']; return new NotificationMessage(method, params, jsonrpc); } @@ -3705,10 +5466,10 @@ final String jsonrpc; /// The method to be invoked. - final String method; + final Method method; /// The notification's params. - final Either2<List<dynamic>, dynamic> params; + final dynamic params; Map<String, dynamic> toJson() { Map<String, dynamic> __result = {}; @@ -3724,35 +5485,60 @@ static bool canParse(Object obj) { return obj is Map<String, dynamic> && obj.containsKey('method') && - obj['method'] is String && + Method.canParse(obj['method']) && obj.containsKey('jsonrpc') && obj['jsonrpc'] is String; } + + @override + bool operator ==(other) { + if (other is NotificationMessage) { + return method == other.method && + params == other.params && + jsonrpc == other.jsonrpc && + true; + } + return false; + } + + @override + int get hashCode { + int hash = 0; + hash = JenkinsSmiHash.combine(hash, method.hashCode); + hash = JenkinsSmiHash.combine(hash, params.hashCode); + hash = JenkinsSmiHash.combine(hash, jsonrpc.hashCode); + return JenkinsSmiHash.finish(hash); + } + + @override + String toString() => jsonEncoder.convert(toJson()); } -/// Represents a parameter of a callable-signature. A -/// parameter can have a label and a doc-comment. +/// Represents a parameter of a callable-signature. A parameter can have a label +/// and a doc-comment. class ParameterInformation implements ToJsonable { ParameterInformation(this.label, this.documentation) { if (label == null) { throw 'label is required but was not provided'; } } - factory ParameterInformation.fromJson(Map<String, dynamic> json) { + static ParameterInformation fromJson(Map<String, dynamic> json) { final label = json['label']; final documentation = json['documentation'] is String ? new Either2<String, MarkupContent>.t1(json['documentation']) : (MarkupContent.canParse(json['documentation']) ? new Either2<String, MarkupContent>.t2( json['documentation'] != null - ? new MarkupContent.fromJson(json['documentation']) + ? MarkupContent.fromJson(json['documentation']) : null) - : (throw '''${json['documentation']} was not one of (string, MarkupContent)''')); + : (json['documentation'] == null + ? null + : (throw '''${json['documentation']} was not one of (String, MarkupContent)'''))); return new ParameterInformation(label, documentation); } - /// The human-readable doc-comment of this parameter. Will - /// be shown in the UI but can be omitted. + /// The human-readable doc-comment of this parameter. Will be shown in the UI + /// but can be omitted. final Either2<String, MarkupContent> documentation; /// The label of this parameter. Will be shown in the UI. @@ -3772,6 +5558,27 @@ obj.containsKey('label') && obj['label'] is String; } + + @override + bool operator ==(other) { + if (other is ParameterInformation) { + return label == other.label && + documentation == other.documentation && + true; + } + return false; + } + + @override + int get hashCode { + int hash = 0; + hash = JenkinsSmiHash.combine(hash, label.hashCode); + hash = JenkinsSmiHash.combine(hash, documentation.hashCode); + return JenkinsSmiHash.finish(hash); + } + + @override + String toString() => jsonEncoder.convert(toJson()); } class Position implements ToJsonable { @@ -3783,19 +5590,18 @@ throw 'character is required but was not provided'; } } - factory Position.fromJson(Map<String, dynamic> json) { + static Position fromJson(Map<String, dynamic> json) { final line = json['line']; final character = json['character']; return new Position(line, character); } - /// Character offset on a line in a document (zero-based). - /// Assuming that the line is represented as a string, the - /// `character` value represents the gap between the - /// `character` and `character + 1`. + /// Character offset on a line in a document (zero-based). Assuming that the + /// line is represented as a string, the `character` value represents the gap + /// between the `character` and `character + 1`. /// - /// If the character value is greater than the line length - /// it defaults back to the line length. + /// If the character value is greater than the line length it defaults back to + /// the line length. final num character; /// Line position in a document (zero-based). @@ -3816,6 +5622,25 @@ obj.containsKey('character') && obj['character'] is num; } + + @override + bool operator ==(other) { + if (other is Position) { + return line == other.line && character == other.character && true; + } + return false; + } + + @override + int get hashCode { + int hash = 0; + hash = JenkinsSmiHash.combine(hash, line.hashCode); + hash = JenkinsSmiHash.combine(hash, character.hashCode); + return JenkinsSmiHash.finish(hash); + } + + @override + String toString() => jsonEncoder.convert(toJson()); } class PublishDiagnosticsParams implements ToJsonable { @@ -3827,10 +5652,10 @@ throw 'diagnostics is required but was not provided'; } } - factory PublishDiagnosticsParams.fromJson(Map<String, dynamic> json) { + static PublishDiagnosticsParams fromJson(Map<String, dynamic> json) { final uri = json['uri']; final diagnostics = json['diagnostics'] - ?.map((item) => item != null ? new Diagnostic.fromJson(item) : null) + ?.map((item) => item != null ? Diagnostic.fromJson(item) : null) ?.cast<Diagnostic>() ?.toList(); return new PublishDiagnosticsParams(uri, diagnostics); @@ -3859,6 +5684,28 @@ (obj['diagnostics'].length == 0 || obj['diagnostics'].every((item) => Diagnostic.canParse(item)))); } + + @override + bool operator ==(other) { + if (other is PublishDiagnosticsParams) { + return uri == other.uri && + listEqual(diagnostics, other.diagnostics, + (Diagnostic a, Diagnostic b) => a == b) && + true; + } + return false; + } + + @override + int get hashCode { + int hash = 0; + hash = JenkinsSmiHash.combine(hash, uri.hashCode); + hash = JenkinsSmiHash.combine(hash, diagnostics.hashCode); + return JenkinsSmiHash.finish(hash); + } + + @override + String toString() => jsonEncoder.convert(toJson()); } class Range implements ToJsonable { @@ -3870,10 +5717,10 @@ throw 'end is required but was not provided'; } } - factory Range.fromJson(Map<String, dynamic> json) { + static Range fromJson(Map<String, dynamic> json) { final start = - json['start'] != null ? new Position.fromJson(json['start']) : null; - final end = json['end'] != null ? new Position.fromJson(json['end']) : null; + json['start'] != null ? Position.fromJson(json['start']) : null; + final end = json['end'] != null ? Position.fromJson(json['end']) : null; return new Range(start, end); } @@ -3897,6 +5744,25 @@ obj.containsKey('end') && Position.canParse(obj['end']); } + + @override + bool operator ==(other) { + if (other is Range) { + return start == other.start && end == other.end && true; + } + return false; + } + + @override + int get hashCode { + int hash = 0; + hash = JenkinsSmiHash.combine(hash, start.hashCode); + hash = JenkinsSmiHash.combine(hash, end.hashCode); + return JenkinsSmiHash.finish(hash); + } + + @override + String toString() => jsonEncoder.convert(toJson()); } class ReferenceContext implements ToJsonable { @@ -3905,7 +5771,7 @@ throw 'includeDeclaration is required but was not provided'; } } - factory ReferenceContext.fromJson(Map<String, dynamic> json) { + static ReferenceContext fromJson(Map<String, dynamic> json) { final includeDeclaration = json['includeDeclaration']; return new ReferenceContext(includeDeclaration); } @@ -3925,6 +5791,24 @@ obj.containsKey('includeDeclaration') && obj['includeDeclaration'] is bool; } + + @override + bool operator ==(other) { + if (other is ReferenceContext) { + return includeDeclaration == other.includeDeclaration && true; + } + return false; + } + + @override + int get hashCode { + int hash = 0; + hash = JenkinsSmiHash.combine(hash, includeDeclaration.hashCode); + return JenkinsSmiHash.finish(hash); + } + + @override + String toString() => jsonEncoder.convert(toJson()); } class ReferenceParams implements TextDocumentPositionParams, ToJsonable { @@ -3939,16 +5823,15 @@ throw 'position is required but was not provided'; } } - factory ReferenceParams.fromJson(Map<String, dynamic> json) { + static ReferenceParams fromJson(Map<String, dynamic> json) { final context = json['context'] != null - ? new ReferenceContext.fromJson(json['context']) + ? ReferenceContext.fromJson(json['context']) : null; final textDocument = json['textDocument'] != null - ? new TextDocumentIdentifier.fromJson(json['textDocument']) + ? TextDocumentIdentifier.fromJson(json['textDocument']) : null; - final position = json['position'] != null - ? new Position.fromJson(json['position']) - : null; + final position = + json['position'] != null ? Position.fromJson(json['position']) : null; return new ReferenceParams(context, textDocument, position); } @@ -3980,6 +5863,29 @@ obj.containsKey('position') && Position.canParse(obj['position']); } + + @override + bool operator ==(other) { + if (other is ReferenceParams) { + return context == other.context && + textDocument == other.textDocument && + position == other.position && + true; + } + return false; + } + + @override + int get hashCode { + int hash = 0; + hash = JenkinsSmiHash.combine(hash, context.hashCode); + hash = JenkinsSmiHash.combine(hash, textDocument.hashCode); + hash = JenkinsSmiHash.combine(hash, position.hashCode); + return JenkinsSmiHash.finish(hash); + } + + @override + String toString() => jsonEncoder.convert(toJson()); } /// General parameters to register for a capability. @@ -3992,15 +5898,15 @@ throw 'method is required but was not provided'; } } - factory Registration.fromJson(Map<String, dynamic> json) { + static Registration fromJson(Map<String, dynamic> json) { final id = json['id']; final method = json['method']; final registerOptions = json['registerOptions']; return new Registration(id, method, registerOptions); } - /// The id used to register the request. The id can be - /// used to deregister the request again. + /// The id used to register the request. The id can be used to deregister the + /// request again. final String id; /// The method / capability to register for. @@ -4026,6 +5932,29 @@ obj.containsKey('method') && obj['method'] is String; } + + @override + bool operator ==(other) { + if (other is Registration) { + return id == other.id && + method == other.method && + registerOptions == other.registerOptions && + true; + } + return false; + } + + @override + int get hashCode { + int hash = 0; + hash = JenkinsSmiHash.combine(hash, id.hashCode); + hash = JenkinsSmiHash.combine(hash, method.hashCode); + hash = JenkinsSmiHash.combine(hash, registerOptions.hashCode); + return JenkinsSmiHash.finish(hash); + } + + @override + String toString() => jsonEncoder.convert(toJson()); } class RegistrationParams implements ToJsonable { @@ -4034,9 +5963,9 @@ throw 'registrations is required but was not provided'; } } - factory RegistrationParams.fromJson(Map<String, dynamic> json) { + static RegistrationParams fromJson(Map<String, dynamic> json) { final registrations = json['registrations'] - ?.map((item) => item != null ? new Registration.fromJson(item) : null) + ?.map((item) => item != null ? Registration.fromJson(item) : null) ?.cast<Registration>() ?.toList(); return new RegistrationParams(registrations); @@ -4059,11 +5988,34 @@ obj['registrations'] .every((item) => Registration.canParse(item)))); } + + @override + bool operator ==(other) { + if (other is RegistrationParams) { + return listEqual(registrations, other.registrations, + (Registration a, Registration b) => a == b) && + true; + } + return false; + } + + @override + int get hashCode { + int hash = 0; + hash = JenkinsSmiHash.combine(hash, registrations.hashCode); + return JenkinsSmiHash.finish(hash); + } + + @override + String toString() => jsonEncoder.convert(toJson()); } /// Rename file operation -class RenameFile implements FileOperation, ToJsonable { - RenameFile(this.oldUri, this.newUri, this.options) { +class RenameFile implements ToJsonable { + RenameFile(this.kind, this.oldUri, this.newUri, this.options) { + if (kind == null) { + throw 'kind is required but was not provided'; + } if (oldUri == null) { throw 'oldUri is required but was not provided'; } @@ -4071,15 +6023,19 @@ throw 'newUri is required but was not provided'; } } - factory RenameFile.fromJson(Map<String, dynamic> json) { + static RenameFile fromJson(Map<String, dynamic> json) { + final kind = json['kind']; final oldUri = json['oldUri']; final newUri = json['newUri']; final options = json['options'] != null - ? new RenameFileOptions.fromJson(json['options']) + ? RenameFileOptions.fromJson(json['options']) : null; - return new RenameFile(oldUri, newUri, options); + return new RenameFile(kind, oldUri, newUri, options); } + /// A rename + final String kind; + /// The new location. final String newUri; @@ -4091,6 +6047,7 @@ Map<String, dynamic> toJson() { Map<String, dynamic> __result = {}; + __result['kind'] = kind ?? (throw 'kind is required but was not set'); __result['oldUri'] = oldUri ?? (throw 'oldUri is required but was not set'); __result['newUri'] = newUri ?? (throw 'newUri is required but was not set'); if (options != null) { @@ -4101,17 +6058,44 @@ static bool canParse(Object obj) { return obj is Map<String, dynamic> && + obj.containsKey('kind') && + obj['kind'] is String && obj.containsKey('oldUri') && obj['oldUri'] is String && obj.containsKey('newUri') && obj['newUri'] is String; } + + @override + bool operator ==(other) { + if (other is RenameFile) { + return kind == other.kind && + oldUri == other.oldUri && + newUri == other.newUri && + options == other.options && + true; + } + return false; + } + + @override + int get hashCode { + int hash = 0; + hash = JenkinsSmiHash.combine(hash, kind.hashCode); + hash = JenkinsSmiHash.combine(hash, oldUri.hashCode); + hash = JenkinsSmiHash.combine(hash, newUri.hashCode); + hash = JenkinsSmiHash.combine(hash, options.hashCode); + return JenkinsSmiHash.finish(hash); + } + + @override + String toString() => jsonEncoder.convert(toJson()); } /// Rename file options class RenameFileOptions implements ToJsonable { RenameFileOptions(this.overwrite, this.ignoreIfExists); - factory RenameFileOptions.fromJson(Map<String, dynamic> json) { + static RenameFileOptions fromJson(Map<String, dynamic> json) { final overwrite = json['overwrite']; final ignoreIfExists = json['ignoreIfExists']; return new RenameFileOptions(overwrite, ignoreIfExists); @@ -4120,8 +6104,7 @@ /// Ignores if target exists. final bool ignoreIfExists; - /// Overwrite target if existing. Overwrite wins over - /// `ignoreIfExists` + /// Overwrite target if existing. Overwrite wins over `ignoreIfExists` final bool overwrite; Map<String, dynamic> toJson() { @@ -4138,18 +6121,38 @@ static bool canParse(Object obj) { return obj is Map<String, dynamic>; } + + @override + bool operator ==(other) { + if (other is RenameFileOptions) { + return overwrite == other.overwrite && + ignoreIfExists == other.ignoreIfExists && + true; + } + return false; + } + + @override + int get hashCode { + int hash = 0; + hash = JenkinsSmiHash.combine(hash, overwrite.hashCode); + hash = JenkinsSmiHash.combine(hash, ignoreIfExists.hashCode); + return JenkinsSmiHash.finish(hash); + } + + @override + String toString() => jsonEncoder.convert(toJson()); } /// Rename options class RenameOptions implements ToJsonable { RenameOptions(this.prepareProvider); - factory RenameOptions.fromJson(Map<String, dynamic> json) { + static RenameOptions fromJson(Map<String, dynamic> json) { final prepareProvider = json['prepareProvider']; return new RenameOptions(prepareProvider); } - /// Renames should be checked and tested before being - /// executed. + /// Renames should be checked and tested before being executed. final bool prepareProvider; Map<String, dynamic> toJson() { @@ -4163,6 +6166,24 @@ static bool canParse(Object obj) { return obj is Map<String, dynamic>; } + + @override + bool operator ==(other) { + if (other is RenameOptions) { + return prepareProvider == other.prepareProvider && true; + } + return false; + } + + @override + int get hashCode { + int hash = 0; + hash = JenkinsSmiHash.combine(hash, prepareProvider.hashCode); + return JenkinsSmiHash.finish(hash); + } + + @override + String toString() => jsonEncoder.convert(toJson()); } class RenameParams implements ToJsonable { @@ -4177,20 +6198,18 @@ throw 'newName is required but was not provided'; } } - factory RenameParams.fromJson(Map<String, dynamic> json) { + static RenameParams fromJson(Map<String, dynamic> json) { final textDocument = json['textDocument'] != null - ? new TextDocumentIdentifier.fromJson(json['textDocument']) + ? TextDocumentIdentifier.fromJson(json['textDocument']) : null; - final position = json['position'] != null - ? new Position.fromJson(json['position']) - : null; + final position = + json['position'] != null ? Position.fromJson(json['position']) : null; final newName = json['newName']; return new RenameParams(textDocument, position, newName); } - /// The new name of the symbol. If the given name is not - /// valid the request must return a [ResponseError] with - /// an appropriate message set. + /// The new name of the symbol. If the given name is not valid the request + /// must return a [ResponseError] with an appropriate message set. final String newName; /// The position at which this request was sent. @@ -4219,27 +6238,48 @@ obj.containsKey('newName') && obj['newName'] is String; } + + @override + bool operator ==(other) { + if (other is RenameParams) { + return textDocument == other.textDocument && + position == other.position && + newName == other.newName && + true; + } + return false; + } + + @override + int get hashCode { + int hash = 0; + hash = JenkinsSmiHash.combine(hash, textDocument.hashCode); + hash = JenkinsSmiHash.combine(hash, position.hashCode); + hash = JenkinsSmiHash.combine(hash, newName.hashCode); + return JenkinsSmiHash.finish(hash); + } + + @override + String toString() => jsonEncoder.convert(toJson()); } class RenameRegistrationOptions implements TextDocumentRegistrationOptions, ToJsonable { RenameRegistrationOptions(this.prepareProvider, this.documentSelector); - factory RenameRegistrationOptions.fromJson(Map<String, dynamic> json) { + static RenameRegistrationOptions fromJson(Map<String, dynamic> json) { final prepareProvider = json['prepareProvider']; final documentSelector = json['documentSelector'] - ?.map((item) => item != null ? new DocumentFilter.fromJson(item) : null) + ?.map((item) => item != null ? DocumentFilter.fromJson(item) : null) ?.cast<DocumentFilter>() ?.toList(); return new RenameRegistrationOptions(prepareProvider, documentSelector); } - /// A document selector to identify the scope of the - /// registration. If set to null the document selector - /// provided on the client side will be used. + /// A document selector to identify the scope of the registration. If set to + /// null the document selector provided on the client side will be used. final List<DocumentFilter> documentSelector; - /// Renames should be checked and tested for validity - /// before being executed. + /// Renames should be checked and tested for validity before being executed. final bool prepareProvider; Map<String, dynamic> toJson() { @@ -4259,9 +6299,30 @@ obj['documentSelector'] .every((item) => DocumentFilter.canParse(item)))); } + + @override + bool operator ==(other) { + if (other is RenameRegistrationOptions) { + return prepareProvider == other.prepareProvider && + documentSelector == other.documentSelector && + true; + } + return false; + } + + @override + int get hashCode { + int hash = 0; + hash = JenkinsSmiHash.combine(hash, prepareProvider.hashCode); + hash = JenkinsSmiHash.combine(hash, documentSelector.hashCode); + return JenkinsSmiHash.finish(hash); + } + + @override + String toString() => jsonEncoder.convert(toJson()); } -class RequestMessage implements Message, ToJsonable { +class RequestMessage implements Message, IncomingMessage, ToJsonable { RequestMessage(this.id, this.method, this.params, this.jsonrpc) { if (id == null) { throw 'id is required but was not provided'; @@ -4273,19 +6334,15 @@ throw 'jsonrpc is required but was not provided'; } } - factory RequestMessage.fromJson(Map<String, dynamic> json) { + static RequestMessage fromJson(Map<String, dynamic> json) { final id = json['id'] is num ? new Either2<num, String>.t1(json['id']) : (json['id'] is String ? new Either2<num, String>.t2(json['id']) - : (throw '''${json['id']} was not one of (number, string)''')); - final method = json['method']; - final params = (json['params'] is List && - (json['params'].length == 0 || - json['params'].every((item) => true))) - ? new Either2<List<dynamic>, dynamic>.t1( - json['params']?.map((item) => item)?.cast<dynamic>()?.toList()) - : (new Either2<List<dynamic>, dynamic>.t2(json['params'])); + : (throw '''${json['id']} was not one of (num, String)''')); + final method = + json['method'] != null ? Method.fromJson(json['method']) : null; + final params = json['params']; final jsonrpc = json['jsonrpc']; return new RequestMessage(id, method, params, jsonrpc); } @@ -4295,10 +6352,10 @@ final String jsonrpc; /// The method to be invoked. - final String method; + final Method method; /// The method's params. - final Either2<List<dynamic>, dynamic> params; + final dynamic params; Map<String, dynamic> toJson() { Map<String, dynamic> __result = {}; @@ -4317,17 +6374,42 @@ obj.containsKey('id') && (obj['id'] is num || obj['id'] is String) && obj.containsKey('method') && - obj['method'] is String && + Method.canParse(obj['method']) && obj.containsKey('jsonrpc') && obj['jsonrpc'] is String; } + + @override + bool operator ==(other) { + if (other is RequestMessage) { + return id == other.id && + method == other.method && + params == other.params && + jsonrpc == other.jsonrpc && + true; + } + return false; + } + + @override + int get hashCode { + int hash = 0; + hash = JenkinsSmiHash.combine(hash, id.hashCode); + hash = JenkinsSmiHash.combine(hash, method.hashCode); + hash = JenkinsSmiHash.combine(hash, params.hashCode); + hash = JenkinsSmiHash.combine(hash, jsonrpc.hashCode); + return JenkinsSmiHash.finish(hash); + } + + @override + String toString() => jsonEncoder.convert(toJson()); } class ResourceOperationKind { const ResourceOperationKind._(this._value); const ResourceOperationKind.fromJson(this._value); - final Object _value; + final String _value; static bool canParse(Object obj) { switch (obj) { @@ -4368,19 +6450,19 @@ throw 'message is required but was not provided'; } } - factory ResponseError.fromJson(Map<String, dynamic> json) { - final code = json['code']; + static ResponseError<D> fromJson<D>(Map<String, dynamic> json) { + final code = + json['code'] != null ? ErrorCodes.fromJson(json['code']) : null; final message = json['message']; final data = json['data']; return new ResponseError<D>(code, message, data); } /// A number indicating the error type that occurred. - final num code; + final ErrorCodes code; - /// A Primitive or Structured value that contains - /// additional information about the error. Can be - /// omitted. + /// A Primitive or Structured value that contains additional information about + /// the error. Can be omitted. final D data; /// A string providing a short description of the error. @@ -4400,10 +6482,33 @@ static bool canParse(Object obj) { return obj is Map<String, dynamic> && obj.containsKey('code') && - obj['code'] is num && + ErrorCodes.canParse(obj['code']) && obj.containsKey('message') && obj['message'] is String; } + + @override + bool operator ==(other) { + if (other is ResponseError) { + return code == other.code && + message == other.message && + data == other.data && + true; + } + return false; + } + + @override + int get hashCode { + int hash = 0; + hash = JenkinsSmiHash.combine(hash, code.hashCode); + hash = JenkinsSmiHash.combine(hash, message.hashCode); + hash = JenkinsSmiHash.combine(hash, data.hashCode); + return JenkinsSmiHash.finish(hash); + } + + @override + String toString() => jsonEncoder.convert(toJson()); } class ResponseMessage implements Message, ToJsonable { @@ -4412,14 +6517,18 @@ throw 'jsonrpc is required but was not provided'; } } - factory ResponseMessage.fromJson(Map<String, dynamic> json) { + static ResponseMessage fromJson(Map<String, dynamic> json) { final id = json['id'] is num ? new Either2<num, String>.t1(json['id']) : (json['id'] is String ? new Either2<num, String>.t2(json['id']) - : (throw '''${json['id']} was not one of (number, string)''')); + : (json['id'] == null + ? null + : (throw '''${json['id']} was not one of (num, String)'''))); final result = json['result']; - final error = json['error']; + final error = json['error'] != null + ? ResponseError.fromJson<dynamic>(json['error']) + : null; final jsonrpc = json['jsonrpc']; return new ResponseMessage(id, result, error, jsonrpc); } @@ -4431,8 +6540,7 @@ final Either2<num, String> id; final String jsonrpc; - /// The result of a request. This can be omitted in the - /// case of an error. + /// The result of a request. This can be omitted in the case of an error. final dynamic result; Map<String, dynamic> toJson() { @@ -4456,18 +6564,42 @@ obj.containsKey('jsonrpc') && obj['jsonrpc'] is String; } + + @override + bool operator ==(other) { + if (other is ResponseMessage) { + return id == other.id && + result == other.result && + error == other.error && + jsonrpc == other.jsonrpc && + true; + } + return false; + } + + @override + int get hashCode { + int hash = 0; + hash = JenkinsSmiHash.combine(hash, id.hashCode); + hash = JenkinsSmiHash.combine(hash, result.hashCode); + hash = JenkinsSmiHash.combine(hash, error.hashCode); + hash = JenkinsSmiHash.combine(hash, jsonrpc.hashCode); + return JenkinsSmiHash.finish(hash); + } + + @override + String toString() => jsonEncoder.convert(toJson()); } /// Save options. class SaveOptions implements ToJsonable { SaveOptions(this.includeText); - factory SaveOptions.fromJson(Map<String, dynamic> json) { + static SaveOptions fromJson(Map<String, dynamic> json) { final includeText = json['includeText']; return new SaveOptions(includeText); } - /// The client is supposed to include the content on - /// save. + /// The client is supposed to include the content on save. final bool includeText; Map<String, dynamic> toJson() { @@ -4481,6 +6613,24 @@ static bool canParse(Object obj) { return obj is Map<String, dynamic>; } + + @override + bool operator ==(other) { + if (other is SaveOptions) { + return includeText == other.includeText && true; + } + return false; + } + + @override + int get hashCode { + int hash = 0; + hash = JenkinsSmiHash.combine(hash, includeText.hashCode); + return JenkinsSmiHash.finish(hash); + } + + @override + String toString() => jsonEncoder.convert(toJson()); } class ServerCapabilities implements ToJsonable { @@ -4490,6 +6640,8 @@ this.completionProvider, this.signatureHelpProvider, this.definitionProvider, + this.typeDefinitionProvider, + this.implementationProvider, this.referencesProvider, this.documentHighlightProvider, this.documentSymbolProvider, @@ -4501,28 +6653,38 @@ this.documentOnTypeFormattingProvider, this.renameProvider, this.documentLinkProvider, + this.colorProvider, + this.foldingRangeProvider, this.executeCommandProvider, - this.supported, - this.changeNotifications); - factory ServerCapabilities.fromJson(Map<String, dynamic> json) { + this.workspace, + this.experimental); + static ServerCapabilities fromJson(Map<String, dynamic> json) { final textDocumentSync = TextDocumentSyncOptions.canParse( json['textDocumentSync']) ? new Either2<TextDocumentSyncOptions, num>.t1( json['textDocumentSync'] != null - ? new TextDocumentSyncOptions.fromJson(json['textDocumentSync']) + ? TextDocumentSyncOptions.fromJson(json['textDocumentSync']) : null) : (json['textDocumentSync'] is num ? new Either2<TextDocumentSyncOptions, num>.t2( json['textDocumentSync']) - : (throw '''${json['textDocumentSync']} was not one of (TextDocumentSyncOptions, number)''')); + : (json['textDocumentSync'] == null + ? null + : (throw '''${json['textDocumentSync']} was not one of (TextDocumentSyncOptions, num)'''))); final hoverProvider = json['hoverProvider']; final completionProvider = json['completionProvider'] != null - ? new CompletionOptions.fromJson(json['completionProvider']) + ? CompletionOptions.fromJson(json['completionProvider']) : null; final signatureHelpProvider = json['signatureHelpProvider'] != null - ? new SignatureHelpOptions.fromJson(json['signatureHelpProvider']) + ? SignatureHelpOptions.fromJson(json['signatureHelpProvider']) : null; final definitionProvider = json['definitionProvider']; + final typeDefinitionProvider = json['typeDefinitionProvider'] is bool + ? new Either2<bool, dynamic>.t1(json['typeDefinitionProvider']) + : (new Either2<bool, dynamic>.t2(json['typeDefinitionProvider'])); + final implementationProvider = json['implementationProvider'] is bool + ? new Either2<bool, dynamic>.t1(json['implementationProvider']) + : (new Either2<bool, dynamic>.t2(json['implementationProvider'])); final referencesProvider = json['referencesProvider']; final documentHighlightProvider = json['documentHighlightProvider']; final documentSymbolProvider = json['documentSymbolProvider']; @@ -4532,45 +6694,70 @@ : (CodeActionOptions.canParse(json['codeActionProvider']) ? new Either2<bool, CodeActionOptions>.t2( json['codeActionProvider'] != null - ? new CodeActionOptions.fromJson(json['codeActionProvider']) + ? CodeActionOptions.fromJson(json['codeActionProvider']) : null) - : (throw '''${json['codeActionProvider']} was not one of (boolean, CodeActionOptions)''')); + : (json['codeActionProvider'] == null + ? null + : (throw '''${json['codeActionProvider']} was not one of (bool, CodeActionOptions)'''))); final codeLensProvider = json['codeLensProvider'] != null - ? new CodeLensOptions.fromJson(json['codeLensProvider']) + ? CodeLensOptions.fromJson(json['codeLensProvider']) : null; final documentFormattingProvider = json['documentFormattingProvider']; final documentRangeFormattingProvider = json['documentRangeFormattingProvider']; final documentOnTypeFormattingProvider = json['documentOnTypeFormattingProvider'] != null - ? new DocumentOnTypeFormattingOptions.fromJson( + ? DocumentOnTypeFormattingOptions.fromJson( json['documentOnTypeFormattingProvider']) : null; final renameProvider = json['renameProvider'] is bool ? new Either2<bool, RenameOptions>.t1(json['renameProvider']) : (RenameOptions.canParse(json['renameProvider']) ? new Either2<bool, RenameOptions>.t2(json['renameProvider'] != null - ? new RenameOptions.fromJson(json['renameProvider']) + ? RenameOptions.fromJson(json['renameProvider']) : null) - : (throw '''${json['renameProvider']} was not one of (boolean, RenameOptions)''')); + : (json['renameProvider'] == null + ? null + : (throw '''${json['renameProvider']} was not one of (bool, RenameOptions)'''))); final documentLinkProvider = json['documentLinkProvider'] != null - ? new DocumentLinkOptions.fromJson(json['documentLinkProvider']) + ? DocumentLinkOptions.fromJson(json['documentLinkProvider']) : null; + final colorProvider = json['colorProvider'] is bool + ? new Either3<bool, ColorProviderOptions, dynamic>.t1( + json['colorProvider']) + : (ColorProviderOptions.canParse(json['colorProvider']) + ? new Either3<bool, ColorProviderOptions, dynamic>.t2( + json['colorProvider'] != null + ? ColorProviderOptions.fromJson(json['colorProvider']) + : null) + : (new Either3<bool, ColorProviderOptions, dynamic>.t3( + json['colorProvider']))); + final foldingRangeProvider = json['foldingRangeProvider'] is bool + ? new Either3<bool, FoldingRangeProviderOptions, dynamic>.t1( + json['foldingRangeProvider']) + : (FoldingRangeProviderOptions.canParse(json['foldingRangeProvider']) + ? new Either3<bool, FoldingRangeProviderOptions, dynamic>.t2( + json['foldingRangeProvider'] != null + ? FoldingRangeProviderOptions.fromJson( + json['foldingRangeProvider']) + : null) + : (new Either3<bool, FoldingRangeProviderOptions, dynamic>.t3( + json['foldingRangeProvider']))); final executeCommandProvider = json['executeCommandProvider'] != null - ? new ExecuteCommandOptions.fromJson(json['executeCommandProvider']) + ? ExecuteCommandOptions.fromJson(json['executeCommandProvider']) : null; - final supported = json['supported']; - final changeNotifications = json['changeNotifications'] is String - ? new Either2<String, bool>.t1(json['changeNotifications']) - : (json['changeNotifications'] is bool - ? new Either2<String, bool>.t2(json['changeNotifications']) - : (throw '''${json['changeNotifications']} was not one of (string, boolean)''')); + final workspace = json['workspace'] != null + ? ServerCapabilitiesWorkspace.fromJson(json['workspace']) + : null; + final experimental = json['experimental']; return new ServerCapabilities( textDocumentSync, hoverProvider, completionProvider, signatureHelpProvider, definitionProvider, + typeDefinitionProvider, + implementationProvider, referencesProvider, documentHighlightProvider, documentSymbolProvider, @@ -4582,31 +6769,26 @@ documentOnTypeFormattingProvider, renameProvider, documentLinkProvider, + colorProvider, + foldingRangeProvider, executeCommandProvider, - supported, - changeNotifications); + workspace, + experimental); } - /// Whether the server wants to receive workspace folder - /// change notifications. - /// - /// If a strings is provided the string is treated as a - /// ID under which the notification is registered on the - /// client side. The ID can be used to unregister for - /// these events using the `client/unregisterCapability` - /// request. - final Either2<String, bool> changeNotifications; - - /// The server provides code actions. The - /// `CodeActionOptions` return type is only valid if the - /// client signals code action literal support via the - /// property - /// `textDocument.codeAction.codeActionLiteralSupport`. + /// The server provides code actions. The `CodeActionOptions` return type is + /// only valid if the client signals code action literal support via the + /// property `textDocument.codeAction.codeActionLiteralSupport`. final Either2<bool, CodeActionOptions> codeActionProvider; /// The server provides code lens. final CodeLensOptions codeLensProvider; + /// The server provides color provider support. + /// + /// Since 3.6.0 + final Either3<bool, ColorProviderOptions, dynamic> colorProvider; + /// The server provides completion support. final CompletionOptions completionProvider; @@ -4634,31 +6816,48 @@ /// The server provides execute command support. final ExecuteCommandOptions executeCommandProvider; + /// Experimental server capabilities. + final dynamic experimental; + + /// The server provides folding provider support. + /// + /// Since 3.10.0 + final Either3<bool, FoldingRangeProviderOptions, dynamic> + foldingRangeProvider; + /// The server provides hover support. final bool hoverProvider; + /// The server provides Goto Implementation support. + /// + /// Since 3.6.0 + final Either2<bool, dynamic> implementationProvider; + /// The server provides find references support. final bool referencesProvider; - /// The server provides rename support. RenameOptions - /// may only be specified if the client states that it - /// supports `prepareSupport` in its initial + /// The server provides rename support. RenameOptions may only be specified if + /// the client states that it supports `prepareSupport` in its initial /// `initialize` request. final Either2<bool, RenameOptions> renameProvider; /// The server provides signature help support. final SignatureHelpOptions signatureHelpProvider; - /// The server has support for workspace folders - final bool supported; - - /// Defines how text documents are synced. Is either a - /// detailed structure defining each notification or for - /// backwards compatibility the TextDocumentSyncKind - /// number. If omitted it defaults to + /// Defines how text documents are synced. Is either a detailed structure + /// defining each notification or for backwards compatibility the + /// TextDocumentSyncKind number. If omitted it defaults to /// `TextDocumentSyncKind.None`. final Either2<TextDocumentSyncOptions, num> textDocumentSync; + /// The server provides Goto Type Definition support. + /// + /// Since 3.6.0 + final Either2<bool, dynamic> typeDefinitionProvider; + + /// Workspace specific server capabilities + final ServerCapabilitiesWorkspace workspace; + /// The server provides workspace symbol support. final bool workspaceSymbolProvider; @@ -4679,6 +6878,12 @@ if (definitionProvider != null) { __result['definitionProvider'] = definitionProvider; } + if (typeDefinitionProvider != null) { + __result['typeDefinitionProvider'] = typeDefinitionProvider; + } + if (implementationProvider != null) { + __result['implementationProvider'] = implementationProvider; + } if (referencesProvider != null) { __result['referencesProvider'] = referencesProvider; } @@ -4714,9 +6919,170 @@ if (documentLinkProvider != null) { __result['documentLinkProvider'] = documentLinkProvider; } + if (colorProvider != null) { + __result['colorProvider'] = colorProvider; + } + if (foldingRangeProvider != null) { + __result['foldingRangeProvider'] = foldingRangeProvider; + } if (executeCommandProvider != null) { __result['executeCommandProvider'] = executeCommandProvider; } + if (workspace != null) { + __result['workspace'] = workspace; + } + if (experimental != null) { + __result['experimental'] = experimental; + } + return __result; + } + + static bool canParse(Object obj) { + return obj is Map<String, dynamic>; + } + + @override + bool operator ==(other) { + if (other is ServerCapabilities) { + return textDocumentSync == other.textDocumentSync && + hoverProvider == other.hoverProvider && + completionProvider == other.completionProvider && + signatureHelpProvider == other.signatureHelpProvider && + definitionProvider == other.definitionProvider && + typeDefinitionProvider == other.typeDefinitionProvider && + implementationProvider == other.implementationProvider && + referencesProvider == other.referencesProvider && + documentHighlightProvider == other.documentHighlightProvider && + documentSymbolProvider == other.documentSymbolProvider && + workspaceSymbolProvider == other.workspaceSymbolProvider && + codeActionProvider == other.codeActionProvider && + codeLensProvider == other.codeLensProvider && + documentFormattingProvider == other.documentFormattingProvider && + documentRangeFormattingProvider == + other.documentRangeFormattingProvider && + documentOnTypeFormattingProvider == + other.documentOnTypeFormattingProvider && + renameProvider == other.renameProvider && + documentLinkProvider == other.documentLinkProvider && + colorProvider == other.colorProvider && + foldingRangeProvider == other.foldingRangeProvider && + executeCommandProvider == other.executeCommandProvider && + workspace == other.workspace && + experimental == other.experimental && + true; + } + return false; + } + + @override + int get hashCode { + int hash = 0; + hash = JenkinsSmiHash.combine(hash, textDocumentSync.hashCode); + hash = JenkinsSmiHash.combine(hash, hoverProvider.hashCode); + hash = JenkinsSmiHash.combine(hash, completionProvider.hashCode); + hash = JenkinsSmiHash.combine(hash, signatureHelpProvider.hashCode); + hash = JenkinsSmiHash.combine(hash, definitionProvider.hashCode); + hash = JenkinsSmiHash.combine(hash, typeDefinitionProvider.hashCode); + hash = JenkinsSmiHash.combine(hash, implementationProvider.hashCode); + hash = JenkinsSmiHash.combine(hash, referencesProvider.hashCode); + hash = JenkinsSmiHash.combine(hash, documentHighlightProvider.hashCode); + hash = JenkinsSmiHash.combine(hash, documentSymbolProvider.hashCode); + hash = JenkinsSmiHash.combine(hash, workspaceSymbolProvider.hashCode); + hash = JenkinsSmiHash.combine(hash, codeActionProvider.hashCode); + hash = JenkinsSmiHash.combine(hash, codeLensProvider.hashCode); + hash = JenkinsSmiHash.combine(hash, documentFormattingProvider.hashCode); + hash = + JenkinsSmiHash.combine(hash, documentRangeFormattingProvider.hashCode); + hash = + JenkinsSmiHash.combine(hash, documentOnTypeFormattingProvider.hashCode); + hash = JenkinsSmiHash.combine(hash, renameProvider.hashCode); + hash = JenkinsSmiHash.combine(hash, documentLinkProvider.hashCode); + hash = JenkinsSmiHash.combine(hash, colorProvider.hashCode); + hash = JenkinsSmiHash.combine(hash, foldingRangeProvider.hashCode); + hash = JenkinsSmiHash.combine(hash, executeCommandProvider.hashCode); + hash = JenkinsSmiHash.combine(hash, workspace.hashCode); + hash = JenkinsSmiHash.combine(hash, experimental.hashCode); + return JenkinsSmiHash.finish(hash); + } + + @override + String toString() => jsonEncoder.convert(toJson()); +} + +class ServerCapabilitiesWorkspace implements ToJsonable { + ServerCapabilitiesWorkspace(this.workspaceFolders); + static ServerCapabilitiesWorkspace fromJson(Map<String, dynamic> json) { + final workspaceFolders = json['workspaceFolders'] != null + ? ServerCapabilitiesWorkspaceFolders.fromJson(json['workspaceFolders']) + : null; + return new ServerCapabilitiesWorkspace(workspaceFolders); + } + + /// The server supports workspace folder. + /// + /// Since 3.6.0 + final ServerCapabilitiesWorkspaceFolders workspaceFolders; + + Map<String, dynamic> toJson() { + Map<String, dynamic> __result = {}; + if (workspaceFolders != null) { + __result['workspaceFolders'] = workspaceFolders; + } + return __result; + } + + static bool canParse(Object obj) { + return obj is Map<String, dynamic>; + } + + @override + bool operator ==(other) { + if (other is ServerCapabilitiesWorkspace) { + return workspaceFolders == other.workspaceFolders && true; + } + return false; + } + + @override + int get hashCode { + int hash = 0; + hash = JenkinsSmiHash.combine(hash, workspaceFolders.hashCode); + return JenkinsSmiHash.finish(hash); + } + + @override + String toString() => jsonEncoder.convert(toJson()); +} + +class ServerCapabilitiesWorkspaceFolders implements ToJsonable { + ServerCapabilitiesWorkspaceFolders(this.supported, this.changeNotifications); + static ServerCapabilitiesWorkspaceFolders fromJson( + Map<String, dynamic> json) { + final supported = json['supported']; + final changeNotifications = json['changeNotifications'] is String + ? new Either2<String, bool>.t1(json['changeNotifications']) + : (json['changeNotifications'] is bool + ? new Either2<String, bool>.t2(json['changeNotifications']) + : (json['changeNotifications'] == null + ? null + : (throw '''${json['changeNotifications']} was not one of (String, bool)'''))); + return new ServerCapabilitiesWorkspaceFolders( + supported, changeNotifications); + } + + /// Whether the server wants to receive workspace folder change notifications. + /// + /// If a strings is provided the string is treated as a ID under which the + /// notification is registered on the client side. The ID can be used to + /// unregister for these events using the `client/unregisterCapability` + /// request. + final Either2<String, bool> changeNotifications; + + /// The server has support for workspace folders + final bool supported; + + Map<String, dynamic> toJson() { + Map<String, dynamic> __result = {}; if (supported != null) { __result['supported'] = supported; } @@ -4729,6 +7095,27 @@ static bool canParse(Object obj) { return obj is Map<String, dynamic>; } + + @override + bool operator ==(other) { + if (other is ServerCapabilitiesWorkspaceFolders) { + return supported == other.supported && + changeNotifications == other.changeNotifications && + true; + } + return false; + } + + @override + int get hashCode { + int hash = 0; + hash = JenkinsSmiHash.combine(hash, supported.hashCode); + hash = JenkinsSmiHash.combine(hash, changeNotifications.hashCode); + return JenkinsSmiHash.finish(hash); + } + + @override + String toString() => jsonEncoder.convert(toJson()); } class ShowMessageParams implements ToJsonable { @@ -4740,9 +7127,9 @@ throw 'message is required but was not provided'; } } - factory ShowMessageParams.fromJson(Map<String, dynamic> json) { + static ShowMessageParams fromJson(Map<String, dynamic> json) { final type = - json['type'] != null ? new MessageType.fromJson(json['type']) : null; + json['type'] != null ? MessageType.fromJson(json['type']) : null; final message = json['message']; return new ShowMessageParams(type, message); } @@ -4768,6 +7155,25 @@ obj.containsKey('message') && obj['message'] is String; } + + @override + bool operator ==(other) { + if (other is ShowMessageParams) { + return type == other.type && message == other.message && true; + } + return false; + } + + @override + int get hashCode { + int hash = 0; + hash = JenkinsSmiHash.combine(hash, type.hashCode); + hash = JenkinsSmiHash.combine(hash, message.hashCode); + return JenkinsSmiHash.finish(hash); + } + + @override + String toString() => jsonEncoder.convert(toJson()); } class ShowMessageRequestParams implements ToJsonable { @@ -4779,13 +7185,12 @@ throw 'message is required but was not provided'; } } - factory ShowMessageRequestParams.fromJson(Map<String, dynamic> json) { + static ShowMessageRequestParams fromJson(Map<String, dynamic> json) { final type = - json['type'] != null ? new MessageType.fromJson(json['type']) : null; + json['type'] != null ? MessageType.fromJson(json['type']) : null; final message = json['message']; final actions = json['actions'] - ?.map((item) => - item != null ? new MessageActionItem.fromJson(item) : null) + ?.map((item) => item != null ? MessageActionItem.fromJson(item) : null) ?.cast<MessageActionItem>() ?.toList(); return new ShowMessageRequestParams(type, message, actions); @@ -4818,21 +7223,44 @@ obj.containsKey('message') && obj['message'] is String; } + + @override + bool operator ==(other) { + if (other is ShowMessageRequestParams) { + return type == other.type && + message == other.message && + listEqual(actions, other.actions, + (MessageActionItem a, MessageActionItem b) => a == b) && + true; + } + return false; + } + + @override + int get hashCode { + int hash = 0; + hash = JenkinsSmiHash.combine(hash, type.hashCode); + hash = JenkinsSmiHash.combine(hash, message.hashCode); + hash = JenkinsSmiHash.combine(hash, actions.hashCode); + return JenkinsSmiHash.finish(hash); + } + + @override + String toString() => jsonEncoder.convert(toJson()); } -/// Signature help represents the signature of something -/// callable. There can be multiple signature but only one -/// active and only one active parameter. +/// Signature help represents the signature of something callable. There can be +/// multiple signature but only one active and only one active parameter. class SignatureHelp implements ToJsonable { SignatureHelp(this.signatures, this.activeSignature, this.activeParameter) { if (signatures == null) { throw 'signatures is required but was not provided'; } } - factory SignatureHelp.fromJson(Map<String, dynamic> json) { + static SignatureHelp fromJson(Map<String, dynamic> json) { final signatures = json['signatures'] - ?.map((item) => - item != null ? new SignatureInformation.fromJson(item) : null) + ?.map( + (item) => item != null ? SignatureInformation.fromJson(item) : null) ?.cast<SignatureInformation>() ?.toList(); final activeSignature = json['activeSignature']; @@ -4840,24 +7268,20 @@ return new SignatureHelp(signatures, activeSignature, activeParameter); } - /// The active parameter of the active signature. If - /// omitted or the value lies outside the range of - /// `signatures[activeSignature].parameters` defaults to - /// 0 if the active signature has parameters. If the - /// active signature has no parameters it is ignored. In - /// future version of the protocol this property might - /// become mandatory to better express the active - /// parameter if the active signature does have any. + /// The active parameter of the active signature. If omitted or the value lies + /// outside the range of `signatures[activeSignature].parameters` defaults to + /// 0 if the active signature has parameters. If the active signature has no + /// parameters it is ignored. In future version of the protocol this property + /// might become mandatory to better express the active parameter if the + /// active signature does have any. final num activeParameter; - /// The active signature. If omitted or the value lies - /// outside the range of `signatures` the value defaults - /// to zero or is ignored if `signatures.length === 0`. - /// Whenever possible implementors should make an active - /// decision about the active signature and shouldn't - /// rely on a default value. In future version of the - /// protocol this property might become mandatory to - /// better express this. + /// The active signature. If omitted or the value lies outside the range of + /// `signatures` the value defaults to zero or is ignored if + /// `signatures.length === 0`. Whenever possible implementors should make an + /// active decision about the active signature and shouldn't rely on a default + /// value. In future version of the protocol this property might become + /// mandatory to better express this. final num activeSignature; /// One or more signatures. @@ -4884,12 +7308,36 @@ obj['signatures'] .every((item) => SignatureInformation.canParse(item)))); } + + @override + bool operator ==(other) { + if (other is SignatureHelp) { + return listEqual(signatures, other.signatures, + (SignatureInformation a, SignatureInformation b) => a == b) && + activeSignature == other.activeSignature && + activeParameter == other.activeParameter && + true; + } + return false; + } + + @override + int get hashCode { + int hash = 0; + hash = JenkinsSmiHash.combine(hash, signatures.hashCode); + hash = JenkinsSmiHash.combine(hash, activeSignature.hashCode); + hash = JenkinsSmiHash.combine(hash, activeParameter.hashCode); + return JenkinsSmiHash.finish(hash); + } + + @override + String toString() => jsonEncoder.convert(toJson()); } /// Signature help options. class SignatureHelpOptions implements ToJsonable { SignatureHelpOptions(this.triggerCharacters); - factory SignatureHelpOptions.fromJson(Map<String, dynamic> json) { + static SignatureHelpOptions fromJson(Map<String, dynamic> json) { final triggerCharacters = json['triggerCharacters'] ?.map((item) => item) ?.cast<String>() @@ -4897,8 +7345,7 @@ return new SignatureHelpOptions(triggerCharacters); } - /// The characters that trigger signature help - /// automatically. + /// The characters that trigger signature help automatically. final List<String> triggerCharacters; Map<String, dynamic> toJson() { @@ -4912,32 +7359,50 @@ static bool canParse(Object obj) { return obj is Map<String, dynamic>; } + + @override + bool operator ==(other) { + if (other is SignatureHelpOptions) { + return listEqual(triggerCharacters, other.triggerCharacters, + (String a, String b) => a == b) && + true; + } + return false; + } + + @override + int get hashCode { + int hash = 0; + hash = JenkinsSmiHash.combine(hash, triggerCharacters.hashCode); + return JenkinsSmiHash.finish(hash); + } + + @override + String toString() => jsonEncoder.convert(toJson()); } class SignatureHelpRegistrationOptions implements TextDocumentRegistrationOptions, ToJsonable { SignatureHelpRegistrationOptions( this.triggerCharacters, this.documentSelector); - factory SignatureHelpRegistrationOptions.fromJson(Map<String, dynamic> json) { + static SignatureHelpRegistrationOptions fromJson(Map<String, dynamic> json) { final triggerCharacters = json['triggerCharacters'] ?.map((item) => item) ?.cast<String>() ?.toList(); final documentSelector = json['documentSelector'] - ?.map((item) => item != null ? new DocumentFilter.fromJson(item) : null) + ?.map((item) => item != null ? DocumentFilter.fromJson(item) : null) ?.cast<DocumentFilter>() ?.toList(); return new SignatureHelpRegistrationOptions( triggerCharacters, documentSelector); } - /// A document selector to identify the scope of the - /// registration. If set to null the document selector - /// provided on the client side will be used. + /// A document selector to identify the scope of the registration. If set to + /// null the document selector provided on the client side will be used. final List<DocumentFilter> documentSelector; - /// The characters that trigger signature help - /// automatically. + /// The characters that trigger signature help automatically. final List<String> triggerCharacters; Map<String, dynamic> toJson() { @@ -4957,41 +7422,63 @@ obj['documentSelector'] .every((item) => DocumentFilter.canParse(item)))); } + + @override + bool operator ==(other) { + if (other is SignatureHelpRegistrationOptions) { + return listEqual(triggerCharacters, other.triggerCharacters, + (String a, String b) => a == b) && + documentSelector == other.documentSelector && + true; + } + return false; + } + + @override + int get hashCode { + int hash = 0; + hash = JenkinsSmiHash.combine(hash, triggerCharacters.hashCode); + hash = JenkinsSmiHash.combine(hash, documentSelector.hashCode); + return JenkinsSmiHash.finish(hash); + } + + @override + String toString() => jsonEncoder.convert(toJson()); } -/// Represents the signature of something callable. A -/// signature can have a label, like a function-name, a -/// doc-comment, and a set of parameters. +/// Represents the signature of something callable. A signature can have a +/// label, like a function-name, a doc-comment, and a set of parameters. class SignatureInformation implements ToJsonable { SignatureInformation(this.label, this.documentation, this.parameters) { if (label == null) { throw 'label is required but was not provided'; } } - factory SignatureInformation.fromJson(Map<String, dynamic> json) { + static SignatureInformation fromJson(Map<String, dynamic> json) { final label = json['label']; final documentation = json['documentation'] is String ? new Either2<String, MarkupContent>.t1(json['documentation']) : (MarkupContent.canParse(json['documentation']) ? new Either2<String, MarkupContent>.t2( json['documentation'] != null - ? new MarkupContent.fromJson(json['documentation']) + ? MarkupContent.fromJson(json['documentation']) : null) - : (throw '''${json['documentation']} was not one of (string, MarkupContent)''')); + : (json['documentation'] == null + ? null + : (throw '''${json['documentation']} was not one of (String, MarkupContent)'''))); final parameters = json['parameters'] - ?.map((item) => - item != null ? new ParameterInformation.fromJson(item) : null) + ?.map( + (item) => item != null ? ParameterInformation.fromJson(item) : null) ?.cast<ParameterInformation>() ?.toList(); return new SignatureInformation(label, documentation, parameters); } - /// The human-readable doc-comment of this signature. - /// Will be shown in the UI but can be omitted. + /// The human-readable doc-comment of this signature. Will be shown in the UI + /// but can be omitted. final Either2<String, MarkupContent> documentation; - /// The label of this signature. Will be shown in the - /// UI. + /// The label of this signature. Will be shown in the UI. final String label; /// The parameters of this signature. @@ -5014,20 +7501,42 @@ obj.containsKey('label') && obj['label'] is String; } + + @override + bool operator ==(other) { + if (other is SignatureInformation) { + return label == other.label && + documentation == other.documentation && + listEqual(parameters, other.parameters, + (ParameterInformation a, ParameterInformation b) => a == b) && + true; + } + return false; + } + + @override + int get hashCode { + int hash = 0; + hash = JenkinsSmiHash.combine(hash, label.hashCode); + hash = JenkinsSmiHash.combine(hash, documentation.hashCode); + hash = JenkinsSmiHash.combine(hash, parameters.hashCode); + return JenkinsSmiHash.finish(hash); + } + + @override + String toString() => jsonEncoder.convert(toJson()); } -/// Static registration options to be returned in the -/// initialize request. +/// Static registration options to be returned in the initialize request. class StaticRegistrationOptions implements ToJsonable { StaticRegistrationOptions(this.id); - factory StaticRegistrationOptions.fromJson(Map<String, dynamic> json) { + static StaticRegistrationOptions fromJson(Map<String, dynamic> json) { final id = json['id']; return new StaticRegistrationOptions(id); } - /// The id used to register the request. The id can be - /// used to deregister the request again. See also - /// Registration#id. + /// The id used to register the request. The id can be used to deregister the + /// request again. See also Registration#id. final String id; Map<String, dynamic> toJson() { @@ -5041,10 +7550,28 @@ static bool canParse(Object obj) { return obj is Map<String, dynamic>; } + + @override + bool operator ==(other) { + if (other is StaticRegistrationOptions) { + return id == other.id && true; + } + return false; + } + + @override + int get hashCode { + int hash = 0; + hash = JenkinsSmiHash.combine(hash, id.hashCode); + return JenkinsSmiHash.finish(hash); + } + + @override + String toString() => jsonEncoder.convert(toJson()); } -/// Represents information about programming constructs -/// like variables, classes, interfaces etc. +/// Represents information about programming constructs like variables, classes, +/// interfaces etc. class SymbolInformation implements ToJsonable { SymbolInformation(this.name, this.kind, this.deprecated, this.location, this.containerName) { @@ -5058,43 +7585,39 @@ throw 'location is required but was not provided'; } } - factory SymbolInformation.fromJson(Map<String, dynamic> json) { + static SymbolInformation fromJson(Map<String, dynamic> json) { final name = json['name']; - final kind = json['kind']; + final kind = + json['kind'] != null ? SymbolKind.fromJson(json['kind']) : null; final deprecated = json['deprecated']; - final location = json['location'] != null - ? new Location.fromJson(json['location']) - : null; + final location = + json['location'] != null ? Location.fromJson(json['location']) : null; final containerName = json['containerName']; return new SymbolInformation( name, kind, deprecated, location, containerName); } - /// The name of the symbol containing this symbol. This - /// information is for user interface purposes (e.g. to - /// render a qualifier in the user interface if - /// necessary). It can't be used to re-infer a hierarchy - /// for the document symbols. + /// The name of the symbol containing this symbol. This information is for + /// user interface purposes (e.g. to render a qualifier in the user interface + /// if necessary). It can't be used to re-infer a hierarchy for the document + /// symbols. final String containerName; /// Indicates if this symbol is deprecated. final bool deprecated; /// The kind of this symbol. - final num kind; + final SymbolKind kind; - /// The location of this symbol. The location's range is - /// used by a tool to reveal the location in the editor. - /// If the symbol is selected in the tool the range's - /// start information is used to position the cursor. So - /// the range usually spans more then the actual - /// symbol's name and does normally include things like - /// visibility modifiers. + /// The location of this symbol. The location's range is used by a tool to + /// reveal the location in the editor. If the symbol is selected in the tool + /// the range's start information is used to position the cursor. So the range + /// usually spans more then the actual symbol's name and does normally include + /// things like visibility modifiers. /// - /// The range doesn't have to denote a node range in the - /// sense of a abstract syntax tree. It can therefore - /// not be used to re-construct a hierarchy of the - /// symbols. + /// The range doesn't have to denote a node range in the sense of a abstract + /// syntax tree. It can therefore not be used to re-construct a hierarchy of + /// the symbols. final Location location; /// The name of this symbol. @@ -5120,10 +7643,37 @@ obj.containsKey('name') && obj['name'] is String && obj.containsKey('kind') && - obj['kind'] is num && + SymbolKind.canParse(obj['kind']) && obj.containsKey('location') && Location.canParse(obj['location']); } + + @override + bool operator ==(other) { + if (other is SymbolInformation) { + return name == other.name && + kind == other.kind && + deprecated == other.deprecated && + location == other.location && + containerName == other.containerName && + true; + } + return false; + } + + @override + int get hashCode { + int hash = 0; + hash = JenkinsSmiHash.combine(hash, name.hashCode); + hash = JenkinsSmiHash.combine(hash, kind.hashCode); + hash = JenkinsSmiHash.combine(hash, deprecated.hashCode); + hash = JenkinsSmiHash.combine(hash, location.hashCode); + hash = JenkinsSmiHash.combine(hash, containerName.hashCode); + return JenkinsSmiHash.finish(hash); + } + + @override + String toString() => jsonEncoder.convert(toJson()); } /// A symbol kind. @@ -5131,7 +7681,7 @@ const SymbolKind._(this._value); const SymbolKind.fromJson(this._value); - final Object _value; + final num _value; static bool canParse(Object obj) { switch (obj) { @@ -5204,8 +7754,8 @@ bool operator ==(o) => o is SymbolKind && o._value == _value; } -/// Describe options to be used when registering for -/// text document change events. +/// Describe options to be used when registering for text document change +/// events. class TextDocumentChangeRegistrationOptions implements TextDocumentRegistrationOptions, ToJsonable { TextDocumentChangeRegistrationOptions(this.syncKind, this.documentSelector) { @@ -5213,24 +7763,22 @@ throw 'syncKind is required but was not provided'; } } - factory TextDocumentChangeRegistrationOptions.fromJson( + static TextDocumentChangeRegistrationOptions fromJson( Map<String, dynamic> json) { final syncKind = json['syncKind']; final documentSelector = json['documentSelector'] - ?.map((item) => item != null ? new DocumentFilter.fromJson(item) : null) + ?.map((item) => item != null ? DocumentFilter.fromJson(item) : null) ?.cast<DocumentFilter>() ?.toList(); return new TextDocumentChangeRegistrationOptions( syncKind, documentSelector); } - /// A document selector to identify the scope of the - /// registration. If set to null the document selector - /// provided on the client side will be used. + /// A document selector to identify the scope of the registration. If set to + /// null the document selector provided on the client side will be used. final List<DocumentFilter> documentSelector; - /// How documents are synced to the server. See - /// TextDocumentSyncKind.Full and + /// How documents are synced to the server. See TextDocumentSyncKind.Full and /// TextDocumentSyncKind.Incremental. final num syncKind; @@ -5252,35 +7800,1651 @@ obj['documentSelector'] .every((item) => DocumentFilter.canParse(item)))); } + + @override + bool operator ==(other) { + if (other is TextDocumentChangeRegistrationOptions) { + return syncKind == other.syncKind && + documentSelector == other.documentSelector && + true; + } + return false; + } + + @override + int get hashCode { + int hash = 0; + hash = JenkinsSmiHash.combine(hash, syncKind.hashCode); + hash = JenkinsSmiHash.combine(hash, documentSelector.hashCode); + return JenkinsSmiHash.finish(hash); + } + + @override + String toString() => jsonEncoder.convert(toJson()); } /// Text document specific client capabilities. class TextDocumentClientCapabilities implements ToJsonable { - TextDocumentClientCapabilities(this.dynamicRegistration, this.willSave, - this.willSaveWaitUntil, this.didSave); - factory TextDocumentClientCapabilities.fromJson(Map<String, dynamic> json) { + TextDocumentClientCapabilities( + this.synchronization, + this.completion, + this.hover, + this.signatureHelp, + this.references, + this.documentHighlight, + this.documentSymbol, + this.formatting, + this.rangeFormatting, + this.onTypeFormatting, + this.definition, + this.typeDefinition, + this.implementation, + this.codeAction, + this.codeLens, + this.documentLink, + this.colorProvider, + this.rename, + this.publishDiagnostics, + this.foldingRange); + static TextDocumentClientCapabilities fromJson(Map<String, dynamic> json) { + final synchronization = json['synchronization'] != null + ? TextDocumentClientCapabilitiesSynchronization.fromJson( + json['synchronization']) + : null; + final completion = json['completion'] != null + ? TextDocumentClientCapabilitiesCompletion.fromJson(json['completion']) + : null; + final hover = json['hover'] != null + ? TextDocumentClientCapabilitiesHover.fromJson(json['hover']) + : null; + final signatureHelp = json['signatureHelp'] != null + ? TextDocumentClientCapabilitiesSignatureHelp.fromJson( + json['signatureHelp']) + : null; + final references = json['references'] != null + ? TextDocumentClientCapabilitiesReferences.fromJson(json['references']) + : null; + final documentHighlight = json['documentHighlight'] != null + ? TextDocumentClientCapabilitiesDocumentHighlight.fromJson( + json['documentHighlight']) + : null; + final documentSymbol = json['documentSymbol'] != null + ? TextDocumentClientCapabilitiesDocumentSymbol.fromJson( + json['documentSymbol']) + : null; + final formatting = json['formatting'] != null + ? TextDocumentClientCapabilitiesFormatting.fromJson(json['formatting']) + : null; + final rangeFormatting = json['rangeFormatting'] != null + ? TextDocumentClientCapabilitiesRangeFormatting.fromJson( + json['rangeFormatting']) + : null; + final onTypeFormatting = json['onTypeFormatting'] != null + ? TextDocumentClientCapabilitiesOnTypeFormatting.fromJson( + json['onTypeFormatting']) + : null; + final definition = json['definition'] != null + ? TextDocumentClientCapabilitiesDefinition.fromJson(json['definition']) + : null; + final typeDefinition = json['typeDefinition'] != null + ? TextDocumentClientCapabilitiesTypeDefinition.fromJson( + json['typeDefinition']) + : null; + final implementation = json['implementation'] != null + ? TextDocumentClientCapabilitiesImplementation.fromJson( + json['implementation']) + : null; + final codeAction = json['codeAction'] != null + ? TextDocumentClientCapabilitiesCodeAction.fromJson(json['codeAction']) + : null; + final codeLens = json['codeLens'] != null + ? TextDocumentClientCapabilitiesCodeLens.fromJson(json['codeLens']) + : null; + final documentLink = json['documentLink'] != null + ? TextDocumentClientCapabilitiesDocumentLink.fromJson( + json['documentLink']) + : null; + final colorProvider = json['colorProvider'] != null + ? TextDocumentClientCapabilitiesColorProvider.fromJson( + json['colorProvider']) + : null; + final rename = json['rename'] != null + ? TextDocumentClientCapabilitiesRename.fromJson(json['rename']) + : null; + final publishDiagnostics = json['publishDiagnostics'] != null + ? TextDocumentClientCapabilitiesPublishDiagnostics.fromJson( + json['publishDiagnostics']) + : null; + final foldingRange = json['foldingRange'] != null + ? TextDocumentClientCapabilitiesFoldingRange.fromJson( + json['foldingRange']) + : null; + return new TextDocumentClientCapabilities( + synchronization, + completion, + hover, + signatureHelp, + references, + documentHighlight, + documentSymbol, + formatting, + rangeFormatting, + onTypeFormatting, + definition, + typeDefinition, + implementation, + codeAction, + codeLens, + documentLink, + colorProvider, + rename, + publishDiagnostics, + foldingRange); + } + + /// Capabilities specific to the `textDocument/codeAction` + final TextDocumentClientCapabilitiesCodeAction codeAction; + + /// Capabilities specific to the `textDocument/codeLens` + final TextDocumentClientCapabilitiesCodeLens codeLens; + + /// Capabilities specific to the `textDocument/documentColor` and the + /// `textDocument/colorPresentation` request. + /// + /// Since 3.6.0 + final TextDocumentClientCapabilitiesColorProvider colorProvider; + + /// Capabilities specific to the `textDocument/completion` + final TextDocumentClientCapabilitiesCompletion completion; + + /// Capabilities specific to the `textDocument/definition` + final TextDocumentClientCapabilitiesDefinition definition; + + /// Capabilities specific to the `textDocument/documentHighlight` + final TextDocumentClientCapabilitiesDocumentHighlight documentHighlight; + + /// Capabilities specific to the `textDocument/documentLink` + final TextDocumentClientCapabilitiesDocumentLink documentLink; + + /// Capabilities specific to the `textDocument/documentSymbol` + final TextDocumentClientCapabilitiesDocumentSymbol documentSymbol; + + /// Capabilities specific to `textDocument/foldingRange` requests. + /// + /// Since 3.10.0 + final TextDocumentClientCapabilitiesFoldingRange foldingRange; + + /// Capabilities specific to the `textDocument/formatting` + final TextDocumentClientCapabilitiesFormatting formatting; + + /// Capabilities specific to the `textDocument/hover` + final TextDocumentClientCapabilitiesHover hover; + + /// Capabilities specific to the `textDocument/implementation`. + /// + /// Since 3.6.0 + final TextDocumentClientCapabilitiesImplementation implementation; + + /// Capabilities specific to the `textDocument/onTypeFormatting` + final TextDocumentClientCapabilitiesOnTypeFormatting onTypeFormatting; + + /// Capabilities specific to `textDocument/publishDiagnostics`. + final TextDocumentClientCapabilitiesPublishDiagnostics publishDiagnostics; + + /// Capabilities specific to the `textDocument/rangeFormatting` + final TextDocumentClientCapabilitiesRangeFormatting rangeFormatting; + + /// Capabilities specific to the `textDocument/references` + final TextDocumentClientCapabilitiesReferences references; + + /// Capabilities specific to the `textDocument/rename` + final TextDocumentClientCapabilitiesRename rename; + + /// Capabilities specific to the `textDocument/signatureHelp` + final TextDocumentClientCapabilitiesSignatureHelp signatureHelp; + final TextDocumentClientCapabilitiesSynchronization synchronization; + + /// Capabilities specific to the `textDocument/typeDefinition` + /// + /// Since 3.6.0 + final TextDocumentClientCapabilitiesTypeDefinition typeDefinition; + + Map<String, dynamic> toJson() { + Map<String, dynamic> __result = {}; + if (synchronization != null) { + __result['synchronization'] = synchronization; + } + if (completion != null) { + __result['completion'] = completion; + } + if (hover != null) { + __result['hover'] = hover; + } + if (signatureHelp != null) { + __result['signatureHelp'] = signatureHelp; + } + if (references != null) { + __result['references'] = references; + } + if (documentHighlight != null) { + __result['documentHighlight'] = documentHighlight; + } + if (documentSymbol != null) { + __result['documentSymbol'] = documentSymbol; + } + if (formatting != null) { + __result['formatting'] = formatting; + } + if (rangeFormatting != null) { + __result['rangeFormatting'] = rangeFormatting; + } + if (onTypeFormatting != null) { + __result['onTypeFormatting'] = onTypeFormatting; + } + if (definition != null) { + __result['definition'] = definition; + } + if (typeDefinition != null) { + __result['typeDefinition'] = typeDefinition; + } + if (implementation != null) { + __result['implementation'] = implementation; + } + if (codeAction != null) { + __result['codeAction'] = codeAction; + } + if (codeLens != null) { + __result['codeLens'] = codeLens; + } + if (documentLink != null) { + __result['documentLink'] = documentLink; + } + if (colorProvider != null) { + __result['colorProvider'] = colorProvider; + } + if (rename != null) { + __result['rename'] = rename; + } + if (publishDiagnostics != null) { + __result['publishDiagnostics'] = publishDiagnostics; + } + if (foldingRange != null) { + __result['foldingRange'] = foldingRange; + } + return __result; + } + + static bool canParse(Object obj) { + return obj is Map<String, dynamic>; + } + + @override + bool operator ==(other) { + if (other is TextDocumentClientCapabilities) { + return synchronization == other.synchronization && + completion == other.completion && + hover == other.hover && + signatureHelp == other.signatureHelp && + references == other.references && + documentHighlight == other.documentHighlight && + documentSymbol == other.documentSymbol && + formatting == other.formatting && + rangeFormatting == other.rangeFormatting && + onTypeFormatting == other.onTypeFormatting && + definition == other.definition && + typeDefinition == other.typeDefinition && + implementation == other.implementation && + codeAction == other.codeAction && + codeLens == other.codeLens && + documentLink == other.documentLink && + colorProvider == other.colorProvider && + rename == other.rename && + publishDiagnostics == other.publishDiagnostics && + foldingRange == other.foldingRange && + true; + } + return false; + } + + @override + int get hashCode { + int hash = 0; + hash = JenkinsSmiHash.combine(hash, synchronization.hashCode); + hash = JenkinsSmiHash.combine(hash, completion.hashCode); + hash = JenkinsSmiHash.combine(hash, hover.hashCode); + hash = JenkinsSmiHash.combine(hash, signatureHelp.hashCode); + hash = JenkinsSmiHash.combine(hash, references.hashCode); + hash = JenkinsSmiHash.combine(hash, documentHighlight.hashCode); + hash = JenkinsSmiHash.combine(hash, documentSymbol.hashCode); + hash = JenkinsSmiHash.combine(hash, formatting.hashCode); + hash = JenkinsSmiHash.combine(hash, rangeFormatting.hashCode); + hash = JenkinsSmiHash.combine(hash, onTypeFormatting.hashCode); + hash = JenkinsSmiHash.combine(hash, definition.hashCode); + hash = JenkinsSmiHash.combine(hash, typeDefinition.hashCode); + hash = JenkinsSmiHash.combine(hash, implementation.hashCode); + hash = JenkinsSmiHash.combine(hash, codeAction.hashCode); + hash = JenkinsSmiHash.combine(hash, codeLens.hashCode); + hash = JenkinsSmiHash.combine(hash, documentLink.hashCode); + hash = JenkinsSmiHash.combine(hash, colorProvider.hashCode); + hash = JenkinsSmiHash.combine(hash, rename.hashCode); + hash = JenkinsSmiHash.combine(hash, publishDiagnostics.hashCode); + hash = JenkinsSmiHash.combine(hash, foldingRange.hashCode); + return JenkinsSmiHash.finish(hash); + } + + @override + String toString() => jsonEncoder.convert(toJson()); +} + +class TextDocumentClientCapabilitiesCodeAction implements ToJsonable { + TextDocumentClientCapabilitiesCodeAction( + this.dynamicRegistration, this.codeActionLiteralSupport); + static TextDocumentClientCapabilitiesCodeAction fromJson( + Map<String, dynamic> json) { + final dynamicRegistration = json['dynamicRegistration']; + final codeActionLiteralSupport = json['codeActionLiteralSupport'] != null + ? TextDocumentClientCapabilitiesCodeActionLiteralSupport.fromJson( + json['codeActionLiteralSupport']) + : null; + return new TextDocumentClientCapabilitiesCodeAction( + dynamicRegistration, codeActionLiteralSupport); + } + + /// The client support code action literals as a valid response of the + /// `textDocument/codeAction` request. + /// + /// Since 3.8.0 + final TextDocumentClientCapabilitiesCodeActionLiteralSupport + codeActionLiteralSupport; + + /// Whether code action supports dynamic registration. + final bool dynamicRegistration; + + Map<String, dynamic> toJson() { + Map<String, dynamic> __result = {}; + if (dynamicRegistration != null) { + __result['dynamicRegistration'] = dynamicRegistration; + } + if (codeActionLiteralSupport != null) { + __result['codeActionLiteralSupport'] = codeActionLiteralSupport; + } + return __result; + } + + static bool canParse(Object obj) { + return obj is Map<String, dynamic>; + } + + @override + bool operator ==(other) { + if (other is TextDocumentClientCapabilitiesCodeAction) { + return dynamicRegistration == other.dynamicRegistration && + codeActionLiteralSupport == other.codeActionLiteralSupport && + true; + } + return false; + } + + @override + int get hashCode { + int hash = 0; + hash = JenkinsSmiHash.combine(hash, dynamicRegistration.hashCode); + hash = JenkinsSmiHash.combine(hash, codeActionLiteralSupport.hashCode); + return JenkinsSmiHash.finish(hash); + } + + @override + String toString() => jsonEncoder.convert(toJson()); +} + +class TextDocumentClientCapabilitiesCodeActionKind implements ToJsonable { + TextDocumentClientCapabilitiesCodeActionKind(this.valueSet) { + if (valueSet == null) { + throw 'valueSet is required but was not provided'; + } + } + static TextDocumentClientCapabilitiesCodeActionKind fromJson( + Map<String, dynamic> json) { + final valueSet = json['valueSet'] + ?.map((item) => item != null ? CodeActionKind.fromJson(item) : null) + ?.cast<CodeActionKind>() + ?.toList(); + return new TextDocumentClientCapabilitiesCodeActionKind(valueSet); + } + + /// The code action kind values the client supports. When this property exists + /// the client also guarantees that it will handle values outside its set + /// gracefully and falls back to a default value when unknown. + final List<CodeActionKind> valueSet; + + Map<String, dynamic> toJson() { + Map<String, dynamic> __result = {}; + __result['valueSet'] = + valueSet ?? (throw 'valueSet is required but was not set'); + return __result; + } + + static bool canParse(Object obj) { + return obj is Map<String, dynamic> && + obj.containsKey('valueSet') && + (obj['valueSet'] is List && + (obj['valueSet'].length == 0 || + obj['valueSet'].every((item) => item is String))); + } + + @override + bool operator ==(other) { + if (other is TextDocumentClientCapabilitiesCodeActionKind) { + return listEqual(valueSet, other.valueSet, + (CodeActionKind a, CodeActionKind b) => a == b) && + true; + } + return false; + } + + @override + int get hashCode { + int hash = 0; + hash = JenkinsSmiHash.combine(hash, valueSet.hashCode); + return JenkinsSmiHash.finish(hash); + } + + @override + String toString() => jsonEncoder.convert(toJson()); +} + +class TextDocumentClientCapabilitiesCodeActionLiteralSupport + implements ToJsonable { + TextDocumentClientCapabilitiesCodeActionLiteralSupport(this.codeActionKind) { + if (codeActionKind == null) { + throw 'codeActionKind is required but was not provided'; + } + } + static TextDocumentClientCapabilitiesCodeActionLiteralSupport fromJson( + Map<String, dynamic> json) { + final codeActionKind = json['codeActionKind'] != null + ? TextDocumentClientCapabilitiesCodeActionKind.fromJson( + json['codeActionKind']) + : null; + return new TextDocumentClientCapabilitiesCodeActionLiteralSupport( + codeActionKind); + } + + /// The code action kind is support with the following value set. + final TextDocumentClientCapabilitiesCodeActionKind codeActionKind; + + Map<String, dynamic> toJson() { + Map<String, dynamic> __result = {}; + __result['codeActionKind'] = + codeActionKind ?? (throw 'codeActionKind is required but was not set'); + return __result; + } + + static bool canParse(Object obj) { + return obj is Map<String, dynamic> && + obj.containsKey('codeActionKind') && + TextDocumentClientCapabilitiesCodeActionKind.canParse( + obj['codeActionKind']); + } + + @override + bool operator ==(other) { + if (other is TextDocumentClientCapabilitiesCodeActionLiteralSupport) { + return codeActionKind == other.codeActionKind && true; + } + return false; + } + + @override + int get hashCode { + int hash = 0; + hash = JenkinsSmiHash.combine(hash, codeActionKind.hashCode); + return JenkinsSmiHash.finish(hash); + } + + @override + String toString() => jsonEncoder.convert(toJson()); +} + +class TextDocumentClientCapabilitiesCodeLens implements ToJsonable { + TextDocumentClientCapabilitiesCodeLens(this.dynamicRegistration); + static TextDocumentClientCapabilitiesCodeLens fromJson( + Map<String, dynamic> json) { + final dynamicRegistration = json['dynamicRegistration']; + return new TextDocumentClientCapabilitiesCodeLens(dynamicRegistration); + } + + /// Whether code lens supports dynamic registration. + final bool dynamicRegistration; + + Map<String, dynamic> toJson() { + Map<String, dynamic> __result = {}; + if (dynamicRegistration != null) { + __result['dynamicRegistration'] = dynamicRegistration; + } + return __result; + } + + static bool canParse(Object obj) { + return obj is Map<String, dynamic>; + } + + @override + bool operator ==(other) { + if (other is TextDocumentClientCapabilitiesCodeLens) { + return dynamicRegistration == other.dynamicRegistration && true; + } + return false; + } + + @override + int get hashCode { + int hash = 0; + hash = JenkinsSmiHash.combine(hash, dynamicRegistration.hashCode); + return JenkinsSmiHash.finish(hash); + } + + @override + String toString() => jsonEncoder.convert(toJson()); +} + +class TextDocumentClientCapabilitiesColorProvider implements ToJsonable { + TextDocumentClientCapabilitiesColorProvider(this.dynamicRegistration); + static TextDocumentClientCapabilitiesColorProvider fromJson( + Map<String, dynamic> json) { + final dynamicRegistration = json['dynamicRegistration']; + return new TextDocumentClientCapabilitiesColorProvider(dynamicRegistration); + } + + /// Whether colorProvider supports dynamic registration. If this is set to + /// `true` the client supports the new `(ColorProviderOptions & + /// TextDocumentRegistrationOptions & StaticRegistrationOptions)` return value + /// for the corresponding server capability as well. + final bool dynamicRegistration; + + Map<String, dynamic> toJson() { + Map<String, dynamic> __result = {}; + if (dynamicRegistration != null) { + __result['dynamicRegistration'] = dynamicRegistration; + } + return __result; + } + + static bool canParse(Object obj) { + return obj is Map<String, dynamic>; + } + + @override + bool operator ==(other) { + if (other is TextDocumentClientCapabilitiesColorProvider) { + return dynamicRegistration == other.dynamicRegistration && true; + } + return false; + } + + @override + int get hashCode { + int hash = 0; + hash = JenkinsSmiHash.combine(hash, dynamicRegistration.hashCode); + return JenkinsSmiHash.finish(hash); + } + + @override + String toString() => jsonEncoder.convert(toJson()); +} + +class TextDocumentClientCapabilitiesCompletion implements ToJsonable { + TextDocumentClientCapabilitiesCompletion(this.dynamicRegistration, + this.completionItem, this.completionItemKind, this.contextSupport); + static TextDocumentClientCapabilitiesCompletion fromJson( + Map<String, dynamic> json) { + final dynamicRegistration = json['dynamicRegistration']; + final completionItem = json['completionItem'] != null + ? TextDocumentClientCapabilitiesCompletionItem.fromJson( + json['completionItem']) + : null; + final completionItemKind = json['completionItemKind'] != null + ? TextDocumentClientCapabilitiesCompletionItemKind.fromJson( + json['completionItemKind']) + : null; + final contextSupport = json['contextSupport']; + return new TextDocumentClientCapabilitiesCompletion(dynamicRegistration, + completionItem, completionItemKind, contextSupport); + } + + /// The client supports the following `CompletionItem` specific capabilities. + final TextDocumentClientCapabilitiesCompletionItem completionItem; + final TextDocumentClientCapabilitiesCompletionItemKind completionItemKind; + + /// The client supports to send additional context information for a + /// `textDocument/completion` request. + final bool contextSupport; + + /// Whether completion supports dynamic registration. + final bool dynamicRegistration; + + Map<String, dynamic> toJson() { + Map<String, dynamic> __result = {}; + if (dynamicRegistration != null) { + __result['dynamicRegistration'] = dynamicRegistration; + } + if (completionItem != null) { + __result['completionItem'] = completionItem; + } + if (completionItemKind != null) { + __result['completionItemKind'] = completionItemKind; + } + if (contextSupport != null) { + __result['contextSupport'] = contextSupport; + } + return __result; + } + + static bool canParse(Object obj) { + return obj is Map<String, dynamic>; + } + + @override + bool operator ==(other) { + if (other is TextDocumentClientCapabilitiesCompletion) { + return dynamicRegistration == other.dynamicRegistration && + completionItem == other.completionItem && + completionItemKind == other.completionItemKind && + contextSupport == other.contextSupport && + true; + } + return false; + } + + @override + int get hashCode { + int hash = 0; + hash = JenkinsSmiHash.combine(hash, dynamicRegistration.hashCode); + hash = JenkinsSmiHash.combine(hash, completionItem.hashCode); + hash = JenkinsSmiHash.combine(hash, completionItemKind.hashCode); + hash = JenkinsSmiHash.combine(hash, contextSupport.hashCode); + return JenkinsSmiHash.finish(hash); + } + + @override + String toString() => jsonEncoder.convert(toJson()); +} + +class TextDocumentClientCapabilitiesCompletionItem implements ToJsonable { + TextDocumentClientCapabilitiesCompletionItem( + this.snippetSupport, + this.commitCharactersSupport, + this.documentationFormat, + this.deprecatedSupport, + this.preselectSupport); + static TextDocumentClientCapabilitiesCompletionItem fromJson( + Map<String, dynamic> json) { + final snippetSupport = json['snippetSupport']; + final commitCharactersSupport = json['commitCharactersSupport']; + final documentationFormat = json['documentationFormat'] + ?.map((item) => item != null ? MarkupKind.fromJson(item) : null) + ?.cast<MarkupKind>() + ?.toList(); + final deprecatedSupport = json['deprecatedSupport']; + final preselectSupport = json['preselectSupport']; + return new TextDocumentClientCapabilitiesCompletionItem( + snippetSupport, + commitCharactersSupport, + documentationFormat, + deprecatedSupport, + preselectSupport); + } + + /// The client supports commit characters on a completion item. + final bool commitCharactersSupport; + + /// The client supports the deprecated property on a completion item. + final bool deprecatedSupport; + + /// The client supports the following content formats for the documentation + /// property. The order describes the preferred format of the client. + final List<MarkupKind> documentationFormat; + + /// The client supports the preselect property on a completion item. + final bool preselectSupport; + + /// The client supports snippets as insert text. + /// + /// A snippet can define tab stops and placeholders with `$1`, `$2` and + /// `${3:foo}`. `$0` defines the final tab stop, it defaults to the end of the + /// snippet. Placeholders with equal identifiers are linked, that is typing in + /// one will update others too. + final bool snippetSupport; + + Map<String, dynamic> toJson() { + Map<String, dynamic> __result = {}; + if (snippetSupport != null) { + __result['snippetSupport'] = snippetSupport; + } + if (commitCharactersSupport != null) { + __result['commitCharactersSupport'] = commitCharactersSupport; + } + if (documentationFormat != null) { + __result['documentationFormat'] = documentationFormat; + } + if (deprecatedSupport != null) { + __result['deprecatedSupport'] = deprecatedSupport; + } + if (preselectSupport != null) { + __result['preselectSupport'] = preselectSupport; + } + return __result; + } + + static bool canParse(Object obj) { + return obj is Map<String, dynamic>; + } + + @override + bool operator ==(other) { + if (other is TextDocumentClientCapabilitiesCompletionItem) { + return snippetSupport == other.snippetSupport && + commitCharactersSupport == other.commitCharactersSupport && + listEqual(documentationFormat, other.documentationFormat, + (MarkupKind a, MarkupKind b) => a == b) && + deprecatedSupport == other.deprecatedSupport && + preselectSupport == other.preselectSupport && + true; + } + return false; + } + + @override + int get hashCode { + int hash = 0; + hash = JenkinsSmiHash.combine(hash, snippetSupport.hashCode); + hash = JenkinsSmiHash.combine(hash, commitCharactersSupport.hashCode); + hash = JenkinsSmiHash.combine(hash, documentationFormat.hashCode); + hash = JenkinsSmiHash.combine(hash, deprecatedSupport.hashCode); + hash = JenkinsSmiHash.combine(hash, preselectSupport.hashCode); + return JenkinsSmiHash.finish(hash); + } + + @override + String toString() => jsonEncoder.convert(toJson()); +} + +class TextDocumentClientCapabilitiesCompletionItemKind implements ToJsonable { + TextDocumentClientCapabilitiesCompletionItemKind(this.valueSet); + static TextDocumentClientCapabilitiesCompletionItemKind fromJson( + Map<String, dynamic> json) { + final valueSet = json['valueSet'] + ?.map((item) => item != null ? CompletionItemKind.fromJson(item) : null) + ?.cast<CompletionItemKind>() + ?.toList(); + return new TextDocumentClientCapabilitiesCompletionItemKind(valueSet); + } + + /// The completion item kind values the client supports. When this property + /// exists the client also guarantees that it will handle values outside its + /// set gracefully and falls back to a default value when unknown. + /// + /// If this property is not present the client only supports the completion + /// items kinds from `Text` to `Reference` as defined in the initial version + /// of the protocol. + final List<CompletionItemKind> valueSet; + + Map<String, dynamic> toJson() { + Map<String, dynamic> __result = {}; + if (valueSet != null) { + __result['valueSet'] = valueSet; + } + return __result; + } + + static bool canParse(Object obj) { + return obj is Map<String, dynamic>; + } + + @override + bool operator ==(other) { + if (other is TextDocumentClientCapabilitiesCompletionItemKind) { + return listEqual(valueSet, other.valueSet, + (CompletionItemKind a, CompletionItemKind b) => a == b) && + true; + } + return false; + } + + @override + int get hashCode { + int hash = 0; + hash = JenkinsSmiHash.combine(hash, valueSet.hashCode); + return JenkinsSmiHash.finish(hash); + } + + @override + String toString() => jsonEncoder.convert(toJson()); +} + +class TextDocumentClientCapabilitiesDefinition implements ToJsonable { + TextDocumentClientCapabilitiesDefinition(this.dynamicRegistration); + static TextDocumentClientCapabilitiesDefinition fromJson( + Map<String, dynamic> json) { + final dynamicRegistration = json['dynamicRegistration']; + return new TextDocumentClientCapabilitiesDefinition(dynamicRegistration); + } + + /// Whether definition supports dynamic registration. + final bool dynamicRegistration; + + Map<String, dynamic> toJson() { + Map<String, dynamic> __result = {}; + if (dynamicRegistration != null) { + __result['dynamicRegistration'] = dynamicRegistration; + } + return __result; + } + + static bool canParse(Object obj) { + return obj is Map<String, dynamic>; + } + + @override + bool operator ==(other) { + if (other is TextDocumentClientCapabilitiesDefinition) { + return dynamicRegistration == other.dynamicRegistration && true; + } + return false; + } + + @override + int get hashCode { + int hash = 0; + hash = JenkinsSmiHash.combine(hash, dynamicRegistration.hashCode); + return JenkinsSmiHash.finish(hash); + } + + @override + String toString() => jsonEncoder.convert(toJson()); +} + +class TextDocumentClientCapabilitiesDocumentHighlight implements ToJsonable { + TextDocumentClientCapabilitiesDocumentHighlight(this.dynamicRegistration); + static TextDocumentClientCapabilitiesDocumentHighlight fromJson( + Map<String, dynamic> json) { + final dynamicRegistration = json['dynamicRegistration']; + return new TextDocumentClientCapabilitiesDocumentHighlight( + dynamicRegistration); + } + + /// Whether document highlight supports dynamic registration. + final bool dynamicRegistration; + + Map<String, dynamic> toJson() { + Map<String, dynamic> __result = {}; + if (dynamicRegistration != null) { + __result['dynamicRegistration'] = dynamicRegistration; + } + return __result; + } + + static bool canParse(Object obj) { + return obj is Map<String, dynamic>; + } + + @override + bool operator ==(other) { + if (other is TextDocumentClientCapabilitiesDocumentHighlight) { + return dynamicRegistration == other.dynamicRegistration && true; + } + return false; + } + + @override + int get hashCode { + int hash = 0; + hash = JenkinsSmiHash.combine(hash, dynamicRegistration.hashCode); + return JenkinsSmiHash.finish(hash); + } + + @override + String toString() => jsonEncoder.convert(toJson()); +} + +class TextDocumentClientCapabilitiesDocumentLink implements ToJsonable { + TextDocumentClientCapabilitiesDocumentLink(this.dynamicRegistration); + static TextDocumentClientCapabilitiesDocumentLink fromJson( + Map<String, dynamic> json) { + final dynamicRegistration = json['dynamicRegistration']; + return new TextDocumentClientCapabilitiesDocumentLink(dynamicRegistration); + } + + /// Whether document link supports dynamic registration. + final bool dynamicRegistration; + + Map<String, dynamic> toJson() { + Map<String, dynamic> __result = {}; + if (dynamicRegistration != null) { + __result['dynamicRegistration'] = dynamicRegistration; + } + return __result; + } + + static bool canParse(Object obj) { + return obj is Map<String, dynamic>; + } + + @override + bool operator ==(other) { + if (other is TextDocumentClientCapabilitiesDocumentLink) { + return dynamicRegistration == other.dynamicRegistration && true; + } + return false; + } + + @override + int get hashCode { + int hash = 0; + hash = JenkinsSmiHash.combine(hash, dynamicRegistration.hashCode); + return JenkinsSmiHash.finish(hash); + } + + @override + String toString() => jsonEncoder.convert(toJson()); +} + +class TextDocumentClientCapabilitiesDocumentSymbol implements ToJsonable { + TextDocumentClientCapabilitiesDocumentSymbol(this.dynamicRegistration, + this.symbolKind, this.hierarchicalDocumentSymbolSupport); + static TextDocumentClientCapabilitiesDocumentSymbol fromJson( + Map<String, dynamic> json) { + final dynamicRegistration = json['dynamicRegistration']; + final symbolKind = json['symbolKind'] != null + ? TextDocumentClientCapabilitiesSymbolKind.fromJson(json['symbolKind']) + : null; + final hierarchicalDocumentSymbolSupport = + json['hierarchicalDocumentSymbolSupport']; + return new TextDocumentClientCapabilitiesDocumentSymbol( + dynamicRegistration, symbolKind, hierarchicalDocumentSymbolSupport); + } + + /// Whether document symbol supports dynamic registration. + final bool dynamicRegistration; + + /// The client supports hierarchical document symbols. + final bool hierarchicalDocumentSymbolSupport; + + /// Specific capabilities for the `SymbolKind`. + final TextDocumentClientCapabilitiesSymbolKind symbolKind; + + Map<String, dynamic> toJson() { + Map<String, dynamic> __result = {}; + if (dynamicRegistration != null) { + __result['dynamicRegistration'] = dynamicRegistration; + } + if (symbolKind != null) { + __result['symbolKind'] = symbolKind; + } + if (hierarchicalDocumentSymbolSupport != null) { + __result['hierarchicalDocumentSymbolSupport'] = + hierarchicalDocumentSymbolSupport; + } + return __result; + } + + static bool canParse(Object obj) { + return obj is Map<String, dynamic>; + } + + @override + bool operator ==(other) { + if (other is TextDocumentClientCapabilitiesDocumentSymbol) { + return dynamicRegistration == other.dynamicRegistration && + symbolKind == other.symbolKind && + hierarchicalDocumentSymbolSupport == + other.hierarchicalDocumentSymbolSupport && + true; + } + return false; + } + + @override + int get hashCode { + int hash = 0; + hash = JenkinsSmiHash.combine(hash, dynamicRegistration.hashCode); + hash = JenkinsSmiHash.combine(hash, symbolKind.hashCode); + hash = JenkinsSmiHash.combine( + hash, hierarchicalDocumentSymbolSupport.hashCode); + return JenkinsSmiHash.finish(hash); + } + + @override + String toString() => jsonEncoder.convert(toJson()); +} + +class TextDocumentClientCapabilitiesFoldingRange implements ToJsonable { + TextDocumentClientCapabilitiesFoldingRange( + this.dynamicRegistration, this.rangeLimit, this.lineFoldingOnly); + static TextDocumentClientCapabilitiesFoldingRange fromJson( + Map<String, dynamic> json) { + final dynamicRegistration = json['dynamicRegistration']; + final rangeLimit = json['rangeLimit']; + final lineFoldingOnly = json['lineFoldingOnly']; + return new TextDocumentClientCapabilitiesFoldingRange( + dynamicRegistration, rangeLimit, lineFoldingOnly); + } + + /// Whether implementation supports dynamic registration for folding range + /// providers. If this is set to `true` the client supports the new + /// `(FoldingRangeProviderOptions & TextDocumentRegistrationOptions & + /// StaticRegistrationOptions)` return value for the corresponding server + /// capability as well. + final bool dynamicRegistration; + + /// If set, the client signals that it only supports folding complete lines. + /// If set, client will ignore specified `startCharacter` and `endCharacter` + /// properties in a FoldingRange. + final bool lineFoldingOnly; + + /// The maximum number of folding ranges that the client prefers to receive + /// per document. The value serves as a hint, servers are free to follow the + /// limit. + final num rangeLimit; + + Map<String, dynamic> toJson() { + Map<String, dynamic> __result = {}; + if (dynamicRegistration != null) { + __result['dynamicRegistration'] = dynamicRegistration; + } + if (rangeLimit != null) { + __result['rangeLimit'] = rangeLimit; + } + if (lineFoldingOnly != null) { + __result['lineFoldingOnly'] = lineFoldingOnly; + } + return __result; + } + + static bool canParse(Object obj) { + return obj is Map<String, dynamic>; + } + + @override + bool operator ==(other) { + if (other is TextDocumentClientCapabilitiesFoldingRange) { + return dynamicRegistration == other.dynamicRegistration && + rangeLimit == other.rangeLimit && + lineFoldingOnly == other.lineFoldingOnly && + true; + } + return false; + } + + @override + int get hashCode { + int hash = 0; + hash = JenkinsSmiHash.combine(hash, dynamicRegistration.hashCode); + hash = JenkinsSmiHash.combine(hash, rangeLimit.hashCode); + hash = JenkinsSmiHash.combine(hash, lineFoldingOnly.hashCode); + return JenkinsSmiHash.finish(hash); + } + + @override + String toString() => jsonEncoder.convert(toJson()); +} + +class TextDocumentClientCapabilitiesFormatting implements ToJsonable { + TextDocumentClientCapabilitiesFormatting(this.dynamicRegistration); + static TextDocumentClientCapabilitiesFormatting fromJson( + Map<String, dynamic> json) { + final dynamicRegistration = json['dynamicRegistration']; + return new TextDocumentClientCapabilitiesFormatting(dynamicRegistration); + } + + /// Whether formatting supports dynamic registration. + final bool dynamicRegistration; + + Map<String, dynamic> toJson() { + Map<String, dynamic> __result = {}; + if (dynamicRegistration != null) { + __result['dynamicRegistration'] = dynamicRegistration; + } + return __result; + } + + static bool canParse(Object obj) { + return obj is Map<String, dynamic>; + } + + @override + bool operator ==(other) { + if (other is TextDocumentClientCapabilitiesFormatting) { + return dynamicRegistration == other.dynamicRegistration && true; + } + return false; + } + + @override + int get hashCode { + int hash = 0; + hash = JenkinsSmiHash.combine(hash, dynamicRegistration.hashCode); + return JenkinsSmiHash.finish(hash); + } + + @override + String toString() => jsonEncoder.convert(toJson()); +} + +class TextDocumentClientCapabilitiesHover implements ToJsonable { + TextDocumentClientCapabilitiesHover( + this.dynamicRegistration, this.contentFormat); + static TextDocumentClientCapabilitiesHover fromJson( + Map<String, dynamic> json) { + final dynamicRegistration = json['dynamicRegistration']; + final contentFormat = json['contentFormat'] + ?.map((item) => item != null ? MarkupKind.fromJson(item) : null) + ?.cast<MarkupKind>() + ?.toList(); + return new TextDocumentClientCapabilitiesHover( + dynamicRegistration, contentFormat); + } + + /// The client supports the follow content formats for the content property. + /// The order describes the preferred format of the client. + final List<MarkupKind> contentFormat; + + /// Whether hover supports dynamic registration. + final bool dynamicRegistration; + + Map<String, dynamic> toJson() { + Map<String, dynamic> __result = {}; + if (dynamicRegistration != null) { + __result['dynamicRegistration'] = dynamicRegistration; + } + if (contentFormat != null) { + __result['contentFormat'] = contentFormat; + } + return __result; + } + + static bool canParse(Object obj) { + return obj is Map<String, dynamic>; + } + + @override + bool operator ==(other) { + if (other is TextDocumentClientCapabilitiesHover) { + return dynamicRegistration == other.dynamicRegistration && + listEqual(contentFormat, other.contentFormat, + (MarkupKind a, MarkupKind b) => a == b) && + true; + } + return false; + } + + @override + int get hashCode { + int hash = 0; + hash = JenkinsSmiHash.combine(hash, dynamicRegistration.hashCode); + hash = JenkinsSmiHash.combine(hash, contentFormat.hashCode); + return JenkinsSmiHash.finish(hash); + } + + @override + String toString() => jsonEncoder.convert(toJson()); +} + +class TextDocumentClientCapabilitiesImplementation implements ToJsonable { + TextDocumentClientCapabilitiesImplementation(this.dynamicRegistration); + static TextDocumentClientCapabilitiesImplementation fromJson( + Map<String, dynamic> json) { + final dynamicRegistration = json['dynamicRegistration']; + return new TextDocumentClientCapabilitiesImplementation( + dynamicRegistration); + } + + /// Whether implementation supports dynamic registration. If this is set to + /// `true` the client supports the new `(TextDocumentRegistrationOptions & + /// StaticRegistrationOptions)` return value for the corresponding server + /// capability as well. + final bool dynamicRegistration; + + Map<String, dynamic> toJson() { + Map<String, dynamic> __result = {}; + if (dynamicRegistration != null) { + __result['dynamicRegistration'] = dynamicRegistration; + } + return __result; + } + + static bool canParse(Object obj) { + return obj is Map<String, dynamic>; + } + + @override + bool operator ==(other) { + if (other is TextDocumentClientCapabilitiesImplementation) { + return dynamicRegistration == other.dynamicRegistration && true; + } + return false; + } + + @override + int get hashCode { + int hash = 0; + hash = JenkinsSmiHash.combine(hash, dynamicRegistration.hashCode); + return JenkinsSmiHash.finish(hash); + } + + @override + String toString() => jsonEncoder.convert(toJson()); +} + +class TextDocumentClientCapabilitiesOnTypeFormatting implements ToJsonable { + TextDocumentClientCapabilitiesOnTypeFormatting(this.dynamicRegistration); + static TextDocumentClientCapabilitiesOnTypeFormatting fromJson( + Map<String, dynamic> json) { + final dynamicRegistration = json['dynamicRegistration']; + return new TextDocumentClientCapabilitiesOnTypeFormatting( + dynamicRegistration); + } + + /// Whether on type formatting supports dynamic registration. + final bool dynamicRegistration; + + Map<String, dynamic> toJson() { + Map<String, dynamic> __result = {}; + if (dynamicRegistration != null) { + __result['dynamicRegistration'] = dynamicRegistration; + } + return __result; + } + + static bool canParse(Object obj) { + return obj is Map<String, dynamic>; + } + + @override + bool operator ==(other) { + if (other is TextDocumentClientCapabilitiesOnTypeFormatting) { + return dynamicRegistration == other.dynamicRegistration && true; + } + return false; + } + + @override + int get hashCode { + int hash = 0; + hash = JenkinsSmiHash.combine(hash, dynamicRegistration.hashCode); + return JenkinsSmiHash.finish(hash); + } + + @override + String toString() => jsonEncoder.convert(toJson()); +} + +class TextDocumentClientCapabilitiesPublishDiagnostics implements ToJsonable { + TextDocumentClientCapabilitiesPublishDiagnostics(this.relatedInformation); + static TextDocumentClientCapabilitiesPublishDiagnostics fromJson( + Map<String, dynamic> json) { + final relatedInformation = json['relatedInformation']; + return new TextDocumentClientCapabilitiesPublishDiagnostics( + relatedInformation); + } + + /// Whether the clients accepts diagnostics with related information. + final bool relatedInformation; + + Map<String, dynamic> toJson() { + Map<String, dynamic> __result = {}; + if (relatedInformation != null) { + __result['relatedInformation'] = relatedInformation; + } + return __result; + } + + static bool canParse(Object obj) { + return obj is Map<String, dynamic>; + } + + @override + bool operator ==(other) { + if (other is TextDocumentClientCapabilitiesPublishDiagnostics) { + return relatedInformation == other.relatedInformation && true; + } + return false; + } + + @override + int get hashCode { + int hash = 0; + hash = JenkinsSmiHash.combine(hash, relatedInformation.hashCode); + return JenkinsSmiHash.finish(hash); + } + + @override + String toString() => jsonEncoder.convert(toJson()); +} + +class TextDocumentClientCapabilitiesRangeFormatting implements ToJsonable { + TextDocumentClientCapabilitiesRangeFormatting(this.dynamicRegistration); + static TextDocumentClientCapabilitiesRangeFormatting fromJson( + Map<String, dynamic> json) { + final dynamicRegistration = json['dynamicRegistration']; + return new TextDocumentClientCapabilitiesRangeFormatting( + dynamicRegistration); + } + + /// Whether range formatting supports dynamic registration. + final bool dynamicRegistration; + + Map<String, dynamic> toJson() { + Map<String, dynamic> __result = {}; + if (dynamicRegistration != null) { + __result['dynamicRegistration'] = dynamicRegistration; + } + return __result; + } + + static bool canParse(Object obj) { + return obj is Map<String, dynamic>; + } + + @override + bool operator ==(other) { + if (other is TextDocumentClientCapabilitiesRangeFormatting) { + return dynamicRegistration == other.dynamicRegistration && true; + } + return false; + } + + @override + int get hashCode { + int hash = 0; + hash = JenkinsSmiHash.combine(hash, dynamicRegistration.hashCode); + return JenkinsSmiHash.finish(hash); + } + + @override + String toString() => jsonEncoder.convert(toJson()); +} + +class TextDocumentClientCapabilitiesReferences implements ToJsonable { + TextDocumentClientCapabilitiesReferences(this.dynamicRegistration); + static TextDocumentClientCapabilitiesReferences fromJson( + Map<String, dynamic> json) { + final dynamicRegistration = json['dynamicRegistration']; + return new TextDocumentClientCapabilitiesReferences(dynamicRegistration); + } + + /// Whether references supports dynamic registration. + final bool dynamicRegistration; + + Map<String, dynamic> toJson() { + Map<String, dynamic> __result = {}; + if (dynamicRegistration != null) { + __result['dynamicRegistration'] = dynamicRegistration; + } + return __result; + } + + static bool canParse(Object obj) { + return obj is Map<String, dynamic>; + } + + @override + bool operator ==(other) { + if (other is TextDocumentClientCapabilitiesReferences) { + return dynamicRegistration == other.dynamicRegistration && true; + } + return false; + } + + @override + int get hashCode { + int hash = 0; + hash = JenkinsSmiHash.combine(hash, dynamicRegistration.hashCode); + return JenkinsSmiHash.finish(hash); + } + + @override + String toString() => jsonEncoder.convert(toJson()); +} + +class TextDocumentClientCapabilitiesRename implements ToJsonable { + TextDocumentClientCapabilitiesRename( + this.dynamicRegistration, this.prepareSupport); + static TextDocumentClientCapabilitiesRename fromJson( + Map<String, dynamic> json) { + final dynamicRegistration = json['dynamicRegistration']; + final prepareSupport = json['prepareSupport']; + return new TextDocumentClientCapabilitiesRename( + dynamicRegistration, prepareSupport); + } + + /// Whether rename supports dynamic registration. + final bool dynamicRegistration; + + /// The client supports testing for validity of rename operations before + /// execution. + final bool prepareSupport; + + Map<String, dynamic> toJson() { + Map<String, dynamic> __result = {}; + if (dynamicRegistration != null) { + __result['dynamicRegistration'] = dynamicRegistration; + } + if (prepareSupport != null) { + __result['prepareSupport'] = prepareSupport; + } + return __result; + } + + static bool canParse(Object obj) { + return obj is Map<String, dynamic>; + } + + @override + bool operator ==(other) { + if (other is TextDocumentClientCapabilitiesRename) { + return dynamicRegistration == other.dynamicRegistration && + prepareSupport == other.prepareSupport && + true; + } + return false; + } + + @override + int get hashCode { + int hash = 0; + hash = JenkinsSmiHash.combine(hash, dynamicRegistration.hashCode); + hash = JenkinsSmiHash.combine(hash, prepareSupport.hashCode); + return JenkinsSmiHash.finish(hash); + } + + @override + String toString() => jsonEncoder.convert(toJson()); +} + +class TextDocumentClientCapabilitiesSignatureHelp implements ToJsonable { + TextDocumentClientCapabilitiesSignatureHelp( + this.dynamicRegistration, this.signatureInformation); + static TextDocumentClientCapabilitiesSignatureHelp fromJson( + Map<String, dynamic> json) { + final dynamicRegistration = json['dynamicRegistration']; + final signatureInformation = json['signatureInformation'] != null + ? TextDocumentClientCapabilitiesSignatureInformation.fromJson( + json['signatureInformation']) + : null; + return new TextDocumentClientCapabilitiesSignatureHelp( + dynamicRegistration, signatureInformation); + } + + /// Whether signature help supports dynamic registration. + final bool dynamicRegistration; + + /// The client supports the following `SignatureInformation` specific + /// properties. + final TextDocumentClientCapabilitiesSignatureInformation signatureInformation; + + Map<String, dynamic> toJson() { + Map<String, dynamic> __result = {}; + if (dynamicRegistration != null) { + __result['dynamicRegistration'] = dynamicRegistration; + } + if (signatureInformation != null) { + __result['signatureInformation'] = signatureInformation; + } + return __result; + } + + static bool canParse(Object obj) { + return obj is Map<String, dynamic>; + } + + @override + bool operator ==(other) { + if (other is TextDocumentClientCapabilitiesSignatureHelp) { + return dynamicRegistration == other.dynamicRegistration && + signatureInformation == other.signatureInformation && + true; + } + return false; + } + + @override + int get hashCode { + int hash = 0; + hash = JenkinsSmiHash.combine(hash, dynamicRegistration.hashCode); + hash = JenkinsSmiHash.combine(hash, signatureInformation.hashCode); + return JenkinsSmiHash.finish(hash); + } + + @override + String toString() => jsonEncoder.convert(toJson()); +} + +class TextDocumentClientCapabilitiesSignatureInformation implements ToJsonable { + TextDocumentClientCapabilitiesSignatureInformation(this.documentationFormat); + static TextDocumentClientCapabilitiesSignatureInformation fromJson( + Map<String, dynamic> json) { + final documentationFormat = json['documentationFormat'] + ?.map((item) => item != null ? MarkupKind.fromJson(item) : null) + ?.cast<MarkupKind>() + ?.toList(); + return new TextDocumentClientCapabilitiesSignatureInformation( + documentationFormat); + } + + /// The client supports the follow content formats for the documentation + /// property. The order describes the preferred format of the client. + final List<MarkupKind> documentationFormat; + + Map<String, dynamic> toJson() { + Map<String, dynamic> __result = {}; + if (documentationFormat != null) { + __result['documentationFormat'] = documentationFormat; + } + return __result; + } + + static bool canParse(Object obj) { + return obj is Map<String, dynamic>; + } + + @override + bool operator ==(other) { + if (other is TextDocumentClientCapabilitiesSignatureInformation) { + return listEqual(documentationFormat, other.documentationFormat, + (MarkupKind a, MarkupKind b) => a == b) && + true; + } + return false; + } + + @override + int get hashCode { + int hash = 0; + hash = JenkinsSmiHash.combine(hash, documentationFormat.hashCode); + return JenkinsSmiHash.finish(hash); + } + + @override + String toString() => jsonEncoder.convert(toJson()); +} + +class TextDocumentClientCapabilitiesSymbolKind implements ToJsonable { + TextDocumentClientCapabilitiesSymbolKind(this.valueSet); + static TextDocumentClientCapabilitiesSymbolKind fromJson( + Map<String, dynamic> json) { + final valueSet = json['valueSet'] + ?.map((item) => item != null ? SymbolKind.fromJson(item) : null) + ?.cast<SymbolKind>() + ?.toList(); + return new TextDocumentClientCapabilitiesSymbolKind(valueSet); + } + + /// The symbol kind values the client supports. When this property exists the + /// client also guarantees that it will handle values outside its set + /// gracefully and falls back to a default value when unknown. + /// + /// If this property is not present the client only supports the symbol kinds + /// from `File` to `Array` as defined in the initial version of the protocol. + final List<SymbolKind> valueSet; + + Map<String, dynamic> toJson() { + Map<String, dynamic> __result = {}; + if (valueSet != null) { + __result['valueSet'] = valueSet; + } + return __result; + } + + static bool canParse(Object obj) { + return obj is Map<String, dynamic>; + } + + @override + bool operator ==(other) { + if (other is TextDocumentClientCapabilitiesSymbolKind) { + return listEqual(valueSet, other.valueSet, + (SymbolKind a, SymbolKind b) => a == b) && + true; + } + return false; + } + + @override + int get hashCode { + int hash = 0; + hash = JenkinsSmiHash.combine(hash, valueSet.hashCode); + return JenkinsSmiHash.finish(hash); + } + + @override + String toString() => jsonEncoder.convert(toJson()); +} + +class TextDocumentClientCapabilitiesSynchronization implements ToJsonable { + TextDocumentClientCapabilitiesSynchronization(this.dynamicRegistration, + this.willSave, this.willSaveWaitUntil, this.didSave); + static TextDocumentClientCapabilitiesSynchronization fromJson( + Map<String, dynamic> json) { final dynamicRegistration = json['dynamicRegistration']; final willSave = json['willSave']; final willSaveWaitUntil = json['willSaveWaitUntil']; final didSave = json['didSave']; - return new TextDocumentClientCapabilities( + return new TextDocumentClientCapabilitiesSynchronization( dynamicRegistration, willSave, willSaveWaitUntil, didSave); } /// The client supports did save notifications. final bool didSave; - /// Whether text document synchronization supports - /// dynamic registration. + /// Whether text document synchronization supports dynamic registration. final bool dynamicRegistration; - /// The client supports sending will save - /// notifications. + /// The client supports sending will save notifications. final bool willSave; - /// The client supports sending a will save request - /// and waits for a response providing text edits - /// which will be applied to the document before it is + /// The client supports sending a will save request and waits for a response + /// providing text edits which will be applied to the document before it is /// saved. final bool willSaveWaitUntil; @@ -5304,20 +9468,90 @@ static bool canParse(Object obj) { return obj is Map<String, dynamic>; } + + @override + bool operator ==(other) { + if (other is TextDocumentClientCapabilitiesSynchronization) { + return dynamicRegistration == other.dynamicRegistration && + willSave == other.willSave && + willSaveWaitUntil == other.willSaveWaitUntil && + didSave == other.didSave && + true; + } + return false; + } + + @override + int get hashCode { + int hash = 0; + hash = JenkinsSmiHash.combine(hash, dynamicRegistration.hashCode); + hash = JenkinsSmiHash.combine(hash, willSave.hashCode); + hash = JenkinsSmiHash.combine(hash, willSaveWaitUntil.hashCode); + hash = JenkinsSmiHash.combine(hash, didSave.hashCode); + return JenkinsSmiHash.finish(hash); + } + + @override + String toString() => jsonEncoder.convert(toJson()); } -/// An event describing a change to a text document. If -/// range and rangeLength are omitted the new text is -/// considered to be the full content of the document. +class TextDocumentClientCapabilitiesTypeDefinition implements ToJsonable { + TextDocumentClientCapabilitiesTypeDefinition(this.dynamicRegistration); + static TextDocumentClientCapabilitiesTypeDefinition fromJson( + Map<String, dynamic> json) { + final dynamicRegistration = json['dynamicRegistration']; + return new TextDocumentClientCapabilitiesTypeDefinition( + dynamicRegistration); + } + + /// Whether typeDefinition supports dynamic registration. If this is set to + /// `true` the client supports the new `(TextDocumentRegistrationOptions & + /// StaticRegistrationOptions)` return value for the corresponding server + /// capability as well. + final bool dynamicRegistration; + + Map<String, dynamic> toJson() { + Map<String, dynamic> __result = {}; + if (dynamicRegistration != null) { + __result['dynamicRegistration'] = dynamicRegistration; + } + return __result; + } + + static bool canParse(Object obj) { + return obj is Map<String, dynamic>; + } + + @override + bool operator ==(other) { + if (other is TextDocumentClientCapabilitiesTypeDefinition) { + return dynamicRegistration == other.dynamicRegistration && true; + } + return false; + } + + @override + int get hashCode { + int hash = 0; + hash = JenkinsSmiHash.combine(hash, dynamicRegistration.hashCode); + return JenkinsSmiHash.finish(hash); + } + + @override + String toString() => jsonEncoder.convert(toJson()); +} + +/// An event describing a change to a text document. If range and rangeLength +/// are omitted the new text is considered to be the full content of the +/// document. class TextDocumentContentChangeEvent implements ToJsonable { TextDocumentContentChangeEvent(this.range, this.rangeLength, this.text) { if (text == null) { throw 'text is required but was not provided'; } } - factory TextDocumentContentChangeEvent.fromJson(Map<String, dynamic> json) { - final range = - json['range'] != null ? new Range.fromJson(json['range']) : null; + static TextDocumentContentChangeEvent fromJson(Map<String, dynamic> json) { + final range = json['range'] != null ? Range.fromJson(json['range']) : null; final rangeLength = json['rangeLength']; final text = json['text']; return new TextDocumentContentChangeEvent(range, rangeLength, text); @@ -5349,9 +9583,32 @@ obj.containsKey('text') && obj['text'] is String; } + + @override + bool operator ==(other) { + if (other is TextDocumentContentChangeEvent) { + return range == other.range && + rangeLength == other.rangeLength && + text == other.text && + true; + } + return false; + } + + @override + int get hashCode { + int hash = 0; + hash = JenkinsSmiHash.combine(hash, range.hashCode); + hash = JenkinsSmiHash.combine(hash, rangeLength.hashCode); + hash = JenkinsSmiHash.combine(hash, text.hashCode); + return JenkinsSmiHash.finish(hash); + } + + @override + String toString() => jsonEncoder.convert(toJson()); } -class TextDocumentEdit implements FileOperation, ToJsonable { +class TextDocumentEdit implements ToJsonable { TextDocumentEdit(this.textDocument, this.edits) { if (textDocument == null) { throw 'textDocument is required but was not provided'; @@ -5360,12 +9617,12 @@ throw 'edits is required but was not provided'; } } - factory TextDocumentEdit.fromJson(Map<String, dynamic> json) { + static TextDocumentEdit fromJson(Map<String, dynamic> json) { final textDocument = json['textDocument'] != null - ? new VersionedTextDocumentIdentifier.fromJson(json['textDocument']) + ? VersionedTextDocumentIdentifier.fromJson(json['textDocument']) : null; final edits = json['edits'] - ?.map((item) => item != null ? new TextEdit.fromJson(item) : null) + ?.map((item) => item != null ? TextEdit.fromJson(item) : null) ?.cast<TextEdit>() ?.toList(); return new TextDocumentEdit(textDocument, edits); @@ -5394,6 +9651,27 @@ (obj['edits'].length == 0 || obj['edits'].every((item) => TextEdit.canParse(item)))); } + + @override + bool operator ==(other) { + if (other is TextDocumentEdit) { + return textDocument == other.textDocument && + listEqual(edits, other.edits, (TextEdit a, TextEdit b) => a == b) && + true; + } + return false; + } + + @override + int get hashCode { + int hash = 0; + hash = JenkinsSmiHash.combine(hash, textDocument.hashCode); + hash = JenkinsSmiHash.combine(hash, edits.hashCode); + return JenkinsSmiHash.finish(hash); + } + + @override + String toString() => jsonEncoder.convert(toJson()); } class TextDocumentIdentifier implements ToJsonable { @@ -5402,7 +9680,7 @@ throw 'uri is required but was not provided'; } } - factory TextDocumentIdentifier.fromJson(Map<String, dynamic> json) { + static TextDocumentIdentifier fromJson(Map<String, dynamic> json) { final uri = json['uri']; return new TextDocumentIdentifier(uri); } @@ -5421,6 +9699,24 @@ obj.containsKey('uri') && obj['uri'] is String; } + + @override + bool operator ==(other) { + if (other is TextDocumentIdentifier) { + return uri == other.uri && true; + } + return false; + } + + @override + int get hashCode { + int hash = 0; + hash = JenkinsSmiHash.combine(hash, uri.hashCode); + return JenkinsSmiHash.finish(hash); + } + + @override + String toString() => jsonEncoder.convert(toJson()); } class TextDocumentItem implements ToJsonable { @@ -5438,7 +9734,7 @@ throw 'text is required but was not provided'; } } - factory TextDocumentItem.fromJson(Map<String, dynamic> json) { + static TextDocumentItem fromJson(Map<String, dynamic> json) { final uri = json['uri']; final languageId = json['languageId']; final version = json['version']; @@ -5455,8 +9751,8 @@ /// The text document's URI. final String uri; - /// The version number of this document (it will - /// increase after each change, including undo/redo). + /// The version number of this document (it will increase after each change, + /// including undo/redo). final num version; Map<String, dynamic> toJson() { @@ -5481,6 +9777,31 @@ obj.containsKey('text') && obj['text'] is String; } + + @override + bool operator ==(other) { + if (other is TextDocumentItem) { + return uri == other.uri && + languageId == other.languageId && + version == other.version && + text == other.text && + true; + } + return false; + } + + @override + int get hashCode { + int hash = 0; + hash = JenkinsSmiHash.combine(hash, uri.hashCode); + hash = JenkinsSmiHash.combine(hash, languageId.hashCode); + hash = JenkinsSmiHash.combine(hash, version.hashCode); + hash = JenkinsSmiHash.combine(hash, text.hashCode); + return JenkinsSmiHash.finish(hash); + } + + @override + String toString() => jsonEncoder.convert(toJson()); } class TextDocumentPositionParams implements ToJsonable { @@ -5492,13 +9813,12 @@ throw 'position is required but was not provided'; } } - factory TextDocumentPositionParams.fromJson(Map<String, dynamic> json) { + static TextDocumentPositionParams fromJson(Map<String, dynamic> json) { final textDocument = json['textDocument'] != null - ? new TextDocumentIdentifier.fromJson(json['textDocument']) + ? TextDocumentIdentifier.fromJson(json['textDocument']) : null; - final position = json['position'] != null - ? new Position.fromJson(json['position']) - : null; + final position = + json['position'] != null ? Position.fromJson(json['position']) : null; return new TextDocumentPositionParams(textDocument, position); } @@ -5524,21 +9844,41 @@ obj.containsKey('position') && Position.canParse(obj['position']); } + + @override + bool operator ==(other) { + if (other is TextDocumentPositionParams) { + return textDocument == other.textDocument && + position == other.position && + true; + } + return false; + } + + @override + int get hashCode { + int hash = 0; + hash = JenkinsSmiHash.combine(hash, textDocument.hashCode); + hash = JenkinsSmiHash.combine(hash, position.hashCode); + return JenkinsSmiHash.finish(hash); + } + + @override + String toString() => jsonEncoder.convert(toJson()); } class TextDocumentRegistrationOptions implements ToJsonable { TextDocumentRegistrationOptions(this.documentSelector); - factory TextDocumentRegistrationOptions.fromJson(Map<String, dynamic> json) { + static TextDocumentRegistrationOptions fromJson(Map<String, dynamic> json) { final documentSelector = json['documentSelector'] - ?.map((item) => item != null ? new DocumentFilter.fromJson(item) : null) + ?.map((item) => item != null ? DocumentFilter.fromJson(item) : null) ?.cast<DocumentFilter>() ?.toList(); return new TextDocumentRegistrationOptions(documentSelector); } - /// A document selector to identify the scope of the - /// registration. If set to null the document selector - /// provided on the client side will be used. + /// A document selector to identify the scope of the registration. If set to + /// null the document selector provided on the client side will be used. final List<DocumentFilter> documentSelector; Map<String, dynamic> toJson() { @@ -5555,6 +9895,24 @@ obj['documentSelector'] .every((item) => DocumentFilter.canParse(item)))); } + + @override + bool operator ==(other) { + if (other is TextDocumentRegistrationOptions) { + return documentSelector == other.documentSelector && true; + } + return false; + } + + @override + int get hashCode { + int hash = 0; + hash = JenkinsSmiHash.combine(hash, documentSelector.hashCode); + return JenkinsSmiHash.finish(hash); + } + + @override + String toString() => jsonEncoder.convert(toJson()); } /// Represents reasons why a text document is saved. @@ -5562,7 +9920,7 @@ const TextDocumentSaveReason._(this._value); const TextDocumentSaveReason.fromJson(this._value); - final Object _value; + final num _value; static bool canParse(Object obj) { switch (obj) { @@ -5574,8 +9932,8 @@ return false; } - /// Manually triggered, e.g. by the user pressing - /// save, by starting debugging, or by an API call. + /// Manually triggered, e.g. by the user pressing save, by starting debugging, + /// or by an API call. static const Manual = const TextDocumentSaveReason._(1); /// Automatic after a delay. @@ -5598,25 +9956,22 @@ class TextDocumentSaveRegistrationOptions implements TextDocumentRegistrationOptions, ToJsonable { TextDocumentSaveRegistrationOptions(this.includeText, this.documentSelector); - factory TextDocumentSaveRegistrationOptions.fromJson( + static TextDocumentSaveRegistrationOptions fromJson( Map<String, dynamic> json) { final includeText = json['includeText']; final documentSelector = json['documentSelector'] - ?.map((item) => item != null ? new DocumentFilter.fromJson(item) : null) + ?.map((item) => item != null ? DocumentFilter.fromJson(item) : null) ?.cast<DocumentFilter>() ?.toList(); return new TextDocumentSaveRegistrationOptions( includeText, documentSelector); } - /// A document selector to identify the scope of the - /// registration. If set to null the document - /// selector provided on the client side will be - /// used. + /// A document selector to identify the scope of the registration. If set to + /// null the document selector provided on the client side will be used. final List<DocumentFilter> documentSelector; - /// The client is supposed to include the content on - /// save. + /// The client is supposed to include the content on save. final bool includeText; Map<String, dynamic> toJson() { @@ -5636,15 +9991,36 @@ obj['documentSelector'] .every((item) => DocumentFilter.canParse(item)))); } + + @override + bool operator ==(other) { + if (other is TextDocumentSaveRegistrationOptions) { + return includeText == other.includeText && + documentSelector == other.documentSelector && + true; + } + return false; + } + + @override + int get hashCode { + int hash = 0; + hash = JenkinsSmiHash.combine(hash, includeText.hashCode); + hash = JenkinsSmiHash.combine(hash, documentSelector.hashCode); + return JenkinsSmiHash.finish(hash); + } + + @override + String toString() => jsonEncoder.convert(toJson()); } -/// Defines how the host (editor) should sync document -/// changes to the language server. +/// Defines how the host (editor) should sync document changes to the language +/// server. class TextDocumentSyncKind { const TextDocumentSyncKind._(this._value); const TextDocumentSyncKind.fromJson(this._value); - final Object _value; + final num _value; static bool canParse(Object obj) { switch (obj) { @@ -5659,13 +10035,11 @@ /// Documents should not be synced at all. static const None = const TextDocumentSyncKind._(0); - /// Documents are synced by always sending the - /// full content of the document. + /// Documents are synced by always sending the full content of the document. static const Full = const TextDocumentSyncKind._(1); - /// Documents are synced by sending the full - /// content on open. After that only incremental - /// updates to the document are send. + /// Documents are synced by sending the full content on open. After that only + /// incremental updates to the document are send. static const Incremental = const TextDocumentSyncKind._(2); Object toJson() => _value; @@ -5682,39 +10056,35 @@ class TextDocumentSyncOptions implements ToJsonable { TextDocumentSyncOptions(this.openClose, this.change, this.willSave, this.willSaveWaitUntil, this.save); - factory TextDocumentSyncOptions.fromJson(Map<String, dynamic> json) { + static TextDocumentSyncOptions fromJson(Map<String, dynamic> json) { final openClose = json['openClose']; final change = json['change'] != null - ? new TextDocumentSyncKind.fromJson(json['change']) + ? TextDocumentSyncKind.fromJson(json['change']) : null; final willSave = json['willSave']; final willSaveWaitUntil = json['willSaveWaitUntil']; final save = - json['save'] != null ? new SaveOptions.fromJson(json['save']) : null; + json['save'] != null ? SaveOptions.fromJson(json['save']) : null; return new TextDocumentSyncOptions( openClose, change, willSave, willSaveWaitUntil, save); } - /// Change notifications are sent to the server. - /// See TextDocumentSyncKind.None, - /// TextDocumentSyncKind.Full and - /// TextDocumentSyncKind.Incremental. If omitted - /// it defaults to TextDocumentSyncKind.None. + /// Change notifications are sent to the server. See + /// TextDocumentSyncKind.None, TextDocumentSyncKind.Full and + /// TextDocumentSyncKind.Incremental. If omitted it defaults to + /// TextDocumentSyncKind.None. final TextDocumentSyncKind change; - /// Open and close notifications are sent to the - /// server. + /// Open and close notifications are sent to the server. final bool openClose; /// Save notifications are sent to the server. final SaveOptions save; - /// Will save notifications are sent to the - /// server. + /// Will save notifications are sent to the server. final bool willSave; - /// Will save wait until requests are sent to the - /// server. + /// Will save wait until requests are sent to the server. final bool willSaveWaitUntil; Map<String, dynamic> toJson() { @@ -5740,6 +10110,33 @@ static bool canParse(Object obj) { return obj is Map<String, dynamic>; } + + @override + bool operator ==(other) { + if (other is TextDocumentSyncOptions) { + return openClose == other.openClose && + change == other.change && + willSave == other.willSave && + willSaveWaitUntil == other.willSaveWaitUntil && + save == other.save && + true; + } + return false; + } + + @override + int get hashCode { + int hash = 0; + hash = JenkinsSmiHash.combine(hash, openClose.hashCode); + hash = JenkinsSmiHash.combine(hash, change.hashCode); + hash = JenkinsSmiHash.combine(hash, willSave.hashCode); + hash = JenkinsSmiHash.combine(hash, willSaveWaitUntil.hashCode); + hash = JenkinsSmiHash.combine(hash, save.hashCode); + return JenkinsSmiHash.finish(hash); + } + + @override + String toString() => jsonEncoder.convert(toJson()); } class TextEdit implements ToJsonable { @@ -5751,20 +10148,17 @@ throw 'newText is required but was not provided'; } } - factory TextEdit.fromJson(Map<String, dynamic> json) { - final range = - json['range'] != null ? new Range.fromJson(json['range']) : null; + static TextEdit fromJson(Map<String, dynamic> json) { + final range = json['range'] != null ? Range.fromJson(json['range']) : null; final newText = json['newText']; return new TextEdit(range, newText); } - /// The string to be inserted. For delete - /// operations use an empty string. + /// The string to be inserted. For delete operations use an empty string. final String newText; - /// The range of the text document to be - /// manipulated. To insert text into a document - /// create a range where start === end. + /// The range of the text document to be manipulated. To insert text into a + /// document create a range where start === end. final Range range; Map<String, dynamic> toJson() { @@ -5782,6 +10176,25 @@ obj.containsKey('newText') && obj['newText'] is String; } + + @override + bool operator ==(other) { + if (other is TextEdit) { + return range == other.range && newText == other.newText && true; + } + return false; + } + + @override + int get hashCode { + int hash = 0; + hash = JenkinsSmiHash.combine(hash, range.hashCode); + hash = JenkinsSmiHash.combine(hash, newText.hashCode); + return JenkinsSmiHash.finish(hash); + } + + @override + String toString() => jsonEncoder.convert(toJson()); } /// General parameters to unregister a capability. @@ -5794,15 +10207,14 @@ throw 'method is required but was not provided'; } } - factory Unregistration.fromJson(Map<String, dynamic> json) { + static Unregistration fromJson(Map<String, dynamic> json) { final id = json['id']; final method = json['method']; return new Unregistration(id, method); } - /// The id used to unregister the request or - /// notification. Usually an id provided during - /// the register request. + /// The id used to unregister the request or notification. Usually an id + /// provided during the register request. final String id; /// The method / capability to unregister for. @@ -5822,6 +10234,25 @@ obj.containsKey('method') && obj['method'] is String; } + + @override + bool operator ==(other) { + if (other is Unregistration) { + return id == other.id && method == other.method && true; + } + return false; + } + + @override + int get hashCode { + int hash = 0; + hash = JenkinsSmiHash.combine(hash, id.hashCode); + hash = JenkinsSmiHash.combine(hash, method.hashCode); + return JenkinsSmiHash.finish(hash); + } + + @override + String toString() => jsonEncoder.convert(toJson()); } class UnregistrationParams implements ToJsonable { @@ -5830,9 +10261,9 @@ throw 'unregisterations is required but was not provided'; } } - factory UnregistrationParams.fromJson(Map<String, dynamic> json) { + static UnregistrationParams fromJson(Map<String, dynamic> json) { final unregisterations = json['unregisterations'] - ?.map((item) => item != null ? new Unregistration.fromJson(item) : null) + ?.map((item) => item != null ? Unregistration.fromJson(item) : null) ?.cast<Unregistration>() ?.toList(); return new UnregistrationParams(unregisterations); @@ -5855,6 +10286,26 @@ obj['unregisterations'] .every((item) => Unregistration.canParse(item)))); } + + @override + bool operator ==(other) { + if (other is UnregistrationParams) { + return listEqual(unregisterations, other.unregisterations, + (Unregistration a, Unregistration b) => a == b) && + true; + } + return false; + } + + @override + int get hashCode { + int hash = 0; + hash = JenkinsSmiHash.combine(hash, unregisterations.hashCode); + return JenkinsSmiHash.finish(hash); + } + + @override + String toString() => jsonEncoder.convert(toJson()); } class VersionedTextDocumentIdentifier @@ -5864,7 +10315,7 @@ throw 'uri is required but was not provided'; } } - factory VersionedTextDocumentIdentifier.fromJson(Map<String, dynamic> json) { + static VersionedTextDocumentIdentifier fromJson(Map<String, dynamic> json) { final version = json['version']; final uri = json['uri']; return new VersionedTextDocumentIdentifier(version, uri); @@ -5873,19 +10324,14 @@ /// The text document's URI. final String uri; - /// The version number of this document. If a - /// versioned text document identifier is sent - /// from the server to the client and the file is - /// not open in the editor (the server has not - /// received an open notification before) the - /// server can send `null` to indicate that the - /// version is known and the content on disk is - /// the truth (as speced with document content - /// ownership). + /// The version number of this document. If a versioned text document + /// identifier is sent from the server to the client and the file is not open + /// in the editor (the server has not received an open notification before) + /// the server can send `null` to indicate that the version is known and the + /// content on disk is the truth (as speced with document content ownership). /// - /// The version number of a document will increase - /// after each change, including undo/redo. The - /// number doesn't need to be consecutive. + /// The version number of a document will increase after each change, + /// including undo/redo. The number doesn't need to be consecutive. final num version; Map<String, dynamic> toJson() { @@ -5902,13 +10348,32 @@ obj.containsKey('uri') && obj['uri'] is String; } + + @override + bool operator ==(other) { + if (other is VersionedTextDocumentIdentifier) { + return version == other.version && uri == other.uri && true; + } + return false; + } + + @override + int get hashCode { + int hash = 0; + hash = JenkinsSmiHash.combine(hash, version.hashCode); + hash = JenkinsSmiHash.combine(hash, uri.hashCode); + return JenkinsSmiHash.finish(hash); + } + + @override + String toString() => jsonEncoder.convert(toJson()); } class WatchKind { const WatchKind._(this._value); const WatchKind.fromJson(this._value); - final Object _value; + final num _value; static bool canParse(Object obj) { switch (obj) { @@ -5940,8 +10405,7 @@ bool operator ==(o) => o is WatchKind && o._value == _value; } -/// The parameters send in a will save text -/// document notification. +/// The parameters send in a will save text document notification. class WillSaveTextDocumentParams implements ToJsonable { WillSaveTextDocumentParams(this.textDocument, this.reason) { if (textDocument == null) { @@ -5951,9 +10415,9 @@ throw 'reason is required but was not provided'; } } - factory WillSaveTextDocumentParams.fromJson(Map<String, dynamic> json) { + static WillSaveTextDocumentParams fromJson(Map<String, dynamic> json) { final textDocument = json['textDocument'] != null - ? new TextDocumentIdentifier.fromJson(json['textDocument']) + ? TextDocumentIdentifier.fromJson(json['textDocument']) : null; final reason = json['reason']; return new WillSaveTextDocumentParams(textDocument, reason); @@ -5980,50 +10444,439 @@ obj.containsKey('reason') && obj['reason'] is num; } + + @override + bool operator ==(other) { + if (other is WillSaveTextDocumentParams) { + return textDocument == other.textDocument && + reason == other.reason && + true; + } + return false; + } + + @override + int get hashCode { + int hash = 0; + hash = JenkinsSmiHash.combine(hash, textDocument.hashCode); + hash = JenkinsSmiHash.combine(hash, reason.hashCode); + return JenkinsSmiHash.finish(hash); + } + + @override + String toString() => jsonEncoder.convert(toJson()); } /// Workspace specific client capabilities. class WorkspaceClientCapabilities implements ToJsonable { - WorkspaceClientCapabilities(this.applyEdit, this.documentChanges, - this.resourceOperations, this.failureHandling); - factory WorkspaceClientCapabilities.fromJson(Map<String, dynamic> json) { + WorkspaceClientCapabilities( + this.applyEdit, + this.workspaceEdit, + this.didChangeConfiguration, + this.didChangeWatchedFiles, + this.symbol, + this.executeCommand, + this.workspaceFolders, + this.configuration); + static WorkspaceClientCapabilities fromJson(Map<String, dynamic> json) { final applyEdit = json['applyEdit']; - final documentChanges = json['documentChanges']; - final resourceOperations = json['resourceOperations'] - ?.map((item) => - item != null ? new ResourceOperationKind.fromJson(item) : null) - ?.cast<ResourceOperationKind>() - ?.toList(); - final failureHandling = json['failureHandling'] != null - ? new FailureHandlingKind.fromJson(json['failureHandling']) + final workspaceEdit = json['workspaceEdit'] != null + ? WorkspaceClientCapabilitiesWorkspaceEdit.fromJson( + json['workspaceEdit']) : null; + final didChangeConfiguration = json['didChangeConfiguration'] != null + ? WorkspaceClientCapabilitiesDidChangeConfiguration.fromJson( + json['didChangeConfiguration']) + : null; + final didChangeWatchedFiles = json['didChangeWatchedFiles'] != null + ? WorkspaceClientCapabilitiesDidChangeWatchedFiles.fromJson( + json['didChangeWatchedFiles']) + : null; + final symbol = json['symbol'] != null + ? WorkspaceClientCapabilitiesSymbol.fromJson(json['symbol']) + : null; + final executeCommand = json['executeCommand'] != null + ? WorkspaceClientCapabilitiesExecuteCommand.fromJson( + json['executeCommand']) + : null; + final workspaceFolders = json['workspaceFolders']; + final configuration = json['configuration']; return new WorkspaceClientCapabilities( - applyEdit, documentChanges, resourceOperations, failureHandling); + applyEdit, + workspaceEdit, + didChangeConfiguration, + didChangeWatchedFiles, + symbol, + executeCommand, + workspaceFolders, + configuration); } - /// The client supports applying batch edits to - /// the workspace by supporting the request - /// 'workspace/applyEdit' + /// The client supports applying batch edits to the workspace by supporting + /// the request 'workspace/applyEdit' final bool applyEdit; - /// The client supports versioned document - /// changes in `WorkspaceEdit`s - final bool documentChanges; + /// The client supports `workspace/configuration` requests. + /// + /// Since 3.6.0 + final bool configuration; - /// The failure handling strategy of a client if - /// applying the workspace edit failes. - final FailureHandlingKind failureHandling; + /// Capabilities specific to the `workspace/didChangeConfiguration` + /// notification. + final WorkspaceClientCapabilitiesDidChangeConfiguration + didChangeConfiguration; - /// The resource operations the client supports. - /// Clients should at least support 'create', - /// 'rename' and 'delete' files and folders. - final List<ResourceOperationKind> resourceOperations; + /// Capabilities specific to the `workspace/didChangeWatchedFiles` + /// notification. + final WorkspaceClientCapabilitiesDidChangeWatchedFiles didChangeWatchedFiles; + + /// Capabilities specific to the `workspace/executeCommand` request. + final WorkspaceClientCapabilitiesExecuteCommand executeCommand; + + /// Capabilities specific to the `workspace/symbol` request. + final WorkspaceClientCapabilitiesSymbol symbol; + + /// Capabilities specific to `WorkspaceEdit`s + final WorkspaceClientCapabilitiesWorkspaceEdit workspaceEdit; + + /// The client has support for workspace folders. + /// + /// Since 3.6.0 + final bool workspaceFolders; Map<String, dynamic> toJson() { Map<String, dynamic> __result = {}; if (applyEdit != null) { __result['applyEdit'] = applyEdit; } + if (workspaceEdit != null) { + __result['workspaceEdit'] = workspaceEdit; + } + if (didChangeConfiguration != null) { + __result['didChangeConfiguration'] = didChangeConfiguration; + } + if (didChangeWatchedFiles != null) { + __result['didChangeWatchedFiles'] = didChangeWatchedFiles; + } + if (symbol != null) { + __result['symbol'] = symbol; + } + if (executeCommand != null) { + __result['executeCommand'] = executeCommand; + } + if (workspaceFolders != null) { + __result['workspaceFolders'] = workspaceFolders; + } + if (configuration != null) { + __result['configuration'] = configuration; + } + return __result; + } + + static bool canParse(Object obj) { + return obj is Map<String, dynamic>; + } + + @override + bool operator ==(other) { + if (other is WorkspaceClientCapabilities) { + return applyEdit == other.applyEdit && + workspaceEdit == other.workspaceEdit && + didChangeConfiguration == other.didChangeConfiguration && + didChangeWatchedFiles == other.didChangeWatchedFiles && + symbol == other.symbol && + executeCommand == other.executeCommand && + workspaceFolders == other.workspaceFolders && + configuration == other.configuration && + true; + } + return false; + } + + @override + int get hashCode { + int hash = 0; + hash = JenkinsSmiHash.combine(hash, applyEdit.hashCode); + hash = JenkinsSmiHash.combine(hash, workspaceEdit.hashCode); + hash = JenkinsSmiHash.combine(hash, didChangeConfiguration.hashCode); + hash = JenkinsSmiHash.combine(hash, didChangeWatchedFiles.hashCode); + hash = JenkinsSmiHash.combine(hash, symbol.hashCode); + hash = JenkinsSmiHash.combine(hash, executeCommand.hashCode); + hash = JenkinsSmiHash.combine(hash, workspaceFolders.hashCode); + hash = JenkinsSmiHash.combine(hash, configuration.hashCode); + return JenkinsSmiHash.finish(hash); + } + + @override + String toString() => jsonEncoder.convert(toJson()); +} + +class WorkspaceClientCapabilitiesDidChangeConfiguration implements ToJsonable { + WorkspaceClientCapabilitiesDidChangeConfiguration(this.dynamicRegistration); + static WorkspaceClientCapabilitiesDidChangeConfiguration fromJson( + Map<String, dynamic> json) { + final dynamicRegistration = json['dynamicRegistration']; + return new WorkspaceClientCapabilitiesDidChangeConfiguration( + dynamicRegistration); + } + + /// Did change configuration notification supports dynamic registration. + final bool dynamicRegistration; + + Map<String, dynamic> toJson() { + Map<String, dynamic> __result = {}; + if (dynamicRegistration != null) { + __result['dynamicRegistration'] = dynamicRegistration; + } + return __result; + } + + static bool canParse(Object obj) { + return obj is Map<String, dynamic>; + } + + @override + bool operator ==(other) { + if (other is WorkspaceClientCapabilitiesDidChangeConfiguration) { + return dynamicRegistration == other.dynamicRegistration && true; + } + return false; + } + + @override + int get hashCode { + int hash = 0; + hash = JenkinsSmiHash.combine(hash, dynamicRegistration.hashCode); + return JenkinsSmiHash.finish(hash); + } + + @override + String toString() => jsonEncoder.convert(toJson()); +} + +class WorkspaceClientCapabilitiesDidChangeWatchedFiles implements ToJsonable { + WorkspaceClientCapabilitiesDidChangeWatchedFiles(this.dynamicRegistration); + static WorkspaceClientCapabilitiesDidChangeWatchedFiles fromJson( + Map<String, dynamic> json) { + final dynamicRegistration = json['dynamicRegistration']; + return new WorkspaceClientCapabilitiesDidChangeWatchedFiles( + dynamicRegistration); + } + + /// Did change watched files notification supports dynamic registration. + final bool dynamicRegistration; + + Map<String, dynamic> toJson() { + Map<String, dynamic> __result = {}; + if (dynamicRegistration != null) { + __result['dynamicRegistration'] = dynamicRegistration; + } + return __result; + } + + static bool canParse(Object obj) { + return obj is Map<String, dynamic>; + } + + @override + bool operator ==(other) { + if (other is WorkspaceClientCapabilitiesDidChangeWatchedFiles) { + return dynamicRegistration == other.dynamicRegistration && true; + } + return false; + } + + @override + int get hashCode { + int hash = 0; + hash = JenkinsSmiHash.combine(hash, dynamicRegistration.hashCode); + return JenkinsSmiHash.finish(hash); + } + + @override + String toString() => jsonEncoder.convert(toJson()); +} + +class WorkspaceClientCapabilitiesExecuteCommand implements ToJsonable { + WorkspaceClientCapabilitiesExecuteCommand(this.dynamicRegistration); + static WorkspaceClientCapabilitiesExecuteCommand fromJson( + Map<String, dynamic> json) { + final dynamicRegistration = json['dynamicRegistration']; + return new WorkspaceClientCapabilitiesExecuteCommand(dynamicRegistration); + } + + /// Execute command supports dynamic registration. + final bool dynamicRegistration; + + Map<String, dynamic> toJson() { + Map<String, dynamic> __result = {}; + if (dynamicRegistration != null) { + __result['dynamicRegistration'] = dynamicRegistration; + } + return __result; + } + + static bool canParse(Object obj) { + return obj is Map<String, dynamic>; + } + + @override + bool operator ==(other) { + if (other is WorkspaceClientCapabilitiesExecuteCommand) { + return dynamicRegistration == other.dynamicRegistration && true; + } + return false; + } + + @override + int get hashCode { + int hash = 0; + hash = JenkinsSmiHash.combine(hash, dynamicRegistration.hashCode); + return JenkinsSmiHash.finish(hash); + } + + @override + String toString() => jsonEncoder.convert(toJson()); +} + +class WorkspaceClientCapabilitiesSymbol implements ToJsonable { + WorkspaceClientCapabilitiesSymbol(this.dynamicRegistration, this.symbolKind); + static WorkspaceClientCapabilitiesSymbol fromJson(Map<String, dynamic> json) { + final dynamicRegistration = json['dynamicRegistration']; + final symbolKind = json['symbolKind'] != null + ? WorkspaceClientCapabilitiesSymbolKind.fromJson(json['symbolKind']) + : null; + return new WorkspaceClientCapabilitiesSymbol( + dynamicRegistration, symbolKind); + } + + /// Symbol request supports dynamic registration. + final bool dynamicRegistration; + + /// Specific capabilities for the `SymbolKind` in the `workspace/symbol` + /// request. + final WorkspaceClientCapabilitiesSymbolKind symbolKind; + + Map<String, dynamic> toJson() { + Map<String, dynamic> __result = {}; + if (dynamicRegistration != null) { + __result['dynamicRegistration'] = dynamicRegistration; + } + if (symbolKind != null) { + __result['symbolKind'] = symbolKind; + } + return __result; + } + + static bool canParse(Object obj) { + return obj is Map<String, dynamic>; + } + + @override + bool operator ==(other) { + if (other is WorkspaceClientCapabilitiesSymbol) { + return dynamicRegistration == other.dynamicRegistration && + symbolKind == other.symbolKind && + true; + } + return false; + } + + @override + int get hashCode { + int hash = 0; + hash = JenkinsSmiHash.combine(hash, dynamicRegistration.hashCode); + hash = JenkinsSmiHash.combine(hash, symbolKind.hashCode); + return JenkinsSmiHash.finish(hash); + } + + @override + String toString() => jsonEncoder.convert(toJson()); +} + +class WorkspaceClientCapabilitiesSymbolKind implements ToJsonable { + WorkspaceClientCapabilitiesSymbolKind(this.valueSet); + static WorkspaceClientCapabilitiesSymbolKind fromJson( + Map<String, dynamic> json) { + final valueSet = json['valueSet'] + ?.map((item) => item != null ? SymbolKind.fromJson(item) : null) + ?.cast<SymbolKind>() + ?.toList(); + return new WorkspaceClientCapabilitiesSymbolKind(valueSet); + } + + /// The symbol kind values the client supports. When this property exists the + /// client also guarantees that it will handle values outside its set + /// gracefully and falls back to a default value when unknown. + /// + /// If this property is not present the client only supports the symbol kinds + /// from `File` to `Array` as defined in the initial version of the protocol. + final List<SymbolKind> valueSet; + + Map<String, dynamic> toJson() { + Map<String, dynamic> __result = {}; + if (valueSet != null) { + __result['valueSet'] = valueSet; + } + return __result; + } + + static bool canParse(Object obj) { + return obj is Map<String, dynamic>; + } + + @override + bool operator ==(other) { + if (other is WorkspaceClientCapabilitiesSymbolKind) { + return listEqual(valueSet, other.valueSet, + (SymbolKind a, SymbolKind b) => a == b) && + true; + } + return false; + } + + @override + int get hashCode { + int hash = 0; + hash = JenkinsSmiHash.combine(hash, valueSet.hashCode); + return JenkinsSmiHash.finish(hash); + } + + @override + String toString() => jsonEncoder.convert(toJson()); +} + +class WorkspaceClientCapabilitiesWorkspaceEdit implements ToJsonable { + WorkspaceClientCapabilitiesWorkspaceEdit( + this.documentChanges, this.resourceOperations, this.failureHandling); + static WorkspaceClientCapabilitiesWorkspaceEdit fromJson( + Map<String, dynamic> json) { + final documentChanges = json['documentChanges']; + final resourceOperations = json['resourceOperations'] + ?.map((item) => + item != null ? ResourceOperationKind.fromJson(item) : null) + ?.cast<ResourceOperationKind>() + ?.toList(); + final failureHandling = json['failureHandling'] != null + ? FailureHandlingKind.fromJson(json['failureHandling']) + : null; + return new WorkspaceClientCapabilitiesWorkspaceEdit( + documentChanges, resourceOperations, failureHandling); + } + + /// The client supports versioned document changes in `WorkspaceEdit`s + final bool documentChanges; + + /// The failure handling strategy of a client if applying the workspace edit + /// fails. + final FailureHandlingKind failureHandling; + + /// The resource operations the client supports. Clients should at least + /// support 'create', 'rename' and 'delete' files and folders. + final List<ResourceOperationKind> resourceOperations; + + Map<String, dynamic> toJson() { + Map<String, dynamic> __result = {}; if (documentChanges != null) { __result['documentChanges'] = documentChanges; } @@ -6039,16 +10892,61 @@ static bool canParse(Object obj) { return obj is Map<String, dynamic>; } + + @override + bool operator ==(other) { + if (other is WorkspaceClientCapabilitiesWorkspaceEdit) { + return documentChanges == other.documentChanges && + listEqual(resourceOperations, other.resourceOperations, + (ResourceOperationKind a, ResourceOperationKind b) => a == b) && + failureHandling == other.failureHandling && + true; + } + return false; + } + + @override + int get hashCode { + int hash = 0; + hash = JenkinsSmiHash.combine(hash, documentChanges.hashCode); + hash = JenkinsSmiHash.combine(hash, resourceOperations.hashCode); + hash = JenkinsSmiHash.combine(hash, failureHandling.hashCode); + return JenkinsSmiHash.finish(hash); + } + + @override + String toString() => jsonEncoder.convert(toJson()); } class WorkspaceEdit implements ToJsonable { WorkspaceEdit(this.changes, this.documentChanges); - factory WorkspaceEdit.fromJson(Map<String, dynamic> json) { - final changes = json['changes']; - final documentChanges = json['documentChanges'] - ?.map((item) => item) - ?.cast<FileOperation>() - ?.toList(); + static WorkspaceEdit fromJson(Map<String, dynamic> json) { + final changes = json['changes'] + ?.map((key, value) => new MapEntry( + key, + value + ?.map((item) => item != null ? TextEdit.fromJson(item) : null) + ?.cast<TextEdit>() + ?.toList())) + ?.cast<String, List<TextEdit>>(); + final documentChanges = (json['documentChanges'] is List && (json['documentChanges'].length == 0 || json['documentChanges'].every((item) => TextDocumentEdit.canParse(item)))) + ? new Either2<List<TextDocumentEdit>, List<Either4<TextDocumentEdit, CreateFile, RenameFile, DeleteFile>>>.t1(json['documentChanges'] + ?.map( + (item) => item != null ? TextDocumentEdit.fromJson(item) : null) + ?.cast<TextDocumentEdit>() + ?.toList()) + : ((json['documentChanges'] is List && (json['documentChanges'].length == 0 || json['documentChanges'].every((item) => (TextDocumentEdit.canParse(item) || CreateFile.canParse(item) || RenameFile.canParse(item) || DeleteFile.canParse(item))))) + ? new Either2<List<TextDocumentEdit>, List<Either4<TextDocumentEdit, CreateFile, RenameFile, DeleteFile>>>.t2(json['documentChanges'] + ?.map((item) => TextDocumentEdit.canParse(item) + ? new Either4<TextDocumentEdit, CreateFile, RenameFile, DeleteFile>.t1( + item != null ? TextDocumentEdit.fromJson(item) : null) + : (CreateFile.canParse(item) + ? new Either4<TextDocumentEdit, CreateFile, RenameFile, DeleteFile>.t2( + item != null ? CreateFile.fromJson(item) : null) + : (RenameFile.canParse(item) ? new Either4<TextDocumentEdit, CreateFile, RenameFile, DeleteFile>.t3(item != null ? RenameFile.fromJson(item) : null) : (DeleteFile.canParse(item) ? new Either4<TextDocumentEdit, CreateFile, RenameFile, DeleteFile>.t4(item != null ? DeleteFile.fromJson(item) : null) : (item == null ? null : (throw '''${item} was not one of (TextDocumentEdit, CreateFile, RenameFile, DeleteFile)''')))))) + ?.cast<Either4<TextDocumentEdit, CreateFile, RenameFile, DeleteFile>>() + ?.toList()) + : (json['documentChanges'] == null ? null : (throw '''${json['documentChanges']} was not one of (List<TextDocumentEdit>, List<Either4<TextDocumentEdit, CreateFile, RenameFile, DeleteFile>>)'''))); return new WorkspaceEdit(changes, documentChanges); } @@ -6056,26 +10954,21 @@ final Map<String, List<TextEdit>> changes; /// Depending on the client capability - /// `workspace.workspaceEdit.resourceOperations` - /// document changes are either an array of - /// `TextDocumentEdit`s to express changes to n - /// different text documents where each text - /// document edit addresses a specific version - /// of a text document. Or it can contain above - /// `TextDocumentEdit`s mixed with create, - /// rename and delete file / folder operations. + /// `workspace.workspaceEdit.resourceOperations` document changes are either + /// an array of `TextDocumentEdit`s to express changes to n different text + /// documents where each text document edit addresses a specific version of a + /// text document. Or it can contain above `TextDocumentEdit`s mixed with + /// create, rename and delete file / folder operations. /// - /// Whether a client supports versioned document - /// edits is expressed via - /// `workspace.workspaceEdit.documentChanges` - /// client capability. + /// Whether a client supports versioned document edits is expressed via + /// `workspace.workspaceEdit.documentChanges` client capability. /// - /// If a client neither supports - /// `documentChanges` nor - /// `workspace.workspaceEdit.resourceOperations` - /// then only plain `TextEdit`s using the - /// `changes` property are supported. - final List<FileOperation> documentChanges; + /// If a client neither supports `documentChanges` nor + /// `workspace.workspaceEdit.resourceOperations` then only plain `TextEdit`s + /// using the `changes` property are supported. + final Either2<List<TextDocumentEdit>, + List<Either4<TextDocumentEdit, CreateFile, RenameFile, DeleteFile>>> + documentChanges; Map<String, dynamic> toJson() { Map<String, dynamic> __result = {}; @@ -6091,6 +10984,28 @@ static bool canParse(Object obj) { return obj is Map<String, dynamic>; } + + @override + bool operator ==(other) { + if (other is WorkspaceEdit) { + return mapEqual(changes, other.changes, + (List<TextEdit> a, List<TextEdit> b) => a == b) && + documentChanges == other.documentChanges && + true; + } + return false; + } + + @override + int get hashCode { + int hash = 0; + hash = JenkinsSmiHash.combine(hash, changes.hashCode); + hash = JenkinsSmiHash.combine(hash, documentChanges.hashCode); + return JenkinsSmiHash.finish(hash); + } + + @override + String toString() => jsonEncoder.convert(toJson()); } class WorkspaceFolder implements ToJsonable { @@ -6102,18 +11017,16 @@ throw 'name is required but was not provided'; } } - factory WorkspaceFolder.fromJson(Map<String, dynamic> json) { + static WorkspaceFolder fromJson(Map<String, dynamic> json) { final uri = json['uri']; final name = json['name']; return new WorkspaceFolder(uri, name); } - /// The name of the workspace folder. Defaults - /// to the uri's basename. + /// The name of the workspace folder. Defaults to the uri's basename. final String name; - /// The associated URI for this workspace - /// folder. + /// The associated URI for this workspace folder. final String uri; Map<String, dynamic> toJson() { @@ -6130,6 +11043,25 @@ obj.containsKey('name') && obj['name'] is String; } + + @override + bool operator ==(other) { + if (other is WorkspaceFolder) { + return uri == other.uri && name == other.name && true; + } + return false; + } + + @override + int get hashCode { + int hash = 0; + hash = JenkinsSmiHash.combine(hash, uri.hashCode); + hash = JenkinsSmiHash.combine(hash, name.hashCode); + return JenkinsSmiHash.finish(hash); + } + + @override + String toString() => jsonEncoder.convert(toJson()); } /// The workspace folder change event. @@ -6142,15 +11074,13 @@ throw 'removed is required but was not provided'; } } - factory WorkspaceFoldersChangeEvent.fromJson(Map<String, dynamic> json) { + static WorkspaceFoldersChangeEvent fromJson(Map<String, dynamic> json) { final added = json['added'] - ?.map( - (item) => item != null ? new WorkspaceFolder.fromJson(item) : null) + ?.map((item) => item != null ? WorkspaceFolder.fromJson(item) : null) ?.cast<WorkspaceFolder>() ?.toList(); final removed = json['removed'] - ?.map( - (item) => item != null ? new WorkspaceFolder.fromJson(item) : null) + ?.map((item) => item != null ? WorkspaceFolder.fromJson(item) : null) ?.cast<WorkspaceFolder>() ?.toList(); return new WorkspaceFoldersChangeEvent(added, removed); @@ -6183,6 +11113,29 @@ obj['removed'] .every((item) => WorkspaceFolder.canParse(item)))); } + + @override + bool operator ==(other) { + if (other is WorkspaceFoldersChangeEvent) { + return listEqual(added, other.added, + (WorkspaceFolder a, WorkspaceFolder b) => a == b) && + listEqual(removed, other.removed, + (WorkspaceFolder a, WorkspaceFolder b) => a == b) && + true; + } + return false; + } + + @override + int get hashCode { + int hash = 0; + hash = JenkinsSmiHash.combine(hash, added.hashCode); + hash = JenkinsSmiHash.combine(hash, removed.hashCode); + return JenkinsSmiHash.finish(hash); + } + + @override + String toString() => jsonEncoder.convert(toJson()); } /// The parameters of a Workspace Symbol Request. @@ -6192,7 +11145,7 @@ throw 'query is required but was not provided'; } } - factory WorkspaceSymbolParams.fromJson(Map<String, dynamic> json) { + static WorkspaceSymbolParams fromJson(Map<String, dynamic> json) { final query = json['query']; return new WorkspaceSymbolParams(query); } @@ -6211,4 +11164,22 @@ obj.containsKey('query') && obj['query'] is String; } + + @override + bool operator ==(other) { + if (other is WorkspaceSymbolParams) { + return query == other.query && true; + } + return false; + } + + @override + int get hashCode { + int hash = 0; + hash = JenkinsSmiHash.combine(hash, query.hashCode); + return JenkinsSmiHash.finish(hash); + } + + @override + String toString() => jsonEncoder.convert(toJson()); }
diff --git a/pkg/analysis_server/lib/lsp_protocol/protocol_special.dart b/pkg/analysis_server/lib/lsp_protocol/protocol_special.dart index 35ae774..fd526fe 100644 --- a/pkg/analysis_server/lib/lsp_protocol/protocol_special.dart +++ b/pkg/analysis_server/lib/lsp_protocol/protocol_special.dart
@@ -2,6 +2,12 @@ // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. +import 'dart:async'; + +import 'package:analysis_server/lsp_protocol/protocol_generated.dart'; + +const jsonRpcVersion = '2.0'; + Object id(Object obj) => obj; Object specToJson(Object obj) { @@ -145,7 +151,54 @@ map((t) => t == o, (t) => t == o, (t) => t == o, (t) => t == o); } -class FileOperation {} +class ErrorOr<T> extends Either2<ResponseError, T> { + ErrorOr.error(ResponseError error) : super.t1(error); + ErrorOr.success([T result]) : super.t2(result); + + /// Returns the error or throws if object is not an error. Check [isError] + /// before accessing [error]. + ResponseError get error { + return _which == 1 ? _t1 : (throw 'Value is not an error'); + } + + /// Returns true if this object is an error, false if it is a result. Prefer + /// [mapResult] instead of checking this flag if [errors] will simply be + /// propagated as-is. + bool get isError => _which == 1; + + /// Returns the result or throws if this object is an error. Check [isError] + /// before accessing [result]. It is valid for this to return null is the + /// object does not represent an error but the resulting value was null. + T get result { + return _which == 2 ? _t2 : (throw 'Value is not a result'); + } + + /// If this object is a result, maps [result] through [f], otherwise returns + /// a new error object representing [error]. + FutureOr<ErrorOr<N>> mapResult<N>(FutureOr<ErrorOr<N>> Function(T) f) { + return isError + // Re-wrap the error using our new type arg + ? new ErrorOr<N>.error(error) + // Otherwise call the map function + : f(result); + } +} + +/// A base class containing the fields common to RequestMessage and +/// NotificationMessage to simplify handling. +abstract class IncomingMessage { + Method get method; + dynamic get params; +} + +abstract class ServerErrorCodes { + // JSON-RPC reserves -32000 to -32099 for implementation-defined server-errors. + static const ServerAlreadyStarted = const ErrorCodes(-32000); + static const UnhandledError = const ErrorCodes(-32001); + static const ServerAlreadyInitialized = const ErrorCodes(-32002); + static const InvalidFilePath = const ErrorCodes(-32003); + static const InvalidFileLineCol = const ErrorCodes(-32004); +} abstract class ToJsonable { Object toJson();
diff --git a/pkg/analysis_server/lib/plugin/edit/assist/assist_dart.dart b/pkg/analysis_server/lib/plugin/edit/assist/assist_dart.dart index 6e7020e..f338cc5 100644 --- a/pkg/analysis_server/lib/plugin/edit/assist/assist_dart.dart +++ b/pkg/analysis_server/lib/plugin/edit/assist/assist_dart.dart
@@ -2,9 +2,7 @@ // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. -import 'package:analyzer/dart/ast/ast.dart'; -import 'package:analyzer/src/dart/analysis/driver.dart'; -import 'package:analyzer/src/generated/source.dart'; +import 'package:analyzer/dart/analysis/results.dart'; /** * An object used to provide context information for Dart assist contributors. @@ -13,9 +11,9 @@ */ abstract class DartAssistContext { /** - * The analysis driver used to access analysis results. + * The resolution result in which assist operates. */ - AnalysisDriver get analysisDriver; + ResolvedUnitResult get resolveResult; /** * The length of the selection. @@ -26,14 +24,4 @@ * The start of the selection. */ int get selectionOffset; - - /** - * The source to get assists in. - */ - Source get source; - - /** - * The [CompilationUnit] to compute assists in. - */ - CompilationUnit get unit; }
diff --git a/pkg/analysis_server/lib/plugin/edit/fix/fix_core.dart b/pkg/analysis_server/lib/plugin/edit/fix/fix_core.dart index af303ec..ccc79a9 100644 --- a/pkg/analysis_server/lib/plugin/edit/fix/fix_core.dart +++ b/pkg/analysis_server/lib/plugin/edit/fix/fix_core.dart
@@ -5,8 +5,6 @@ import 'dart:async'; import 'package:analyzer/error/error.dart'; -import 'package:analyzer/file_system/file_system.dart'; -import 'package:analyzer/src/dart/analysis/driver.dart'; import 'package:analyzer_plugin/protocol/protocol_common.dart' show SourceChange; import 'package:analyzer_plugin/utilities/fixes/fixes.dart'; @@ -64,25 +62,9 @@ */ abstract class FixContext { /** - * The analysis driver used to access analysis results. - */ - AnalysisDriver get analysisDriver; - - /** - * The error to fix, should be reported by the given [analysisDriver]. + * The error to fix. */ AnalysisError get error; - - /** - * All of the errors in the file. This is used to compute additional fixes - * such "Fix all instances in file." - */ - List<AnalysisError> get errors; - - /** - * The [ResourceProvider] to access files and folders. - */ - ResourceProvider get resourceProvider; } /** @@ -96,5 +78,5 @@ /** * Return a list of fixes for the given [context]. */ - Future<List<Fix>> computeFixes(FixContext context); + Future<List<Fix>> computeFixes(covariant FixContext context); }
diff --git a/pkg/analysis_server/lib/plugin/edit/fix/fix_dart.dart b/pkg/analysis_server/lib/plugin/edit/fix/fix_dart.dart index c4d54d1..2ac36c5 100644 --- a/pkg/analysis_server/lib/plugin/edit/fix/fix_dart.dart +++ b/pkg/analysis_server/lib/plugin/edit/fix/fix_dart.dart
@@ -2,24 +2,8 @@ // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. -import 'dart:async'; - import 'package:analysis_server/plugin/edit/fix/fix_core.dart'; -import 'package:analysis_server/src/services/correction/fix_internal.dart' - show DartFixContextImpl; -import 'package:analyzer/dart/ast/ast.dart'; -import 'package:analyzer/src/dart/analysis/ast_provider_driver.dart'; -import 'package:analyzer/src/dart/analysis/driver.dart'; -import 'package:analyzer/src/dart/analysis/top_level_declaration.dart'; -import 'package:analyzer/src/dart/element/ast_provider.dart'; -import 'package:analyzer/src/generated/engine.dart'; -import 'package:analyzer/src/generated/source.dart'; - -/** - * Complete with top-level declarations with the given [name]. - */ -typedef Future<List<TopLevelDeclarationInSource>> GetTopLevelDeclarations( - String name); +import 'package:analyzer/dart/analysis/results.dart'; /** * An object used to provide context information for [DartFixContributor]s. @@ -28,48 +12,7 @@ */ abstract class DartFixContext implements FixContext { /** - * The provider for parsed or resolved ASTs. + * The resolution result in which fix operates. */ - AstProvider get astProvider; - - /** - * The function to get top-level declarations from. - */ - GetTopLevelDeclarations get getTopLevelDeclarations; - - /** - * The [CompilationUnit] to compute fixes in. - */ - CompilationUnit get unit; -} - -/** - * A [FixContributor] that can be used to contribute fixes for errors in Dart - * files. - * - * Clients may extend this class when implementing plugins. - */ -abstract class DartFixContributor implements FixContributor { - @override - Future<List<Fix>> computeFixes(FixContext context) async { - // TODO(brianwilkerson) Determine whether this await is necessary. - await null; - AnalysisDriver driver = context.analysisDriver; - Source source = context.error.source; - if (!AnalysisEngine.isDartFileName(source.fullName)) { - return const <Fix>[]; - } - CompilationUnit unit = (await driver.getResult(source.fullName)).unit; - if (unit == null) { - return const <Fix>[]; - } - DartFixContext dartContext = - new DartFixContextImpl(context, new AstProviderForDriver(driver), unit); - return internalComputeFixes(dartContext); - } - - /** - * Return a list of fixes for the given [context]. - */ - Future<List<Fix>> internalComputeFixes(DartFixContext context); + ResolvedUnitResult get resolveResult; }
diff --git a/pkg/analysis_server/lib/plugin/protocol/protocol_dart.dart b/pkg/analysis_server/lib/plugin/protocol/protocol_dart.dart index e4ab6d5..cab3a80 100644 --- a/pkg/analysis_server/lib/plugin/protocol/protocol_dart.dart +++ b/pkg/analysis_server/lib/plugin/protocol/protocol_dart.dart
@@ -64,6 +64,9 @@ if (kind == engine.ElementKind.FUNCTION_TYPE_ALIAS) { return ElementKind.FUNCTION_TYPE_ALIAS; } + if (kind == engine.ElementKind.GENERIC_FUNCTION_TYPE) { + return ElementKind.FUNCTION_TYPE_ALIAS; + } if (kind == engine.ElementKind.GETTER) { return ElementKind.GETTER; }
diff --git a/pkg/analysis_server/lib/src/analysis_server.dart b/pkg/analysis_server/lib/src/analysis_server.dart index ae93b77..ff16acf 100644 --- a/pkg/analysis_server/lib/src/analysis_server.dart +++ b/pkg/analysis_server/lib/src/analysis_server.dart
@@ -14,6 +14,7 @@ import 'package:analysis_server/protocol/protocol_generated.dart' hide AnalysisOptions; import 'package:analysis_server/src/analysis_logger.dart'; +import 'package:analysis_server/src/analysis_server_abstract.dart'; import 'package:analysis_server/src/channel/channel.dart'; import 'package:analysis_server/src/collections.dart'; import 'package:analysis_server/src/computer/computer_highlights.dart'; @@ -42,36 +43,28 @@ import 'package:analysis_server/src/search/search_domain.dart'; import 'package:analysis_server/src/server/detachable_filesystem_manager.dart'; import 'package:analysis_server/src/server/diagnostic_server.dart'; -import 'package:analysis_server/src/services/correction/namespace.dart'; -import 'package:analysis_server/src/services/search/element_visitors.dart'; import 'package:analysis_server/src/services/search/search_engine.dart'; import 'package:analysis_server/src/services/search/search_engine_internal.dart'; import 'package:analysis_server/src/utilities/null_string_sink.dart'; +import 'package:analyzer/dart/analysis/results.dart'; import 'package:analyzer/dart/ast/ast.dart'; -import 'package:analyzer/dart/element/element.dart'; import 'package:analyzer/exception/exception.dart'; import 'package:analyzer/file_system/file_system.dart'; import 'package:analyzer/file_system/physical_file_system.dart'; import 'package:analyzer/instrumentation/instrumentation.dart'; import 'package:analyzer/src/context/builder.dart'; import 'package:analyzer/src/context/context_root.dart'; -import 'package:analyzer/src/dart/analysis/ast_provider_driver.dart'; import 'package:analyzer/src/dart/analysis/byte_store.dart'; import 'package:analyzer/src/dart/analysis/driver.dart' as nd; -import 'package:analyzer/src/dart/analysis/file_byte_store.dart' - show EvictingFileByteStore; import 'package:analyzer/src/dart/analysis/file_state.dart' as nd; import 'package:analyzer/src/dart/analysis/performance_logger.dart'; import 'package:analyzer/src/dart/analysis/status.dart' as nd; -import 'package:analyzer/src/dart/ast/utilities.dart'; -import 'package:analyzer/src/dart/element/ast_provider.dart'; import 'package:analyzer/src/generated/engine.dart'; import 'package:analyzer/src/generated/sdk.dart'; import 'package:analyzer/src/generated/source.dart'; import 'package:analyzer/src/generated/source_io.dart'; import 'package:analyzer/src/generated/utilities_general.dart'; import 'package:analyzer/src/plugin/resolver_provider.dart'; -import 'package:analyzer/src/util/glob.dart'; import 'package:analyzer_plugin/protocol/protocol_common.dart' hide Element; import 'package:analyzer_plugin/src/utilities/navigation/navigation.dart'; import 'package:telemetry/crash_reporting.dart'; @@ -80,179 +73,99 @@ typedef void OptionUpdater(AnalysisOptionsImpl options); -/** - * Instances of the class [AnalysisServer] implement a server that listens on a - * [CommunicationChannel] for analysis requests and process them. - */ -class AnalysisServer { - /** - * The options of this server instance. - */ +/// Instances of the class [AnalysisServer] implement a server that listens on a +/// [CommunicationChannel] for analysis requests and process them. +class AnalysisServer extends AbstractAnalysisServer { + /// The options of this server instance. AnalysisServerOptions options; - /** - * The channel from which requests are received and to which responses should - * be sent. - */ + /// The channel from which requests are received and to which responses should + /// be sent. final ServerCommunicationChannel channel; - /** - * The object used to manage sending a subset of notifications to the client. - * The subset of notifications are those to which plugins may contribute. - * This field is `null` when the new plugin support is disabled. - */ + /// The object used to manage sending a subset of notifications to the client. + /// The subset of notifications are those to which plugins may contribute. + /// This field is `null` when the new plugin support is disabled. final NotificationManager notificationManager; - /** - * The object used to manage the execution of plugins. - */ + /// The object used to manage the execution of plugins. PluginManager pluginManager; - /** - * The [ResourceProvider] using which paths are converted into [Resource]s. - */ - final ResourceProvider resourceProvider; - - /** - * The [SearchEngine] for this server, may be `null` if indexing is disabled. - */ + /// The [SearchEngine] for this server, may be `null` if indexing is disabled. SearchEngine searchEngine; - /** - * A list of the globs used to determine which files should be analyzed. The - * list is lazily created and should be accessed using [analyzedFilesGlobs]. - */ - List<Glob> _analyzedFilesGlobs = null; - - /** - * The [ContextManager] that handles the mapping from analysis roots to - * context directories. - */ - ContextManager contextManager; - - /** - * A flag indicating whether the server is running. When false, contexts - * will no longer be added to [contextWorkQueue], and [performOperation] will - * discard any tasks it finds on [contextWorkQueue]. - */ - bool running; - - /** - * A flag indicating the value of the 'analyzing' parameter sent in the last - * status message to the client. - */ + /// A flag indicating the value of the 'analyzing' parameter sent in the last + /// status message to the client. bool statusAnalyzing = false; - /** - * A list of the request handlers used to handle the requests sent to this - * server. - */ + /// A list of the request handlers used to handle the requests sent to this + /// server. List<RequestHandler> handlers; - /** - * The object used to manage the SDK's known to this server. - */ + /// The object used to manage the SDK's known to this server. final DartSdkManager sdkManager; - /** - * The instrumentation service that is to be used by this analysis server. - */ + /// The instrumentation service that is to be used by this analysis server. final InstrumentationService instrumentationService; - /** - * A set of the [ServerService]s to send notifications for. - */ + /// A set of the [ServerService]s to send notifications for. Set<ServerService> serverServices = new HashSet<ServerService>(); - /** - * A set of the [GeneralAnalysisService]s to send notifications for. - */ + /// A set of the [GeneralAnalysisService]s to send notifications for. Set<GeneralAnalysisService> generalAnalysisServices = new HashSet<GeneralAnalysisService>(); - /** - * A table mapping [AnalysisService]s to the file paths for which these - * notifications should be sent. - */ + /// A table mapping [AnalysisService]s to the file paths for which these + /// notifications should be sent. Map<AnalysisService, Set<String>> analysisServices = new HashMap<AnalysisService, Set<String>>(); - /** - * A table mapping [FlutterService]s to the file paths for which these - * notifications should be sent. - */ + /// A table mapping [FlutterService]s to the file paths for which these + /// notifications should be sent. Map<FlutterService, Set<String>> flutterServices = {}; - /** - * Performance information before initial analysis is complete. - */ + /// Performance information before initial analysis is complete. final ServerPerformance performanceDuringStartup = new ServerPerformance(); - /** - * Performance information after initial analysis is complete - * or `null` if the initial analysis is not yet complete - */ + /// Performance information after initial analysis is complete + /// or `null` if the initial analysis is not yet complete ServerPerformance performanceAfterStartup; - /** - * A [RecentBuffer] of the most recent exceptions encountered by the analysis - * server. - */ + /// A [RecentBuffer] of the most recent exceptions encountered by the analysis + /// server. final RecentBuffer<ServerException> exceptions = new RecentBuffer(10); - /** - * The class into which performance information is currently being recorded. - * During startup, this will be the same as [performanceDuringStartup] - * and after startup is complete, this switches to [performanceAfterStartup]. - */ + /// The class into which performance information is currently being recorded. + /// During startup, this will be the same as [performanceDuringStartup] + /// and after startup is complete, this switches to [performanceAfterStartup]. ServerPerformance _performance; - /** - * The [Completer] that completes when analysis is complete. - */ + /// The [Completer] that completes when analysis is complete. Completer _onAnalysisCompleteCompleter; - /** - * The controller that is notified when analysis is started. - */ + /// The controller that is notified when analysis is started. StreamController<bool> _onAnalysisStartedController; - /** - * The content overlay for all analysis drivers. - */ + /// The content overlay for all analysis drivers. final nd.FileContentOverlay fileContentOverlay = new nd.FileContentOverlay(); - /** - * The current state of overlays from the client. This is used as the - * content cache for all contexts. - */ - final ContentCache overlayState = new ContentCache(); - - /** - * If the "analysis.analyzedFiles" notification is currently being subscribed - * to (see [generalAnalysisServices]), and at least one such notification has - * been sent since the subscription was enabled, the set of analyzed files - * that was delivered in the most recently sent notification. Otherwise - * `null`. - */ + /// If the "analysis.analyzedFiles" notification is currently being subscribed + /// to (see [generalAnalysisServices]), and at least one such notification has + /// been sent since the subscription was enabled, the set of analyzed files + /// that was delivered in the most recently sent notification. Otherwise + /// `null`. Set<String> prevAnalyzedFiles; - /** - * The default options used to create new analysis contexts. This object is - * also referenced by the ContextManager. - */ + /// The default options used to create new analysis contexts. This object is + /// also referenced by the ContextManager. final AnalysisOptionsImpl defaultContextOptions = new AnalysisOptionsImpl(); - /** - * The file resolver provider used to override the way file URI's are - * resolved in some contexts. - */ + /// The file resolver provider used to override the way file URI's are + /// resolved in some contexts. ResolverProvider fileResolverProvider; - /** - * The package resolver provider used to override the way package URI's are - * resolved in some contexts. - */ + /// The package resolver provider used to override the way package URI's are + /// resolved in some contexts. ResolverProvider packageResolverProvider; PerformanceLog _analysisPerformanceLogger; @@ -260,38 +173,27 @@ ByteStore byteStore; nd.AnalysisDriverScheduler analysisDriverScheduler; - /** - * The controller for [onAnalysisSetChanged]. - */ + /// The controller for [onAnalysisSetChanged]. final StreamController _onAnalysisSetChangedController = new StreamController.broadcast(sync: true); - /** - * The set of the files that are currently priority. - */ - final Set<String> priorityFiles = new Set<String>(); - - /** - * The DiagnosticServer for this AnalysisServer. If available, it can be used - * to start an http diagnostics server or return the port for an existing - * server. - */ + /// The DiagnosticServer for this AnalysisServer. If available, it can be used + /// to start an http diagnostics server or return the port for an existing + /// server. final DiagnosticServer diagnosticServer; final DetachableFileSystemManager detachableFileSystemManager; - /** - * Initialize a newly created server to receive requests from and send - * responses to the given [channel]. - * - * If [rethrowExceptions] is true, then any exceptions thrown by analysis are - * propagated up the call stack. The default is true to allow analysis - * exceptions to show up in unit tests, but it should be set to false when - * running a full analysis server. - */ + /// Initialize a newly created server to receive requests from and send + /// responses to the given [channel]. + /// + /// If [rethrowExceptions] is true, then any exceptions thrown by analysis are + /// propagated up the call stack. The default is true to allow analysis + /// exceptions to show up in unit tests, but it should be set to false when + /// running a full analysis server. AnalysisServer( this.channel, - this.resourceProvider, + ResourceProvider resourceProvider, this.options, this.sdkManager, this.instrumentationService, { @@ -299,8 +201,9 @@ ResolverProvider fileResolverProvider: null, ResolverProvider packageResolverProvider: null, this.detachableFileSystemManager: null, - }) : notificationManager = - new NotificationManager(channel, resourceProvider) { + }) : notificationManager = + new NotificationManager(channel, resourceProvider), + super(resourceProvider) { _performance = performanceDuringStartup; pluginManager = new PluginManager( @@ -328,7 +231,7 @@ } _analysisPerformanceLogger = new PerformanceLog(sink); } - byteStore = _createByteStore(); + byteStore = createByteStore(resourceProvider); analysisDriverScheduler = new nd.AnalysisDriverScheduler( _analysisPerformanceLogger, driverWatcher: pluginWatcher); @@ -350,7 +253,6 @@ contextManager.callbacks = contextManagerCallbacks; AnalysisEngine.instance.logger = new AnalysisLogger(this); _onAnalysisStartedController = new StreamController.broadcast(); - running = true; onAnalysisStarted.first.then((_) { onAnalysisComplete.then((_) { performanceAfterStartup = new ServerPerformance(); @@ -378,47 +280,10 @@ ]; } - /** - * The analytics instance; note, this object can be `null`. - */ + /// The analytics instance; note, this object can be `null`. telemetry.Analytics get analytics => options.analytics; - /** - * Return a list of the globs used to determine which files should be analyzed. - */ - List<Glob> get analyzedFilesGlobs { - if (_analyzedFilesGlobs == null) { - _analyzedFilesGlobs = <Glob>[]; - List<String> patterns = <String>[ - '**/*.${AnalysisEngine.SUFFIX_DART}', - '**/*.${AnalysisEngine.SUFFIX_HTML}', - '**/*.${AnalysisEngine.SUFFIX_HTM}', - '**/${AnalysisEngine.ANALYSIS_OPTIONS_FILE}', - '**/${AnalysisEngine.ANALYSIS_OPTIONS_YAML_FILE}', - '**/${AnalysisEngine.PUBSPEC_YAML_FILE}' - ]; - for (String pattern in patterns) { - try { - _analyzedFilesGlobs - .add(new Glob(resourceProvider.pathContext.separator, pattern)); - } catch (exception, stackTrace) { - AnalysisEngine.instance.logger.logError( - 'Invalid glob pattern: "$pattern"', - new CaughtException(exception, stackTrace)); - } - } - } - return _analyzedFilesGlobs; - } - - /** - * A table mapping [Folder]s to the [AnalysisDriver]s associated with them. - */ - Map<Folder, nd.AnalysisDriver> get driverMap => contextManager.driverMap; - - /** - * The [Future] that completes when analysis is complete. - */ + /// The [Future] that completes when analysis is complete. Future get onAnalysisComplete { if (isAnalysisComplete()) { return new Future.value(); @@ -429,50 +294,34 @@ return _onAnalysisCompleteCompleter.future; } - /** - * The stream that is notified when the analysis set is changed - this might - * be a change to a file, external via a watch event, or internal via - * overlay. This means that the resolved world might have changed. - * - * The type of produced elements is not specified and should not be used. - */ + /// The stream that is notified when the analysis set is changed - this might + /// be a change to a file, external via a watch event, or internal via + /// overlay. This means that the resolved world might have changed. + /// + /// The type of produced elements is not specified and should not be used. Stream get onAnalysisSetChanged => _onAnalysisSetChangedController.stream; - /** - * The stream that is notified with `true` when analysis is started. - */ + /// The stream that is notified with `true` when analysis is started. Stream<bool> get onAnalysisStarted { return _onAnalysisStartedController.stream; } - /** - * Return the total time the server's been alive. - */ + /// Return the total time the server's been alive. Duration get uptime { DateTime start = new DateTime.fromMillisecondsSinceEpoch( performanceDuringStartup.startTime); return new DateTime.now().difference(start); } - /** - * The socket from which requests are being read has been closed. - */ - void done() { - running = false; - } + /// The socket from which requests are being read has been closed. + void done() {} - /** - * There was an error related to the socket from which requests are being - * read. - */ - void error(argument) { - running = false; - } + /// There was an error related to the socket from which requests are being + /// read. + void error(argument) {} - /** - * Return one of the SDKs that has been created, or `null` if no SDKs have - * been created yet. - */ + /// Return one of the SDKs that has been created, or `null` if no SDKs have + /// been created yet. DartSdk findSdk() { DartSdk sdk = sdkManager.anySdk; if (sdk != null) { @@ -482,64 +331,9 @@ return null; } - /** - * Return an analysis driver to which the file with the given [path] is - * added if one exists, otherwise a driver in which the file was analyzed if - * one exists, otherwise the first driver, otherwise `null`. - */ - nd.AnalysisDriver getAnalysisDriver(String path) { - List<nd.AnalysisDriver> drivers = driverMap.values.toList(); - if (drivers.isNotEmpty) { - // Sort the drivers so that more deeply nested contexts will be checked - // before enclosing contexts. - drivers.sort((first, second) => - second.contextRoot.root.length - first.contextRoot.root.length); - nd.AnalysisDriver driver = drivers.firstWhere( - (driver) => driver.contextRoot.containsFile(path), - orElse: () => null); - driver ??= drivers.firstWhere( - (driver) => driver.knownFiles.contains(path), - orElse: () => null); - driver ??= drivers.first; - return driver; - } - return null; - } - - /** - * Return the analysis result for the file with the given [path]. The file is - * analyzed in one of the analysis drivers to which the file was added, - * otherwise in the first driver, otherwise `null` is returned. - */ - Future<nd.AnalysisResult> getAnalysisResult(String path, - {bool sendCachedToStream: false}) { - if (!AnalysisEngine.isDartFileName(path)) { - return null; - } - - nd.AnalysisDriver driver = getAnalysisDriver(path); - if (driver == null) { - return new Future.value(); - } - - return driver - .getResult(path, sendCachedToStream: sendCachedToStream) - .catchError((_) => null); - } - - /** - * Return the [AstProvider] for the given [path]. - */ - AstProvider getAstProvider(String path) { - nd.AnalysisDriver analysisDriver = getAnalysisDriver(path); - return new AstProviderForDriver(analysisDriver); - } - - /** - * Return the cached analysis result for the file with the given [path]. - * If there is no cached result, return `null`. - */ - nd.AnalysisResult getCachedAnalysisResult(String path) { + /// Return the cached analysis result for the file with the given [path]. + /// If there is no cached result, return `null`. + ResolvedUnitResult getCachedResolvedUnit(String path) { if (!AnalysisEngine.isDartFileName(path)) { return null; } @@ -548,90 +342,7 @@ return driver?.getCachedResult(path); } - /** - * Return a [Future] that completes with the [Element] at the given - * [offset] of the given [file], or with `null` if there is no node at the - * [offset] or the node does not have an element. - */ - Future<Element> getElementAtOffset(String file, int offset) async { - // TODO(brianwilkerson) Determine whether this await is necessary. - await null; - if (!priorityFiles.contains(file)) { - var driver = getAnalysisDriver(file); - if (driver == null) { - return null; - } - - var unitElementResult = await driver.getUnitElement(file); - if (unitElementResult == null) { - return null; - } - - var element = findElementByNameOffset(unitElementResult.element, offset); - if (element != null) { - return element; - } - } - - AstNode node = await getNodeAtOffset(file, offset); - return getElementOfNode(node); - } - - /** - * Return the [Element] of the given [node], or `null` if [node] is `null` or - * does not have an element. - */ - Element getElementOfNode(AstNode node) { - if (node == null) { - return null; - } - if (node is SimpleIdentifier && node.parent is LibraryIdentifier) { - node = node.parent; - } - if (node is LibraryIdentifier) { - node = node.parent; - } - if (node is StringLiteral && node.parent is UriBasedDirective) { - return null; - } - Element element = ElementLocator.locate(node); - if (node is SimpleIdentifier && element is PrefixElement) { - element = getImportElement(node); - } - return element; - } - - /** - * Return a [Future] that completes with the resolved [AstNode] at the - * given [offset] of the given [file], or with `null` if there is no node as - * the [offset]. - */ - Future<AstNode> getNodeAtOffset(String file, int offset) async { - // TODO(brianwilkerson) Determine whether this await is necessary. - await null; - nd.AnalysisResult result = await getAnalysisResult(file); - CompilationUnit unit = result?.unit; - if (unit != null) { - return new NodeLocator(offset).searchWithin(unit); - } - return null; - } - - /** - * Return a [Future] that completes with the resolved [CompilationUnit] for - * the Dart file with the given [path], or with `null` if the file is not a - * Dart file or cannot be resolved. - */ - Future<CompilationUnit> getResolvedCompilationUnit(String path) async { - // TODO(brianwilkerson) Determine whether this await is necessary. - await null; - nd.AnalysisResult result = await getAnalysisResult(path); - return result?.unit; - } - - /** - * Handle a [request] that was read from the communication channel. - */ + /// Handle a [request] that was read from the communication channel. void handleRequest(Request request) { _performance.logRequest(request); runZoned(() { @@ -672,50 +383,38 @@ }); } - /** - * Return `true` if analysis is complete. - */ + /// Return `true` if analysis is complete. bool isAnalysisComplete() { return !analysisDriverScheduler.isAnalyzing; } - /** - * Return `true` if the given path is a valid `FilePath`. - * - * This means that it is absolute and normalized. - */ + /// Return `true` if the given path is a valid `FilePath`. + /// + /// This means that it is absolute and normalized. bool isValidFilePath(String path) { return resourceProvider.pathContext.isAbsolute(path) && resourceProvider.pathContext.normalize(path) == path; } - /** - * Trigger reanalysis of all files in the given list of analysis [roots], or - * everything if the analysis roots is `null`. - */ + /// Trigger reanalysis of all files in the given list of analysis [roots], or + /// everything if the analysis roots is `null`. void reanalyze(List<Resource> roots) { // Instruct the contextDirectoryManager to rebuild all contexts from // scratch. contextManager.refresh(roots); } - /** - * Send the given [notification] to the client. - */ + /// Send the given [notification] to the client. void sendNotification(Notification notification) { channel.sendNotification(notification); } - /** - * Send the given [response] to the client. - */ + /// Send the given [response] to the client. void sendResponse(Response response) { channel.sendResponse(response); } - /** - * Sends a `server.error` notification. - */ + /// Sends a `server.error` notification. void sendServerErrorNotification( String message, dynamic exception, @@ -761,10 +460,8 @@ )); } - /** - * Send status notification to the client. The state of analysis is given by - * the [status] information. - */ + /// Send status notification to the client. The state of analysis is given by + /// the [status] information. void sendStatusNotificationNew(nd.AnalysisStatus status) { if (status.isAnalyzing) { _onAnalysisStartedController.add(true); @@ -795,18 +492,16 @@ new ServerStatusParams(analysis: analysis).toNotification()); } - /** - * Implementation for `analysis.setAnalysisRoots`. - * - * TODO(scheglov) implement complete projects/contexts semantics. - * - * The current implementation is intentionally simplified and expected - * that only folders are given each given folder corresponds to the exactly - * one context. - * - * So, we can start working in parallel on adding services and improving - * projects/contexts support. - */ + /// Implementation for `analysis.setAnalysisRoots`. + /// + /// TODO(scheglov) implement complete projects/contexts semantics. + /// + /// The current implementation is intentionally simplified and expected + /// that only folders are given each given folder corresponds to the exactly + /// one context. + /// + /// So, we can start working in parallel on adding services and improving + /// projects/contexts support. void setAnalysisRoots(String requestId, List<String> includedPaths, List<String> excludedPaths, Map<String, String> packageRoots) { if (notificationManager != null) { @@ -820,9 +515,7 @@ } } - /** - * Implementation for `analysis.setSubscriptions`. - */ + /// Implementation for `analysis.setSubscriptions`. void setAnalysisSubscriptions( Map<AnalysisService, Set<String>> subscriptions) { if (notificationManager != null) { @@ -836,14 +529,12 @@ // the fully resolved unit, and processed with sending analysis // notifications as it happens after content changes. if (AnalysisEngine.isDartFileName(file)) { - getAnalysisResult(file, sendCachedToStream: true); + getResolvedUnit(file, sendCachedToStream: true); } } } - /** - * Implementation for `flutter.setSubscriptions`. - */ + /// Implementation for `flutter.setSubscriptions`. void setFlutterSubscriptions(Map<FlutterService, Set<String>> subscriptions) { this.flutterServices = subscriptions; Set<String> allNewFiles = @@ -853,14 +544,12 @@ // the fully resolved unit, and processed with sending analysis // notifications as it happens after content changes. if (AnalysisEngine.isDartFileName(file)) { - getAnalysisResult(file, sendCachedToStream: true); + getResolvedUnit(file, sendCachedToStream: true); } } } - /** - * Implementation for `analysis.setGeneralSubscriptions`. - */ + /// Implementation for `analysis.setGeneralSubscriptions`. void setGeneralAnalysisSubscriptions( List<GeneralAnalysisService> subscriptions) { Set<GeneralAnalysisService> newServices = subscriptions.toSet(); @@ -877,9 +566,7 @@ generalAnalysisServices = newServices; } - /** - * Set the priority files to the given [files]. - */ + /// Set the priority files to the given [files]. void setPriorityFiles(String requestId, List<String> files) { priorityFiles.clear(); priorityFiles.addAll(files); @@ -889,17 +576,13 @@ }); } - /** - * Returns `true` if errors should be reported for [file] with the given - * absolute path. - */ + /// Returns `true` if errors should be reported for [file] with the given + /// absolute path. bool shouldSendErrorsNotificationFor(String file) { return contextManager.isInAnalysisRoot(file); } Future<void> shutdown() { - running = false; - if (options.analytics != null) { options.analytics .waitForLastPing(timeout: new Duration(milliseconds: 200)) @@ -922,9 +605,7 @@ return new Future.value(); } - /** - * Implementation for `analysis.updateContent`. - */ + /// Implementation for `analysis.updateContent`. void updateContent(String id, Map<String, dynamic> changes) { _onAnalysisSetChangedController.add(null); changes.forEach((file, change) { @@ -969,10 +650,8 @@ }); } - /** - * Use the given updaters to update the values of the options in every - * existing analysis context. - */ + /// Use the given updaters to update the values of the options in every + /// existing analysis context. void updateOptions(List<OptionUpdater> optionUpdaters) { // TODO(scheglov) implement for the new analysis driver // // @@ -996,32 +675,8 @@ // }); } - /** - * If the state location can be accessed, return the file byte store, - * otherwise return the memory byte store. - */ - ByteStore _createByteStore() { - const int M = 1024 * 1024 /*1 MiB*/; - const int G = 1024 * 1024 * 1024 /*1 GiB*/; - - const int memoryCacheSize = 128 * M; - - if (resourceProvider is PhysicalResourceProvider) { - Folder stateLocation = - resourceProvider.getStateLocation('.analysis-driver'); - if (stateLocation != null) { - return new MemoryCachingByteStore( - new EvictingFileByteStore(stateLocation.path, G), memoryCacheSize); - } - } - - return new MemoryCachingByteStore(new NullByteStore(), memoryCacheSize); - } - - /** - * Return the path to the location of the byte store on disk, or `null` if - * there is no on-disk byte store. - */ + /// Return the path to the location of the byte store on disk, or `null` if + /// there is no on-disk byte store. String _getByteStorePath() { if (resourceProvider is PhysicalResourceProvider) { Folder stateLocation = @@ -1033,10 +688,8 @@ return null; } - /** - * Returns `true` if there is a subscription for the given [service] and - * [file]. - */ + /// Returns `true` if there is a subscription for the given [service] and + /// [file]. bool _hasAnalysisServiceSubscription(AnalysisService service, String file) { return analysisServices[service]?.contains(file) ?? false; } @@ -1055,9 +708,7 @@ } } -/** - * Various IDE options. - */ +/// Various IDE options. class AnalysisServerOptions { bool useAnalysisHighlight2 = false; @@ -1067,48 +718,37 @@ String clientId; String clientVersion; - /** - * Base path where to cache data. - */ + /// Base path where to cache data. String cacheFolder; - /** - * The analytics instance; note, this object can be `null`, and should be - * accessed via a null-aware operator. - */ + /// The analytics instance; note, this object can be `null`, and should be + /// accessed via a null-aware operator. telemetry.Analytics analytics; - /** - * The crash report sender instance; note, this object can be `null`, and - * should be accessed via a null-aware operator. - */ + /// The crash report sender instance; note, this object can be `null`, and + /// should be accessed via a null-aware operator. CrashReportSender crashReportSender; - /** - * Whether to enable parsing via the Fasta parser. - */ + /// Whether to use the Language Server Protocol. + bool useLanguageServerProtocol = false; + + /// Whether to enable parsing via the Fasta parser. bool useFastaParser = true; - /** - * User Experience, Experiment #1. This experiment changes the notion of - * what analysis roots are and priority files: the analysis root is set to be - * the priority files' containing directory. - */ + /// User Experience, Experiment #1. This experiment changes the notion of + /// what analysis roots are and priority files: the analysis root is set to be + /// the priority files' containing directory. bool enableUXExperiment1 = false; - /** - * User Experience, Experiment #2. This experiment introduces the notion of an - * intermittent file system. - */ + /// User Experience, Experiment #2. This experiment introduces the notion of + /// an intermittent file system. bool enableUXExperiment2 = false; } class ServerContextManagerCallbacks extends ContextManagerCallbacks { final AnalysisServer analysisServer; - /** - * The [ResourceProvider] by which paths are converted into [Resource]s. - */ + /// The [ResourceProvider] by which paths are converted into [Resource]s. final ResourceProvider resourceProvider; ServerContextManagerCallbacks(this.analysisServer, this.resourceProvider); @@ -1132,7 +772,7 @@ NotificationManager.serverId, path, server.doAnalysisError_listFromEngine( - result.driver.analysisOptions, + result.session.analysisContext.analysisOptions, result.lineInfo, result.errors)); } else { @@ -1232,8 +872,8 @@ if (analysisServer._hasFlutterServiceSubscription( FlutterService.OUTLINE, path)) { _runDelayed(() { - sendFlutterNotificationOutline( - analysisServer, path, result.content, result.lineInfo, unit); + sendFlutterNotificationOutline(analysisServer, path, result.content, + result.lineInfo, unit, result.typeProvider); }); } // TODO(scheglov) Implement notifications for AnalysisService.IMPLEMENTED. @@ -1303,14 +943,15 @@ builderOptions.defaultOptions = options; builderOptions.defaultPackageFilePath = defaultPackageFilePath; builderOptions.defaultPackagesDirectoryPath = defaultPackagesDirectoryPath; - ContextBuilder builder = new ContextBuilder(resourceProvider, - analysisServer.sdkManager, analysisServer.overlayState, + ContextBuilder builder = new ContextBuilder( + resourceProvider, analysisServer.sdkManager, null, options: builderOptions); builder.fileResolverProvider = analysisServer.fileResolverProvider; builder.packageResolverProvider = analysisServer.packageResolverProvider; builder.analysisDriverScheduler = analysisServer.analysisDriverScheduler; builder.performanceLog = analysisServer._analysisPerformanceLogger; builder.byteStore = analysisServer.byteStore; + builder.enableIndex = true; builder.fileContentOverlay = analysisServer.fileContentOverlay; return builder; } @@ -1347,7 +988,7 @@ server.AnalysisNavigationParams _computeNavigationParams( String path, CompilationUnit unit) { NavigationCollectorImpl collector = new NavigationCollectorImpl(); - computeDartNavigation(collector, unit, null, null); + computeDartNavigation(resourceProvider, collector, unit, null, null); collector.createRegions(); return new server.AnalysisNavigationParams( path, collector.regions, collector.targets, collector.files); @@ -1382,29 +1023,25 @@ libraryName: libraryName); } - /** - * Run [f] in a new [Future]. - * - * This method is used to delay sending notifications. If there is a more - * important consumer of an analysis results, specifically a code completion - * computer, we want it to run before spending time of sending notifications. - * - * TODO(scheglov) Consider replacing this with full priority based scheduler. - * - * TODO(scheglov) Alternatively, if code completion work in a way that does - * not produce (at first) fully resolved unit, but only part of it - a single - * method, or a top-level declaration, we would not have this problem - the - * completion computer would be the only consumer of the partial analysis - * result. - */ + /// Run [f] in a new [Future]. + /// + /// This method is used to delay sending notifications. If there is a more + /// important consumer of an analysis results, specifically a code completion + /// computer, we want it to run before spending time of sending notifications. + /// + /// TODO(scheglov) Consider replacing this with full priority based scheduler. + /// + /// TODO(scheglov) Alternatively, if code completion work in a way that does + /// not produce (at first) fully resolved unit, but only part of it - a single + /// method, or a top-level declaration, we would not have this problem - the + /// completion computer would be the only consumer of the partial analysis + /// result. void _runDelayed(f()) { new Future(f); } } -/** - * Used to record server exceptions. - */ +/// Used to record server exceptions. class ServerException { final String message; final dynamic exception; @@ -1417,40 +1054,26 @@ String toString() => message; } -/** - * A class used by [AnalysisServer] to record performance information - * such as request latency. - */ +/// A class used by [AnalysisServer] to record performance information +/// such as request latency. class ServerPerformance { - /** - * The creation time and the time when performance information - * started to be recorded here. - */ + /// The creation time and the time when performance information + /// started to be recorded here. final int startTime = new DateTime.now().millisecondsSinceEpoch; - /** - * The number of requests. - */ + /// The number of requests. int requestCount = 0; - /** - * The total latency (milliseconds) for all recorded requests. - */ + /// The total latency (milliseconds) for all recorded requests. int requestLatency = 0; - /** - * The maximum latency (milliseconds) for all recorded requests. - */ + /// The maximum latency (milliseconds) for all recorded requests. int maxLatency = 0; - /** - * The number of requests with latency > 150 milliseconds. - */ + /// The number of requests with latency > 150 milliseconds. int slowRequestCount = 0; - /** - * Log performance information about the given request. - */ + /// Log performance information about the given request. void logRequest(Request request) { ++requestCount; if (request.clientRequestTime != null) { @@ -1465,34 +1088,22 @@ } } -/** - * Container with global [AnalysisServer] performance statistics. - */ +/// Container with global [AnalysisServer] performance statistics. class ServerPerformanceStatistics { - /** - * The [PerformanceTag] for `package:analysis_server`. - */ + /// The [PerformanceTag] for `package:analysis_server`. static final PerformanceTag server = new PerformanceTag('server'); - /** - * The [PerformanceTag] for time spent between calls to - * AnalysisServer.performOperation when the server is idle. - */ + /// The [PerformanceTag] for time spent between calls to + /// AnalysisServer.performOperation when the server is idle. static final PerformanceTag idle = new PerformanceTag('idle'); - /** - * The [PerformanceTag] for time spent in - * PerformAnalysisOperation._sendNotices. - */ + /// The [PerformanceTag] for time spent in + /// PerformAnalysisOperation._sendNotices. static final PerformanceTag notices = server.createChild('notices'); - /** - * The [PerformanceTag] for time spent in server communication channels. - */ + /// The [PerformanceTag] for time spent in server communication channels. static final PerformanceTag serverChannel = server.createChild('channel'); - /** - * The [PerformanceTag] for time spent in server request handlers. - */ + /// The [PerformanceTag] for time spent in server request handlers. static final PerformanceTag serverRequests = server.createChild('requests'); }
diff --git a/pkg/analysis_server/lib/src/analysis_server_abstract.dart b/pkg/analysis_server/lib/src/analysis_server_abstract.dart new file mode 100644 index 0000000..20a6559 --- /dev/null +++ b/pkg/analysis_server/lib/src/analysis_server_abstract.dart
@@ -0,0 +1,200 @@ +// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'dart:async'; +import 'dart:core'; + +import 'package:analysis_server/src/context_manager.dart'; +import 'package:analysis_server/src/services/correction/namespace.dart'; +import 'package:analysis_server/src/services/search/element_visitors.dart'; +import 'package:analyzer/dart/analysis/results.dart'; +import 'package:analyzer/dart/ast/ast.dart'; +import 'package:analyzer/dart/element/element.dart'; +import 'package:analyzer/exception/exception.dart'; +import 'package:analyzer/file_system/file_system.dart'; +import 'package:analyzer/file_system/physical_file_system.dart'; +import 'package:analyzer/src/dart/analysis/byte_store.dart'; +import 'package:analyzer/src/dart/analysis/driver.dart' as nd; +import 'package:analyzer/src/dart/analysis/file_byte_store.dart' + show EvictingFileByteStore; +import 'package:analyzer/src/dart/analysis/file_state.dart' as nd; +import 'package:analyzer/src/dart/analysis/status.dart' as nd; +import 'package:analyzer/src/dart/ast/utilities.dart'; +import 'package:analyzer/src/generated/engine.dart'; +import 'package:analyzer/src/util/glob.dart'; + +/// Implementations of [AbstractAnalysisServer] implement a server that listens +/// on a [CommunicationChannel] for analysis messages and process them. +abstract class AbstractAnalysisServer { + /// The [ContextManager] that handles the mapping from analysis roots to + /// context directories. + ContextManager contextManager; + + /// The set of the files that are currently priority. + final Set<String> priorityFiles = new Set<String>(); + + final List<String> analyzableFilePatterns = <String>[ + '**/*.${AnalysisEngine.SUFFIX_DART}', + '**/*.${AnalysisEngine.SUFFIX_HTML}', + '**/*.${AnalysisEngine.SUFFIX_HTM}', + '**/${AnalysisEngine.ANALYSIS_OPTIONS_FILE}', + '**/${AnalysisEngine.ANALYSIS_OPTIONS_YAML_FILE}', + '**/${AnalysisEngine.PUBSPEC_YAML_FILE}' + ]; + + /// The [ResourceProvider] using which paths are converted into [Resource]s. + final ResourceProvider resourceProvider; + + /// A list of the globs used to determine which files should be analyzed. The + /// list is lazily created and should be accessed using [analyzedFilesGlobs]. + List<Glob> _analyzedFilesGlobs = null; + + AbstractAnalysisServer(this.resourceProvider); + + /// Return a list of the globs used to determine which files should be + /// analyzed. + List<Glob> get analyzedFilesGlobs { + if (_analyzedFilesGlobs == null) { + _analyzedFilesGlobs = <Glob>[]; + for (String pattern in analyzableFilePatterns) { + try { + _analyzedFilesGlobs + .add(new Glob(resourceProvider.pathContext.separator, pattern)); + } catch (exception, stackTrace) { + AnalysisEngine.instance.logger.logError( + 'Invalid glob pattern: "$pattern"', + new CaughtException(exception, stackTrace)); + } + } + } + return _analyzedFilesGlobs; + } + + /// A table mapping [Folder]s to the [AnalysisDriver]s associated with them. + Map<Folder, nd.AnalysisDriver> get driverMap => contextManager.driverMap; + + /// If the state location can be accessed, return the file byte store, + /// otherwise return the memory byte store. + ByteStore createByteStore(ResourceProvider resourceProvider) { + const int M = 1024 * 1024 /*1 MiB*/; + const int G = 1024 * 1024 * 1024 /*1 GiB*/; + + const int memoryCacheSize = 128 * M; + + if (resourceProvider is PhysicalResourceProvider) { + Folder stateLocation = + resourceProvider.getStateLocation('.analysis-driver'); + if (stateLocation != null) { + return new MemoryCachingByteStore( + new EvictingFileByteStore(stateLocation.path, G), memoryCacheSize); + } + } + + return new MemoryCachingByteStore(new NullByteStore(), memoryCacheSize); + } + + /// Return an analysis driver to which the file with the given [path] is + /// added if one exists, otherwise a driver in which the file was analyzed if + /// one exists, otherwise the first driver, otherwise `null`. + nd.AnalysisDriver getAnalysisDriver(String path) { + List<nd.AnalysisDriver> drivers = driverMap.values.toList(); + if (drivers.isNotEmpty) { + // Sort the drivers so that more deeply nested contexts will be checked + // before enclosing contexts. + drivers.sort((first, second) => + second.contextRoot.root.length - first.contextRoot.root.length); + nd.AnalysisDriver driver = drivers.firstWhere( + (driver) => driver.contextRoot.containsFile(path), + orElse: () => null); + driver ??= drivers.firstWhere( + (driver) => driver.knownFiles.contains(path), + orElse: () => null); + driver ??= drivers.first; + return driver; + } + return null; + } + + /// Return a [Future] that completes with the [Element] at the given + /// [offset] of the given [file], or with `null` if there is no node at the + /// [offset] or the node does not have an element. + Future<Element> getElementAtOffset(String file, int offset) async { + // TODO(brianwilkerson) Determine whether this await is necessary. + await null; + if (!priorityFiles.contains(file)) { + var driver = getAnalysisDriver(file); + if (driver == null) { + return null; + } + + var unitElementResult = await driver.getUnitElement(file); + if (unitElementResult == null) { + return null; + } + + var element = findElementByNameOffset(unitElementResult.element, offset); + if (element != null) { + return element; + } + } + + AstNode node = await getNodeAtOffset(file, offset); + return getElementOfNode(node); + } + + /// Return the [Element] of the given [node], or `null` if [node] is `null` or + /// does not have an element. + Element getElementOfNode(AstNode node) { + if (node == null) { + return null; + } + if (node is SimpleIdentifier && node.parent is LibraryIdentifier) { + node = node.parent; + } + if (node is LibraryIdentifier) { + node = node.parent; + } + if (node is StringLiteral && node.parent is UriBasedDirective) { + return null; + } + Element element = ElementLocator.locate(node); + if (node is SimpleIdentifier && element is PrefixElement) { + element = getImportElement(node); + } + return element; + } + + /// Return a [Future] that completes with the resolved [AstNode] at the + /// given [offset] of the given [file], or with `null` if there is no node as + /// the [offset]. + Future<AstNode> getNodeAtOffset(String file, int offset) async { + // TODO(brianwilkerson) Determine whether this await is necessary. + await null; + ResolvedUnitResult result = await getResolvedUnit(file); + CompilationUnit unit = result?.unit; + if (unit != null) { + return new NodeLocator(offset).searchWithin(unit); + } + return null; + } + + /// Return the resolved unit for the file with the given [path]. The file is + /// analyzed in one of the analysis drivers to which the file was added, + /// otherwise in the first driver, otherwise `null` is returned. + Future<ResolvedUnitResult> getResolvedUnit(String path, + {bool sendCachedToStream: false}) { + if (!AnalysisEngine.isDartFileName(path)) { + return null; + } + + nd.AnalysisDriver driver = getAnalysisDriver(path); + if (driver == null) { + return new Future.value(); + } + + return driver + .getResult(path, sendCachedToStream: sendCachedToStream) + .catchError((_) => null); + } +}
diff --git a/pkg/analysis_server/lib/src/computer/computer_closingLabels.dart b/pkg/analysis_server/lib/src/computer/computer_closingLabels.dart index d1fe2d4..19ff554 100644 --- a/pkg/analysis_server/lib/src/computer/computer_closingLabels.dart +++ b/pkg/analysis_server/lib/src/computer/computer_closingLabels.dart
@@ -1,4 +1,4 @@ -// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file +// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. @@ -45,8 +45,7 @@ /** * An AST visitor for [DartUnitClosingLabelsComputer]. */ -class _DartUnitClosingLabelsComputerVisitor - extends RecursiveAstVisitor<Object> { +class _DartUnitClosingLabelsComputerVisitor extends RecursiveAstVisitor<void> { final DartUnitClosingLabelsComputer computer; int interpolatedStringsEntered = 0; @@ -57,7 +56,7 @@ ClosingLabel get _currentLabel => labelStack.isEmpty ? null : labelStack.last; @override - Object visitInstanceCreationExpression(InstanceCreationExpression node) { + void visitInstanceCreationExpression(InstanceCreationExpression node) { ClosingLabel label; if (node.argumentList != null) { @@ -75,14 +74,14 @@ if (label != null) _pushLabel(label); try { - return super.visitInstanceCreationExpression(node); + super.visitInstanceCreationExpression(node); } finally { if (label != null) _popLabel(); } } @override - Object visitListLiteral(ListLiteral node) { + void visitListLiteral(ListLiteral node) { final NodeList<TypeAnnotation> args = node.typeArguments?.arguments; final String typeName = args != null ? args[0]?.toString() : null; @@ -95,17 +94,17 @@ if (label != null) _pushLabel(label); try { - return super.visitListLiteral(node); + super.visitListLiteral(node); } finally { if (label != null) _popLabel(); } } @override - Object visitStringInterpolation(StringInterpolation node) { + void visitStringInterpolation(StringInterpolation node) { interpolatedStringsEntered++; try { - return super.visitStringInterpolation(node); + super.visitStringInterpolation(node); } finally { interpolatedStringsEntered--; }
diff --git a/pkg/analysis_server/lib/src/computer/computer_folding.dart b/pkg/analysis_server/lib/src/computer/computer_folding.dart index 9488775..4edf2fc 100644 --- a/pkg/analysis_server/lib/src/computer/computer_folding.dart +++ b/pkg/analysis_server/lib/src/computer/computer_folding.dart
@@ -1,4 +1,4 @@ -// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. @@ -105,129 +105,129 @@ /** * An AST visitor for [DartUnitFoldingComputer]. */ -class _DartUnitFoldingComputerVisitor extends RecursiveAstVisitor<Object> { +class _DartUnitFoldingComputerVisitor extends RecursiveAstVisitor<void> { final DartUnitFoldingComputer _computer; _DartUnitFoldingComputerVisitor(this._computer); @override - Object visitBlockFunctionBody(BlockFunctionBody node) { + void visitBlockFunctionBody(BlockFunctionBody node) { _computer._addRegion(node.block.leftBracket.end, node.block.rightBracket.offset, FoldingKind.FUNCTION_BODY); - return super.visitBlockFunctionBody(node); + super.visitBlockFunctionBody(node); } @override - Object visitClassDeclaration(ClassDeclaration node) { + void visitClassDeclaration(ClassDeclaration node) { _computer._addRegionForAnnotations(node.metadata); _computer._addRegion( node.leftBracket.end, node.rightBracket.offset, FoldingKind.CLASS_BODY); - return super.visitClassDeclaration(node); + super.visitClassDeclaration(node); } @override - Object visitComment(Comment node) { + void visitComment(Comment node) { if (node.isDocumentation) { _computer._addRegion( node.offset, node.end, FoldingKind.DOCUMENTATION_COMMENT); } - return super.visitComment(node); + super.visitComment(node); } @override - Object visitConstructorDeclaration(ConstructorDeclaration node) { + void visitConstructorDeclaration(ConstructorDeclaration node) { _computer._addRegionForAnnotations(node.metadata); - return super.visitConstructorDeclaration(node); + super.visitConstructorDeclaration(node); } @override - Object visitExportDirective(ExportDirective node) { + void visitExportDirective(ExportDirective node) { _computer._recordDirective(node); - return super.visitExportDirective(node); + super.visitExportDirective(node); } @override - Object visitFieldDeclaration(FieldDeclaration node) { + void visitFieldDeclaration(FieldDeclaration node) { _computer._addRegionForAnnotations(node.metadata); - return super.visitFieldDeclaration(node); + super.visitFieldDeclaration(node); } @override - Object visitFunctionDeclaration(FunctionDeclaration node) { + void visitFunctionDeclaration(FunctionDeclaration node) { _computer._addRegionForAnnotations(node.metadata); - return super.visitFunctionDeclaration(node); + super.visitFunctionDeclaration(node); } @override - Object visitFunctionExpressionInvocation(FunctionExpressionInvocation node) { + void visitFunctionExpressionInvocation(FunctionExpressionInvocation node) { _computer._addRegion(node.argumentList.leftParenthesis.end, node.argumentList.rightParenthesis.offset, FoldingKind.INVOCATION); - return super.visitFunctionExpressionInvocation(node); + super.visitFunctionExpressionInvocation(node); } @override - visitImportDirective(ImportDirective node) { + void visitImportDirective(ImportDirective node) { _computer._recordDirective(node); - return super.visitImportDirective(node); + super.visitImportDirective(node); } @override - Object visitInstanceCreationExpression(InstanceCreationExpression node) { + void visitInstanceCreationExpression(InstanceCreationExpression node) { _computer._addRegion(node.argumentList.leftParenthesis.end, node.argumentList.rightParenthesis.offset, FoldingKind.INVOCATION); - return super.visitInstanceCreationExpression(node); + super.visitInstanceCreationExpression(node); } @override - Object visitLibraryDirective(LibraryDirective node) { + void visitLibraryDirective(LibraryDirective node) { _computer._recordDirective(node); - return super.visitLibraryDirective(node); + super.visitLibraryDirective(node); } @override - Object visitListLiteral(ListLiteral node) { + void visitListLiteral(ListLiteral node) { _computer._addRegion( node.leftBracket.end, node.rightBracket.offset, FoldingKind.LITERAL); - return super.visitListLiteral(node); + super.visitListLiteral(node); } @override - Object visitMapLiteral(MapLiteral node) { + void visitMapLiteral(MapLiteral node) { _computer._addRegion( node.leftBracket.end, node.rightBracket.offset, FoldingKind.LITERAL); - return super.visitMapLiteral(node); + super.visitMapLiteral(node); } @override - Object visitMethodDeclaration(MethodDeclaration node) { + void visitMethodDeclaration(MethodDeclaration node) { _computer._addRegionForAnnotations(node.metadata); - return super.visitMethodDeclaration(node); + super.visitMethodDeclaration(node); } @override - Object visitMethodInvocation(MethodInvocation node) { + void visitMethodInvocation(MethodInvocation node) { _computer._addRegion(node.argumentList.leftParenthesis.end, node.argumentList.rightParenthesis.offset, FoldingKind.INVOCATION); - return super.visitMethodInvocation(node); + super.visitMethodInvocation(node); } @override - Object visitMixinDeclaration(MixinDeclaration node) { + void visitMixinDeclaration(MixinDeclaration node) { _computer._addRegionForAnnotations(node.metadata); // TODO(brianwilkerson) Define `FoldingKind.MIXIN_BODY`? _computer._addRegion( node.leftBracket.end, node.rightBracket.offset, FoldingKind.CLASS_BODY); - return super.visitMixinDeclaration(node); + super.visitMixinDeclaration(node); } @override - Object visitPartDirective(PartDirective node) { + void visitPartDirective(PartDirective node) { _computer._recordDirective(node); - return super.visitPartDirective(node); + super.visitPartDirective(node); } @override - Object visitPartOfDirective(PartOfDirective node) { + void visitPartOfDirective(PartOfDirective node) { _computer._recordDirective(node); - return super.visitPartOfDirective(node); + super.visitPartOfDirective(node); } }
diff --git a/pkg/analysis_server/lib/src/computer/computer_highlights.dart b/pkg/analysis_server/lib/src/computer/computer_highlights.dart index b0b5d40..39c1e8e 100644 --- a/pkg/analysis_server/lib/src/computer/computer_highlights.dart +++ b/pkg/analysis_server/lib/src/computer/computer_highlights.dart
@@ -1,4 +1,4 @@ -// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file +// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. @@ -344,251 +344,251 @@ /** * An AST visitor for [DartUnitHighlightsComputer]. */ -class _DartUnitHighlightsComputerVisitor extends RecursiveAstVisitor<Object> { +class _DartUnitHighlightsComputerVisitor extends RecursiveAstVisitor<void> { final DartUnitHighlightsComputer computer; _DartUnitHighlightsComputerVisitor(this.computer); @override - Object visitAnnotation(Annotation node) { + void visitAnnotation(Annotation node) { computer._addIdentifierRegion_annotation(node); - return super.visitAnnotation(node); + super.visitAnnotation(node); } @override - Object visitAsExpression(AsExpression node) { + void visitAsExpression(AsExpression node) { computer._addRegion_token(node.asOperator, HighlightRegionType.BUILT_IN); - return super.visitAsExpression(node); + super.visitAsExpression(node); } @override - Object visitAssertStatement(AssertStatement node) { + void visitAssertStatement(AssertStatement node) { computer._addRegion_token(node.assertKeyword, HighlightRegionType.KEYWORD); - return super.visitAssertStatement(node); + super.visitAssertStatement(node); } @override - Object visitAwaitExpression(AwaitExpression node) { + void visitAwaitExpression(AwaitExpression node) { computer._addRegion_token(node.awaitKeyword, HighlightRegionType.BUILT_IN); - return super.visitAwaitExpression(node); + super.visitAwaitExpression(node); } @override - Object visitBlockFunctionBody(BlockFunctionBody node) { + void visitBlockFunctionBody(BlockFunctionBody node) { _addRegions_functionBody(node); - return super.visitBlockFunctionBody(node); + super.visitBlockFunctionBody(node); } @override - Object visitBooleanLiteral(BooleanLiteral node) { + void visitBooleanLiteral(BooleanLiteral node) { computer._addRegion_node(node, HighlightRegionType.KEYWORD); computer._addRegion_node(node, HighlightRegionType.LITERAL_BOOLEAN); - return super.visitBooleanLiteral(node); + super.visitBooleanLiteral(node); } @override - Object visitBreakStatement(BreakStatement node) { + void visitBreakStatement(BreakStatement node) { computer._addRegion_token(node.breakKeyword, HighlightRegionType.KEYWORD); - return super.visitBreakStatement(node); + super.visitBreakStatement(node); } @override - Object visitCatchClause(CatchClause node) { + void visitCatchClause(CatchClause node) { computer._addRegion_token(node.catchKeyword, HighlightRegionType.KEYWORD); computer._addRegion_token(node.onKeyword, HighlightRegionType.BUILT_IN); - return super.visitCatchClause(node); + super.visitCatchClause(node); } @override - Object visitClassDeclaration(ClassDeclaration node) { + void visitClassDeclaration(ClassDeclaration node) { computer._addRegion_token(node.classKeyword, HighlightRegionType.KEYWORD); computer._addRegion_token( node.abstractKeyword, HighlightRegionType.BUILT_IN); - return super.visitClassDeclaration(node); + super.visitClassDeclaration(node); } @override - Object visitClassTypeAlias(ClassTypeAlias node) { + void visitClassTypeAlias(ClassTypeAlias node) { computer._addRegion_token( node.abstractKeyword, HighlightRegionType.BUILT_IN); - return super.visitClassTypeAlias(node); + super.visitClassTypeAlias(node); } @override - Object visitConstructorDeclaration(ConstructorDeclaration node) { + void visitConstructorDeclaration(ConstructorDeclaration node) { computer._addRegion_token( node.externalKeyword, HighlightRegionType.BUILT_IN); computer._addRegion_token( node.factoryKeyword, HighlightRegionType.BUILT_IN); - return super.visitConstructorDeclaration(node); + super.visitConstructorDeclaration(node); } @override - Object visitContinueStatement(ContinueStatement node) { + void visitContinueStatement(ContinueStatement node) { computer._addRegion_token( node.continueKeyword, HighlightRegionType.KEYWORD); - return super.visitContinueStatement(node); + super.visitContinueStatement(node); } @override - Object visitDoStatement(DoStatement node) { + void visitDoStatement(DoStatement node) { computer._addRegion_token(node.doKeyword, HighlightRegionType.KEYWORD); computer._addRegion_token(node.whileKeyword, HighlightRegionType.KEYWORD); - return super.visitDoStatement(node); + super.visitDoStatement(node); } @override - Object visitDoubleLiteral(DoubleLiteral node) { + void visitDoubleLiteral(DoubleLiteral node) { computer._addRegion_node(node, HighlightRegionType.LITERAL_DOUBLE); - return super.visitDoubleLiteral(node); + super.visitDoubleLiteral(node); } @override - Object visitEnumDeclaration(EnumDeclaration node) { + void visitEnumDeclaration(EnumDeclaration node) { computer._addRegion_token(node.enumKeyword, HighlightRegionType.KEYWORD); - return super.visitEnumDeclaration(node); + super.visitEnumDeclaration(node); } @override - Object visitExportDirective(ExportDirective node) { + void visitExportDirective(ExportDirective node) { computer._addRegion_node(node, HighlightRegionType.DIRECTIVE); computer._addRegion_token(node.keyword, HighlightRegionType.BUILT_IN); - return super.visitExportDirective(node); + super.visitExportDirective(node); } @override - Object visitExpressionFunctionBody(ExpressionFunctionBody node) { + void visitExpressionFunctionBody(ExpressionFunctionBody node) { _addRegions_functionBody(node); - return super.visitExpressionFunctionBody(node); + super.visitExpressionFunctionBody(node); } @override - Object visitExtendsClause(ExtendsClause node) { + void visitExtendsClause(ExtendsClause node) { computer._addRegion_token(node.extendsKeyword, HighlightRegionType.KEYWORD); - return super.visitExtendsClause(node); + super.visitExtendsClause(node); } @override - Object visitFieldDeclaration(FieldDeclaration node) { + void visitFieldDeclaration(FieldDeclaration node) { computer._addRegion_token(node.staticKeyword, HighlightRegionType.BUILT_IN); - return super.visitFieldDeclaration(node); + super.visitFieldDeclaration(node); } @override - Object visitForEachStatement(ForEachStatement node) { + void visitForEachStatement(ForEachStatement node) { computer._addRegion_token(node.awaitKeyword, HighlightRegionType.BUILT_IN); computer._addRegion_token(node.forKeyword, HighlightRegionType.KEYWORD); computer._addRegion_token(node.inKeyword, HighlightRegionType.KEYWORD); - return super.visitForEachStatement(node); + super.visitForEachStatement(node); } @override - Object visitForStatement(ForStatement node) { + void visitForStatement(ForStatement node) { computer._addRegion_token(node.forKeyword, HighlightRegionType.KEYWORD); - return super.visitForStatement(node); + super.visitForStatement(node); } @override - Object visitFunctionDeclaration(FunctionDeclaration node) { + void visitFunctionDeclaration(FunctionDeclaration node) { computer._addRegion_token( node.externalKeyword, HighlightRegionType.BUILT_IN); computer._addRegion_token( node.propertyKeyword, HighlightRegionType.BUILT_IN); - return super.visitFunctionDeclaration(node); + super.visitFunctionDeclaration(node); } @override - Object visitFunctionTypeAlias(FunctionTypeAlias node) { + void visitFunctionTypeAlias(FunctionTypeAlias node) { computer._addRegion_token( node.typedefKeyword, HighlightRegionType.BUILT_IN); - return super.visitFunctionTypeAlias(node); + super.visitFunctionTypeAlias(node); } @override - Object visitGenericFunctionType(GenericFunctionType node) { + void visitGenericFunctionType(GenericFunctionType node) { computer._addRegion_token( node.functionKeyword, HighlightRegionType.KEYWORD); - return super.visitGenericFunctionType(node); + super.visitGenericFunctionType(node); } @override - Object visitGenericTypeAlias(GenericTypeAlias node) { + void visitGenericTypeAlias(GenericTypeAlias node) { computer._addRegion_token(node.typedefKeyword, HighlightRegionType.KEYWORD); - return super.visitGenericTypeAlias(node); + super.visitGenericTypeAlias(node); } @override - Object visitHideCombinator(HideCombinator node) { + void visitHideCombinator(HideCombinator node) { computer._addRegion_token(node.keyword, HighlightRegionType.BUILT_IN); - return super.visitHideCombinator(node); + super.visitHideCombinator(node); } @override - Object visitIfStatement(IfStatement node) { + void visitIfStatement(IfStatement node) { computer._addRegion_token(node.ifKeyword, HighlightRegionType.KEYWORD); - return super.visitIfStatement(node); + super.visitIfStatement(node); } @override - Object visitImplementsClause(ImplementsClause node) { + void visitImplementsClause(ImplementsClause node) { computer._addRegion_token( node.implementsKeyword, HighlightRegionType.BUILT_IN); - return super.visitImplementsClause(node); + super.visitImplementsClause(node); } @override - Object visitImportDirective(ImportDirective node) { + void visitImportDirective(ImportDirective node) { computer._addRegion_node(node, HighlightRegionType.DIRECTIVE); computer._addRegion_token(node.keyword, HighlightRegionType.BUILT_IN); computer._addRegion_token( node.deferredKeyword, HighlightRegionType.BUILT_IN); computer._addRegion_token(node.asKeyword, HighlightRegionType.BUILT_IN); - return super.visitImportDirective(node); + super.visitImportDirective(node); } @override - Object visitInstanceCreationExpression(InstanceCreationExpression node) { + void visitInstanceCreationExpression(InstanceCreationExpression node) { if (node.keyword != null) { computer._addRegion_token(node.keyword, HighlightRegionType.KEYWORD); } - return super.visitInstanceCreationExpression(node); + super.visitInstanceCreationExpression(node); } @override - Object visitIntegerLiteral(IntegerLiteral node) { + void visitIntegerLiteral(IntegerLiteral node) { computer._addRegion_node(node, HighlightRegionType.LITERAL_INTEGER); - return super.visitIntegerLiteral(node); + super.visitIntegerLiteral(node); } @override - Object visitIsExpression(IsExpression node) { + void visitIsExpression(IsExpression node) { computer._addRegion_token(node.isOperator, HighlightRegionType.KEYWORD); - return super.visitIsExpression(node); + super.visitIsExpression(node); } @override - Object visitLibraryDirective(LibraryDirective node) { + void visitLibraryDirective(LibraryDirective node) { computer._addRegion_node(node, HighlightRegionType.DIRECTIVE); computer._addRegion_token(node.keyword, HighlightRegionType.BUILT_IN); - return super.visitLibraryDirective(node); + super.visitLibraryDirective(node); } @override - Object visitListLiteral(ListLiteral node) { + void visitListLiteral(ListLiteral node) { computer._addRegion_node(node, HighlightRegionType.LITERAL_LIST); computer._addRegion_token(node.constKeyword, HighlightRegionType.KEYWORD); - return super.visitListLiteral(node); + super.visitListLiteral(node); } @override - Object visitMapLiteral(MapLiteral node) { + void visitMapLiteral(MapLiteral node) { computer._addRegion_node(node, HighlightRegionType.LITERAL_MAP); computer._addRegion_token(node.constKeyword, HighlightRegionType.KEYWORD); - return super.visitMapLiteral(node); + super.visitMapLiteral(node); } @override - Object visitMethodDeclaration(MethodDeclaration node) { + void visitMethodDeclaration(MethodDeclaration node) { computer._addRegion_token( node.externalKeyword, HighlightRegionType.BUILT_IN); computer._addRegion_token( @@ -597,117 +597,117 @@ node.operatorKeyword, HighlightRegionType.BUILT_IN); computer._addRegion_token( node.propertyKeyword, HighlightRegionType.BUILT_IN); - return super.visitMethodDeclaration(node); + super.visitMethodDeclaration(node); } @override - Object visitMixinDeclaration(MixinDeclaration node) { + void visitMixinDeclaration(MixinDeclaration node) { computer._addRegion_token(node.mixinKeyword, HighlightRegionType.BUILT_IN); - return super.visitMixinDeclaration(node); + super.visitMixinDeclaration(node); } @override - Object visitNativeClause(NativeClause node) { + void visitNativeClause(NativeClause node) { computer._addRegion_token(node.nativeKeyword, HighlightRegionType.BUILT_IN); - return super.visitNativeClause(node); + super.visitNativeClause(node); } @override - Object visitNativeFunctionBody(NativeFunctionBody node) { + void visitNativeFunctionBody(NativeFunctionBody node) { computer._addRegion_token(node.nativeKeyword, HighlightRegionType.BUILT_IN); - return super.visitNativeFunctionBody(node); + super.visitNativeFunctionBody(node); } @override - Object visitOnClause(OnClause node) { + void visitOnClause(OnClause node) { computer._addRegion_token(node.onKeyword, HighlightRegionType.BUILT_IN); - return super.visitOnClause(node); + super.visitOnClause(node); } @override - Object visitPartDirective(PartDirective node) { + void visitPartDirective(PartDirective node) { computer._addRegion_node(node, HighlightRegionType.DIRECTIVE); computer._addRegion_token(node.keyword, HighlightRegionType.BUILT_IN); - return super.visitPartDirective(node); + super.visitPartDirective(node); } @override - Object visitPartOfDirective(PartOfDirective node) { + void visitPartOfDirective(PartOfDirective node) { computer._addRegion_node(node, HighlightRegionType.DIRECTIVE); computer._addRegion_tokenStart_tokenEnd( node.partKeyword, node.ofKeyword, HighlightRegionType.BUILT_IN); - return super.visitPartOfDirective(node); + super.visitPartOfDirective(node); } @override - Object visitRethrowExpression(RethrowExpression node) { + void visitRethrowExpression(RethrowExpression node) { computer._addRegion_token(node.rethrowKeyword, HighlightRegionType.KEYWORD); - return super.visitRethrowExpression(node); + super.visitRethrowExpression(node); } @override - Object visitReturnStatement(ReturnStatement node) { + void visitReturnStatement(ReturnStatement node) { computer._addRegion_token(node.returnKeyword, HighlightRegionType.KEYWORD); - return super.visitReturnStatement(node); + super.visitReturnStatement(node); } @override - Object visitShowCombinator(ShowCombinator node) { + void visitShowCombinator(ShowCombinator node) { computer._addRegion_token(node.keyword, HighlightRegionType.BUILT_IN); - return super.visitShowCombinator(node); + super.visitShowCombinator(node); } @override - Object visitSimpleIdentifier(SimpleIdentifier node) { + void visitSimpleIdentifier(SimpleIdentifier node) { computer._addIdentifierRegion(node); - return super.visitSimpleIdentifier(node); + super.visitSimpleIdentifier(node); } @override - Object visitSimpleStringLiteral(SimpleStringLiteral node) { + void visitSimpleStringLiteral(SimpleStringLiteral node) { computer._addRegion_node(node, HighlightRegionType.LITERAL_STRING); - return super.visitSimpleStringLiteral(node); + super.visitSimpleStringLiteral(node); } @override - Object visitSuperConstructorInvocation(SuperConstructorInvocation node) { + void visitSuperConstructorInvocation(SuperConstructorInvocation node) { computer._addRegion_token(node.superKeyword, HighlightRegionType.KEYWORD); - return super.visitSuperConstructorInvocation(node); + super.visitSuperConstructorInvocation(node); } @override - Object visitSwitchCase(SwitchCase node) { + void visitSwitchCase(SwitchCase node) { computer._addRegion_token(node.keyword, HighlightRegionType.KEYWORD); - return super.visitSwitchCase(node); + super.visitSwitchCase(node); } @override - Object visitSwitchDefault(SwitchDefault node) { + void visitSwitchDefault(SwitchDefault node) { computer._addRegion_token(node.keyword, HighlightRegionType.KEYWORD); - return super.visitSwitchDefault(node); + super.visitSwitchDefault(node); } @override - Object visitSwitchStatement(SwitchStatement node) { + void visitSwitchStatement(SwitchStatement node) { computer._addRegion_token(node.switchKeyword, HighlightRegionType.KEYWORD); - return super.visitSwitchStatement(node); + super.visitSwitchStatement(node); } @override - Object visitThisExpression(ThisExpression node) { + void visitThisExpression(ThisExpression node) { computer._addRegion_token(node.thisKeyword, HighlightRegionType.KEYWORD); - return super.visitThisExpression(node); + super.visitThisExpression(node); } @override - Object visitTryStatement(TryStatement node) { + void visitTryStatement(TryStatement node) { computer._addRegion_token(node.tryKeyword, HighlightRegionType.KEYWORD); computer._addRegion_token(node.finallyKeyword, HighlightRegionType.KEYWORD); - return super.visitTryStatement(node); + super.visitTryStatement(node); } @override - Object visitTypeName(TypeName node) { + void visitTypeName(TypeName node) { DartType type = node.type; if (type != null) { if (type.isDynamic && node.name.name == "dynamic") { @@ -715,35 +715,35 @@ return null; } } - return super.visitTypeName(node); + super.visitTypeName(node); } @override - Object visitVariableDeclarationList(VariableDeclarationList node) { + void visitVariableDeclarationList(VariableDeclarationList node) { computer._addRegion_token(node.keyword, HighlightRegionType.KEYWORD); - return super.visitVariableDeclarationList(node); + super.visitVariableDeclarationList(node); } @override - Object visitWhileStatement(WhileStatement node) { + void visitWhileStatement(WhileStatement node) { computer._addRegion_token(node.whileKeyword, HighlightRegionType.KEYWORD); - return super.visitWhileStatement(node); + super.visitWhileStatement(node); } @override - Object visitWithClause(WithClause node) { + void visitWithClause(WithClause node) { computer._addRegion_token(node.withKeyword, HighlightRegionType.KEYWORD); - return super.visitWithClause(node); + super.visitWithClause(node); } @override - Object visitYieldStatement(YieldStatement node) { + void visitYieldStatement(YieldStatement node) { Token keyword = node.yieldKeyword; Token star = node.star; int offset = keyword.offset; int end = star != null ? star.end : keyword.end; computer._addRegion(offset, end - offset, HighlightRegionType.BUILT_IN); - return super.visitYieldStatement(node); + super.visitYieldStatement(node); } void _addRegions_functionBody(FunctionBody node) {
diff --git a/pkg/analysis_server/lib/src/computer/computer_highlights2.dart b/pkg/analysis_server/lib/src/computer/computer_highlights2.dart index dad226c..6ae85e2 100644 --- a/pkg/analysis_server/lib/src/computer/computer_highlights2.dart +++ b/pkg/analysis_server/lib/src/computer/computer_highlights2.dart
@@ -1,4 +1,4 @@ -// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file +// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. @@ -435,257 +435,257 @@ /** * An AST visitor for [DartUnitHighlightsComputer2]. */ -class _DartUnitHighlightsComputerVisitor2 extends RecursiveAstVisitor<Object> { +class _DartUnitHighlightsComputerVisitor2 extends RecursiveAstVisitor<void> { final DartUnitHighlightsComputer2 computer; _DartUnitHighlightsComputerVisitor2(this.computer); @override - Object visitAnnotation(Annotation node) { + void visitAnnotation(Annotation node) { computer._addIdentifierRegion_annotation(node); - return super.visitAnnotation(node); + super.visitAnnotation(node); } @override - Object visitAsExpression(AsExpression node) { + void visitAsExpression(AsExpression node) { computer._addRegion_token(node.asOperator, HighlightRegionType.BUILT_IN); - return super.visitAsExpression(node); + super.visitAsExpression(node); } @override - Object visitAssertStatement(AssertStatement node) { + void visitAssertStatement(AssertStatement node) { computer._addRegion_token(node.assertKeyword, HighlightRegionType.KEYWORD); - return super.visitAssertStatement(node); + super.visitAssertStatement(node); } @override - Object visitAwaitExpression(AwaitExpression node) { + void visitAwaitExpression(AwaitExpression node) { computer._addRegion_token(node.awaitKeyword, HighlightRegionType.BUILT_IN); - return super.visitAwaitExpression(node); + super.visitAwaitExpression(node); } @override - Object visitBlockFunctionBody(BlockFunctionBody node) { + void visitBlockFunctionBody(BlockFunctionBody node) { _addRegions_functionBody(node); - return super.visitBlockFunctionBody(node); + super.visitBlockFunctionBody(node); } @override - Object visitBooleanLiteral(BooleanLiteral node) { + void visitBooleanLiteral(BooleanLiteral node) { computer._addRegion_node(node, HighlightRegionType.KEYWORD); computer._addRegion_node(node, HighlightRegionType.LITERAL_BOOLEAN); - return super.visitBooleanLiteral(node); + super.visitBooleanLiteral(node); } @override - Object visitBreakStatement(BreakStatement node) { + void visitBreakStatement(BreakStatement node) { computer._addRegion_token(node.breakKeyword, HighlightRegionType.KEYWORD); - return super.visitBreakStatement(node); + super.visitBreakStatement(node); } @override - Object visitCatchClause(CatchClause node) { + void visitCatchClause(CatchClause node) { computer._addRegion_token(node.catchKeyword, HighlightRegionType.KEYWORD); computer._addRegion_token(node.onKeyword, HighlightRegionType.BUILT_IN); - return super.visitCatchClause(node); + super.visitCatchClause(node); } @override - Object visitClassDeclaration(ClassDeclaration node) { + void visitClassDeclaration(ClassDeclaration node) { computer._addRegion_token(node.classKeyword, HighlightRegionType.KEYWORD); computer._addRegion_token( node.abstractKeyword, HighlightRegionType.BUILT_IN); - return super.visitClassDeclaration(node); + super.visitClassDeclaration(node); } @override - Object visitClassTypeAlias(ClassTypeAlias node) { + void visitClassTypeAlias(ClassTypeAlias node) { computer._addRegion_token( node.abstractKeyword, HighlightRegionType.BUILT_IN); - return super.visitClassTypeAlias(node); + super.visitClassTypeAlias(node); } @override - Object visitConstructorDeclaration(ConstructorDeclaration node) { + void visitConstructorDeclaration(ConstructorDeclaration node) { computer._addRegion_token( node.externalKeyword, HighlightRegionType.BUILT_IN); computer._addRegion_token( node.factoryKeyword, HighlightRegionType.BUILT_IN); - return super.visitConstructorDeclaration(node); + super.visitConstructorDeclaration(node); } @override - Object visitContinueStatement(ContinueStatement node) { + void visitContinueStatement(ContinueStatement node) { computer._addRegion_token( node.continueKeyword, HighlightRegionType.KEYWORD); - return super.visitContinueStatement(node); + super.visitContinueStatement(node); } @override - Object visitDoStatement(DoStatement node) { + void visitDoStatement(DoStatement node) { computer._addRegion_token(node.doKeyword, HighlightRegionType.KEYWORD); computer._addRegion_token(node.whileKeyword, HighlightRegionType.KEYWORD); - return super.visitDoStatement(node); + super.visitDoStatement(node); } @override - Object visitDoubleLiteral(DoubleLiteral node) { + void visitDoubleLiteral(DoubleLiteral node) { computer._addRegion_node(node, HighlightRegionType.LITERAL_DOUBLE); - return super.visitDoubleLiteral(node); + super.visitDoubleLiteral(node); } @override - Object visitEnumDeclaration(EnumDeclaration node) { + void visitEnumDeclaration(EnumDeclaration node) { computer._addRegion_token(node.enumKeyword, HighlightRegionType.KEYWORD); - return super.visitEnumDeclaration(node); + super.visitEnumDeclaration(node); } @override - Object visitExportDirective(ExportDirective node) { + void visitExportDirective(ExportDirective node) { computer._addRegion_node(node, HighlightRegionType.DIRECTIVE); computer._addRegion_token(node.keyword, HighlightRegionType.BUILT_IN); - return super.visitExportDirective(node); + super.visitExportDirective(node); } @override - Object visitExpressionFunctionBody(ExpressionFunctionBody node) { + void visitExpressionFunctionBody(ExpressionFunctionBody node) { _addRegions_functionBody(node); - return super.visitExpressionFunctionBody(node); + super.visitExpressionFunctionBody(node); } @override - Object visitExtendsClause(ExtendsClause node) { + void visitExtendsClause(ExtendsClause node) { computer._addRegion_token(node.extendsKeyword, HighlightRegionType.KEYWORD); - return super.visitExtendsClause(node); + super.visitExtendsClause(node); } @override - Object visitFieldDeclaration(FieldDeclaration node) { + void visitFieldDeclaration(FieldDeclaration node) { computer._addRegion_token(node.staticKeyword, HighlightRegionType.BUILT_IN); - return super.visitFieldDeclaration(node); + super.visitFieldDeclaration(node); } @override - Object visitForEachStatement(ForEachStatement node) { + void visitForEachStatement(ForEachStatement node) { computer._addRegion_token(node.awaitKeyword, HighlightRegionType.BUILT_IN); computer._addRegion_token(node.forKeyword, HighlightRegionType.KEYWORD); computer._addRegion_token(node.inKeyword, HighlightRegionType.KEYWORD); - return super.visitForEachStatement(node); + super.visitForEachStatement(node); } @override - Object visitForStatement(ForStatement node) { + void visitForStatement(ForStatement node) { computer._addRegion_token(node.forKeyword, HighlightRegionType.KEYWORD); - return super.visitForStatement(node); + super.visitForStatement(node); } @override - Object visitFunctionDeclaration(FunctionDeclaration node) { + void visitFunctionDeclaration(FunctionDeclaration node) { computer._addRegion_token( node.externalKeyword, HighlightRegionType.BUILT_IN); computer._addRegion_token( node.propertyKeyword, HighlightRegionType.BUILT_IN); - return super.visitFunctionDeclaration(node); + super.visitFunctionDeclaration(node); } @override - Object visitFunctionTypeAlias(FunctionTypeAlias node) { + void visitFunctionTypeAlias(FunctionTypeAlias node) { computer._addRegion_token( node.typedefKeyword, HighlightRegionType.BUILT_IN); - return super.visitFunctionTypeAlias(node); + super.visitFunctionTypeAlias(node); } @override - Object visitGenericFunctionType(GenericFunctionType node) { + void visitGenericFunctionType(GenericFunctionType node) { computer._addRegion_token( node.functionKeyword, HighlightRegionType.KEYWORD); - return super.visitGenericFunctionType(node); + super.visitGenericFunctionType(node); } @override - Object visitGenericTypeAlias(GenericTypeAlias node) { + void visitGenericTypeAlias(GenericTypeAlias node) { computer._addRegion_token(node.typedefKeyword, HighlightRegionType.KEYWORD); - return super.visitGenericTypeAlias(node); + super.visitGenericTypeAlias(node); } @override - Object visitHideCombinator(HideCombinator node) { + void visitHideCombinator(HideCombinator node) { computer._addRegion_token(node.keyword, HighlightRegionType.BUILT_IN); - return super.visitHideCombinator(node); + super.visitHideCombinator(node); } @override - Object visitIfStatement(IfStatement node) { + void visitIfStatement(IfStatement node) { computer._addRegion_token(node.ifKeyword, HighlightRegionType.KEYWORD); - return super.visitIfStatement(node); + super.visitIfStatement(node); } @override - Object visitImplementsClause(ImplementsClause node) { + void visitImplementsClause(ImplementsClause node) { computer._addRegion_token( node.implementsKeyword, HighlightRegionType.BUILT_IN); - return super.visitImplementsClause(node); + super.visitImplementsClause(node); } @override - Object visitImportDirective(ImportDirective node) { + void visitImportDirective(ImportDirective node) { computer._addRegion_node(node, HighlightRegionType.DIRECTIVE); computer._addRegion_token(node.keyword, HighlightRegionType.BUILT_IN); computer._addRegion_token( node.deferredKeyword, HighlightRegionType.BUILT_IN); computer._addRegion_token(node.asKeyword, HighlightRegionType.BUILT_IN); - return super.visitImportDirective(node); + super.visitImportDirective(node); } @override - Object visitInstanceCreationExpression(InstanceCreationExpression node) { + void visitInstanceCreationExpression(InstanceCreationExpression node) { if (node.keyword != null) { computer._addRegion_token(node.keyword, HighlightRegionType.KEYWORD); } - return super.visitInstanceCreationExpression(node); + super.visitInstanceCreationExpression(node); } @override - Object visitIntegerLiteral(IntegerLiteral node) { + void visitIntegerLiteral(IntegerLiteral node) { computer._addRegion_node(node, HighlightRegionType.LITERAL_INTEGER); - return super.visitIntegerLiteral(node); + super.visitIntegerLiteral(node); } @override - Object visitIsExpression(IsExpression node) { + void visitIsExpression(IsExpression node) { computer._addRegion_token(node.isOperator, HighlightRegionType.KEYWORD); - return super.visitIsExpression(node); + super.visitIsExpression(node); } @override - Object visitLibraryDirective(LibraryDirective node) { + void visitLibraryDirective(LibraryDirective node) { computer._addRegion_node(node, HighlightRegionType.DIRECTIVE); computer._addRegion_token(node.keyword, HighlightRegionType.BUILT_IN); - return super.visitLibraryDirective(node); + super.visitLibraryDirective(node); } @override - Object visitLibraryIdentifier(LibraryIdentifier node) { + void visitLibraryIdentifier(LibraryIdentifier node) { computer._addRegion_node(node, HighlightRegionType.LIBRARY_NAME); - return null; + null; } @override - Object visitListLiteral(ListLiteral node) { + void visitListLiteral(ListLiteral node) { computer._addRegion_node(node, HighlightRegionType.LITERAL_LIST); computer._addRegion_token(node.constKeyword, HighlightRegionType.KEYWORD); - return super.visitListLiteral(node); + super.visitListLiteral(node); } @override - Object visitMapLiteral(MapLiteral node) { + void visitMapLiteral(MapLiteral node) { computer._addRegion_node(node, HighlightRegionType.LITERAL_MAP); computer._addRegion_token(node.constKeyword, HighlightRegionType.KEYWORD); - return super.visitMapLiteral(node); + super.visitMapLiteral(node); } @override - Object visitMethodDeclaration(MethodDeclaration node) { + void visitMethodDeclaration(MethodDeclaration node) { computer._addRegion_token( node.externalKeyword, HighlightRegionType.BUILT_IN); computer._addRegion_token( @@ -694,117 +694,117 @@ node.operatorKeyword, HighlightRegionType.BUILT_IN); computer._addRegion_token( node.propertyKeyword, HighlightRegionType.BUILT_IN); - return super.visitMethodDeclaration(node); + super.visitMethodDeclaration(node); } @override - Object visitMixinDeclaration(MixinDeclaration node) { + void visitMixinDeclaration(MixinDeclaration node) { computer._addRegion_token(node.mixinKeyword, HighlightRegionType.BUILT_IN); - return super.visitMixinDeclaration(node); + super.visitMixinDeclaration(node); } @override - Object visitNativeClause(NativeClause node) { + void visitNativeClause(NativeClause node) { computer._addRegion_token(node.nativeKeyword, HighlightRegionType.BUILT_IN); - return super.visitNativeClause(node); + super.visitNativeClause(node); } @override - Object visitNativeFunctionBody(NativeFunctionBody node) { + void visitNativeFunctionBody(NativeFunctionBody node) { computer._addRegion_token(node.nativeKeyword, HighlightRegionType.BUILT_IN); - return super.visitNativeFunctionBody(node); + super.visitNativeFunctionBody(node); } @override - Object visitOnClause(OnClause node) { + void visitOnClause(OnClause node) { computer._addRegion_token(node.onKeyword, HighlightRegionType.BUILT_IN); - return super.visitOnClause(node); + super.visitOnClause(node); } @override - Object visitPartDirective(PartDirective node) { + void visitPartDirective(PartDirective node) { computer._addRegion_node(node, HighlightRegionType.DIRECTIVE); computer._addRegion_token(node.keyword, HighlightRegionType.BUILT_IN); - return super.visitPartDirective(node); + super.visitPartDirective(node); } @override - Object visitPartOfDirective(PartOfDirective node) { + void visitPartOfDirective(PartOfDirective node) { computer._addRegion_node(node, HighlightRegionType.DIRECTIVE); computer._addRegion_tokenStart_tokenEnd( node.partKeyword, node.ofKeyword, HighlightRegionType.BUILT_IN); - return super.visitPartOfDirective(node); + super.visitPartOfDirective(node); } @override - Object visitRethrowExpression(RethrowExpression node) { + void visitRethrowExpression(RethrowExpression node) { computer._addRegion_token(node.rethrowKeyword, HighlightRegionType.KEYWORD); - return super.visitRethrowExpression(node); + super.visitRethrowExpression(node); } @override - Object visitReturnStatement(ReturnStatement node) { + void visitReturnStatement(ReturnStatement node) { computer._addRegion_token(node.returnKeyword, HighlightRegionType.KEYWORD); - return super.visitReturnStatement(node); + super.visitReturnStatement(node); } @override - Object visitShowCombinator(ShowCombinator node) { + void visitShowCombinator(ShowCombinator node) { computer._addRegion_token(node.keyword, HighlightRegionType.BUILT_IN); - return super.visitShowCombinator(node); + super.visitShowCombinator(node); } @override - Object visitSimpleIdentifier(SimpleIdentifier node) { + void visitSimpleIdentifier(SimpleIdentifier node) { computer._addIdentifierRegion(node); - return super.visitSimpleIdentifier(node); + super.visitSimpleIdentifier(node); } @override - Object visitSimpleStringLiteral(SimpleStringLiteral node) { + void visitSimpleStringLiteral(SimpleStringLiteral node) { computer._addRegion_node(node, HighlightRegionType.LITERAL_STRING); - return super.visitSimpleStringLiteral(node); + super.visitSimpleStringLiteral(node); } @override - Object visitSuperConstructorInvocation(SuperConstructorInvocation node) { + void visitSuperConstructorInvocation(SuperConstructorInvocation node) { computer._addRegion_token(node.superKeyword, HighlightRegionType.KEYWORD); - return super.visitSuperConstructorInvocation(node); + super.visitSuperConstructorInvocation(node); } @override - Object visitSwitchCase(SwitchCase node) { + void visitSwitchCase(SwitchCase node) { computer._addRegion_token(node.keyword, HighlightRegionType.KEYWORD); - return super.visitSwitchCase(node); + super.visitSwitchCase(node); } @override - Object visitSwitchDefault(SwitchDefault node) { + void visitSwitchDefault(SwitchDefault node) { computer._addRegion_token(node.keyword, HighlightRegionType.KEYWORD); - return super.visitSwitchDefault(node); + super.visitSwitchDefault(node); } @override - Object visitSwitchStatement(SwitchStatement node) { + void visitSwitchStatement(SwitchStatement node) { computer._addRegion_token(node.switchKeyword, HighlightRegionType.KEYWORD); - return super.visitSwitchStatement(node); + super.visitSwitchStatement(node); } @override - Object visitThisExpression(ThisExpression node) { + void visitThisExpression(ThisExpression node) { computer._addRegion_token(node.thisKeyword, HighlightRegionType.KEYWORD); - return super.visitThisExpression(node); + super.visitThisExpression(node); } @override - Object visitTryStatement(TryStatement node) { + void visitTryStatement(TryStatement node) { computer._addRegion_token(node.tryKeyword, HighlightRegionType.KEYWORD); computer._addRegion_token(node.finallyKeyword, HighlightRegionType.KEYWORD); - return super.visitTryStatement(node); + super.visitTryStatement(node); } @override - Object visitTypeName(TypeName node) { + void visitTypeName(TypeName node) { DartType type = node.type; if (type != null) { if (type.isDynamic && node.name.name == "dynamic") { @@ -812,35 +812,35 @@ return null; } } - return super.visitTypeName(node); + super.visitTypeName(node); } @override - Object visitVariableDeclarationList(VariableDeclarationList node) { + void visitVariableDeclarationList(VariableDeclarationList node) { computer._addRegion_token(node.keyword, HighlightRegionType.KEYWORD); - return super.visitVariableDeclarationList(node); + super.visitVariableDeclarationList(node); } @override - Object visitWhileStatement(WhileStatement node) { + void visitWhileStatement(WhileStatement node) { computer._addRegion_token(node.whileKeyword, HighlightRegionType.KEYWORD); - return super.visitWhileStatement(node); + super.visitWhileStatement(node); } @override - Object visitWithClause(WithClause node) { + void visitWithClause(WithClause node) { computer._addRegion_token(node.withKeyword, HighlightRegionType.KEYWORD); - return super.visitWithClause(node); + super.visitWithClause(node); } @override - Object visitYieldStatement(YieldStatement node) { + void visitYieldStatement(YieldStatement node) { Token keyword = node.yieldKeyword; Token star = node.star; int offset = keyword.offset; int end = star != null ? star.end : keyword.end; computer._addRegion(offset, end - offset, HighlightRegionType.BUILT_IN); - return super.visitYieldStatement(node); + super.visitYieldStatement(node); } void _addRegions_functionBody(FunctionBody node) {
diff --git a/pkg/analysis_server/lib/src/computer/computer_outline.dart b/pkg/analysis_server/lib/src/computer/computer_outline.dart index 490f5b5..24af9ba 100644 --- a/pkg/analysis_server/lib/src/computer/computer_outline.dart +++ b/pkg/analysis_server/lib/src/computer/computer_outline.dart
@@ -63,6 +63,9 @@ } else if (unitMember is FunctionTypeAlias) { FunctionTypeAlias alias = unitMember; unitContents.add(_newFunctionTypeAliasOutline(alias)); + } else if (unitMember is GenericTypeAlias) { + GenericTypeAlias alias = unitMember; + unitContents.add(_newGenericTypeAliasOutline(alias)); } } Outline unitOutline = _newUnitOutline(unitContents); @@ -224,6 +227,27 @@ return _nodeOutline(node, element); } + Outline _newGenericTypeAliasOutline(GenericTypeAlias node) { + var functionType = node.functionType; + TypeAnnotation returnType = functionType.returnType; + SimpleIdentifier nameNode = node.name; + String name = nameNode.name; + FormalParameterList parameters = functionType.parameters; + String parametersStr = _safeToSource(parameters); + String returnTypeStr = _safeToSource(returnType); + Element element = new Element( + ElementKind.FUNCTION_TYPE_ALIAS, + name, + Element.makeFlags( + isPrivate: Identifier.isPrivateName(name), + isDeprecated: _isDeprecated(node)), + location: _getLocationNode(nameNode), + parameters: parametersStr, + returnType: returnTypeStr, + typeParameters: _getTypeParametersStr(node.typeParameters)); + return _nodeOutline(node, element); + } + Outline _newMethodOutline(MethodDeclaration method) { TypeAnnotation returnType = method.returnType; SimpleIdentifier nameNode = method.name;
diff --git a/pkg/analysis_server/lib/src/computer/import_elements_computer.dart b/pkg/analysis_server/lib/src/computer/import_elements_computer.dart index 292b748..7973eed 100644 --- a/pkg/analysis_server/lib/src/computer/import_elements_computer.dart +++ b/pkg/analysis_server/lib/src/computer/import_elements_computer.dart
@@ -38,7 +38,7 @@ * The resolution result associated with the defining compilation unit of the * library to which imports might be added. */ - final ResolveResult libraryResult; + final ResolvedUnitResult libraryResult; /** * Initialize a newly created builder.
diff --git a/pkg/analysis_server/lib/src/computer/imported_elements_computer.dart b/pkg/analysis_server/lib/src/computer/imported_elements_computer.dart index 6150a2c..a587098 100644 --- a/pkg/analysis_server/lib/src/computer/imported_elements_computer.dart +++ b/pkg/analysis_server/lib/src/computer/imported_elements_computer.dart
@@ -1,4 +1,4 @@ -// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file +// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. @@ -50,7 +50,7 @@ * The visitor used by an [ImportedElementsComputer] to record the names of all * imported elements. */ -class _Visitor extends UnifyingAstVisitor<Object> { +class _Visitor extends UnifyingAstVisitor<void> { /** * The element representing the library containing the code being visited. */ @@ -79,15 +79,14 @@ _Visitor(this.containingLibrary, this.startOffset, this.endOffset); @override - Object visitNode(AstNode node) { + void visitNode(AstNode node) { if (node.offset <= endOffset && node.end >= startOffset) { node.visitChildren(this); } - return null; } @override - Object visitSimpleIdentifier(SimpleIdentifier node) { + void visitSimpleIdentifier(SimpleIdentifier node) { if (!node.inDeclarationContext() && node.offset <= endOffset && node.end >= startOffset && @@ -119,7 +118,6 @@ } } } - return null; } static bool _isConstructorDeclarationReturnType(SimpleIdentifier node) {
diff --git a/pkg/analysis_server/lib/src/computer/new_notifications.dart b/pkg/analysis_server/lib/src/computer/new_notifications.dart index 0e11991..06aabc7 100644 --- a/pkg/analysis_server/lib/src/computer/new_notifications.dart +++ b/pkg/analysis_server/lib/src/computer/new_notifications.dart
@@ -8,15 +8,16 @@ import 'package:analysis_server/src/domains/analysis/occurrences.dart'; import 'package:analysis_server/src/domains/analysis/occurrences_dart.dart'; import 'package:analysis_server/src/protocol_server.dart' as protocol; -import 'package:analyzer/src/dart/analysis/driver.dart'; +import 'package:analyzer/dart/analysis/results.dart'; import 'package:analyzer_plugin/src/utilities/navigation/navigation.dart'; void new_sendDartNotificationNavigation( - AnalysisServer analysisServer, AnalysisResult result) { + AnalysisServer analysisServer, ResolvedUnitResult result) { var unit = result.unit; if (unit != null) { NavigationCollectorImpl collector = new NavigationCollectorImpl(); - computeDartNavigation(collector, unit, null, null); + computeDartNavigation( + analysisServer.resourceProvider, collector, unit, null, null); collector.createRegions(); var params = new protocol.AnalysisNavigationParams( result.path, collector.regions, collector.targets, collector.files); @@ -25,7 +26,7 @@ } void new_sendDartNotificationOccurrences( - AnalysisServer analysisServer, AnalysisResult result) { + AnalysisServer analysisServer, ResolvedUnitResult result) { var unit = result.unit; if (unit != null) { OccurrencesCollectorImpl collector = new OccurrencesCollectorImpl(); @@ -37,9 +38,12 @@ } void new_sendErrorNotification( - AnalysisServer analysisServer, AnalysisResult result) { + AnalysisServer analysisServer, ResolvedUnitResult result) { var serverErrors = protocol.doAnalysisError_listFromEngine( - result.driver.analysisOptions, result.lineInfo, result.errors); + result.session.analysisContext.analysisOptions, + result.lineInfo, + result.errors, + ); var params = new protocol.AnalysisErrorsParams(result.path, serverErrors); analysisServer.sendNotification(params.toNotification()); }
diff --git a/pkg/analysis_server/lib/src/context_manager.dart b/pkg/analysis_server/lib/src/context_manager.dart index 32c9e00..f38b989 100644 --- a/pkg/analysis_server/lib/src/context_manager.dart +++ b/pkg/analysis_server/lib/src/context_manager.dart
@@ -899,8 +899,7 @@ convertedErrors ?? <protocol.AnalysisError>[]); } - void _checkForAnalysisOptionsUpdate( - String path, ContextInfo info, ChangeType changeType) { + void _checkForAnalysisOptionsUpdate(String path, ContextInfo info) { if (AnalysisEngine.isAnalysisOptionsFileName(path, pathContext)) { AnalysisDriver driver = info.analysisDriver; if (driver == null) { @@ -909,39 +908,29 @@ // yet created a driver for that context. return; } - String contextRoot = info.folder.path; - ContextBuilder builder = - callbacks.createContextBuilder(info.folder, defaultContextOptions); - AnalysisOptions options = builder.getAnalysisOptions(contextRoot, - contextRoot: driver.contextRoot); - SourceFactory factory = builder.createSourceFactory(contextRoot, options); - driver.configure(analysisOptions: options, sourceFactory: factory); // TODO(brianwilkerson) Set exclusion patterns. _analyzeAnalysisOptionsFile(driver, path); + _updateAnalysisOptions(info); } } - void _checkForPackagespecUpdate( - String path, ContextInfo info, Folder folder) { + void _checkForPackagespecUpdate(String path, ContextInfo info) { // Check to see if this is the .packages file for this context and if so, // update the context's source factory. if (pathContext.basename(path) == PACKAGE_SPEC_NAME) { - String contextRoot = info.folder.path; - ContextBuilder builder = - callbacks.createContextBuilder(info.folder, defaultContextOptions); AnalysisDriver driver = info.analysisDriver; - if (driver != null) { - AnalysisOptions options = builder.getAnalysisOptions(contextRoot, - contextRoot: driver.contextRoot); - SourceFactory factory = - builder.createSourceFactory(contextRoot, options); - driver.configure(analysisOptions: options, sourceFactory: factory); + if (driver == null) { + // I suspect that this happens as a result of a race condition: server + // has determined that the file (at [path]) is in a context, but hasn't + // yet created a driver for that context. + return; } + + _updateAnalysisOptions(info); } } - void _checkForPubspecUpdate( - String path, ContextInfo info, ChangeType changeType) { + void _checkForPubspecUpdate(String path, ContextInfo info) { if (_isPubspec(path)) { AnalysisDriver driver = info.analysisDriver; if (driver == null) { @@ -951,6 +940,7 @@ return; } _analyzePubspecFile(driver, path); + _updateAnalysisOptions(info); } } @@ -1424,9 +1414,9 @@ } } } - _checkForPackagespecUpdate(path, info, info.folder); - _checkForAnalysisOptionsUpdate(path, info, type); - _checkForPubspecUpdate(path, info, type); + _checkForPackagespecUpdate(path, info); + _checkForAnalysisOptionsUpdate(path, info); + _checkForPubspecUpdate(path, info); } /** @@ -1555,6 +1545,17 @@ return false; } + void _updateAnalysisOptions(ContextInfo info) { + AnalysisDriver driver = info.analysisDriver; + String contextRoot = info.folder.path; + ContextBuilder builder = + callbacks.createContextBuilder(info.folder, defaultContextOptions); + AnalysisOptions options = builder.getAnalysisOptions(contextRoot, + contextRoot: driver.contextRoot); + SourceFactory factory = builder.createSourceFactory(contextRoot, options); + driver.configure(analysisOptions: options, sourceFactory: factory); + } + void _updateContextPackageUriResolver(Folder contextFolder) { ContextInfo info = getContextInfoFor(contextFolder); AnalysisDriver driver = info.analysisDriver;
diff --git a/pkg/analysis_server/lib/src/domain_analysis.dart b/pkg/analysis_server/lib/src/domain_analysis.dart index a3e3257..d9d7164 100644 --- a/pkg/analysis_server/lib/src/domain_analysis.dart +++ b/pkg/analysis_server/lib/src/domain_analysis.dart
@@ -17,12 +17,12 @@ import 'package:analysis_server/src/plugin/result_merger.dart'; import 'package:analysis_server/src/protocol/protocol_internal.dart'; import 'package:analysis_server/src/protocol_server.dart'; +import 'package:analyzer/dart/analysis/results.dart'; import 'package:analyzer/dart/ast/ast.dart'; import 'package:analyzer/error/error.dart' as engine; import 'package:analyzer/file_system/file_system.dart'; import 'package:analyzer/src/dart/analysis/driver.dart'; import 'package:analyzer/src/generated/engine.dart' as engine; -import 'package:analyzer/src/generated/source.dart'; import 'package:analyzer_plugin/protocol/protocol.dart' as plugin; import 'package:analyzer_plugin/protocol/protocol_common.dart'; import 'package:analyzer_plugin/protocol/protocol_constants.dart' as plugin; @@ -47,24 +47,21 @@ * Implement the `analysis.getErrors` request. */ Future<void> getErrors(Request request) async { - // TODO(brianwilkerson) Determine whether this await is necessary. - await null; String file = new AnalysisGetErrorsParams.fromRequest(request).file; + ResolvedUnitResult result = await server.getResolvedUnit(file); - void send(engine.AnalysisOptions analysisOptions, LineInfo lineInfo, - List<engine.AnalysisError> errors) { - if (lineInfo == null) { - server.sendResponse(new Response.getErrorsInvalidFile(request)); - } else { - List<AnalysisError> protocolErrors = - doAnalysisError_listFromEngine(analysisOptions, lineInfo, errors); - server.sendResponse( - new AnalysisGetErrorsResult(protocolErrors).toResponse(request.id)); - } + if (result?.state != ResultState.VALID) { + server.sendResponse(new Response.getErrorsInvalidFile(request)); + return; } - AnalysisResult result = await server.getAnalysisResult(file); - send(result?.driver?.analysisOptions, result?.lineInfo, result?.errors); + List<AnalysisError> protocolErrors = doAnalysisError_listFromEngine( + result.session.analysisContext.analysisOptions, + result.lineInfo, + result.errors, + ); + server.sendResponse( + new AnalysisGetErrorsResult(protocolErrors).toResponse(request.id)); } /** @@ -76,7 +73,7 @@ var params = new AnalysisGetHoverParams.fromRequest(request); // Prepare the resolved units. - AnalysisResult result = await server.getAnalysisResult(params.file); + ResolvedUnitResult result = await server.getResolvedUnit(params.file); CompilationUnit unit = result?.unit; // Prepare the hovers. @@ -105,9 +102,10 @@ // // Prepare the resolved unit. // - AnalysisResult result = await server.getAnalysisResult(params.file); - if (result == null) { + ResolvedUnitResult result = await server.getResolvedUnit(params.file); + if (result?.state != ResultState.VALID) { server.sendResponse(new Response.getImportedElementsInvalidFile(request)); + return; } List<ImportedElements> elements; @@ -179,11 +177,12 @@ // Compute navigation data generated by server. // List<AnalysisNavigationParams> allResults = <AnalysisNavigationParams>[]; - AnalysisResult result = await server.getAnalysisResult(file); - CompilationUnit unit = result?.unit; - if (unit != null && result.exists) { + ResolvedUnitResult result = await server.getResolvedUnit(file); + if (result?.state == ResultState.VALID) { + CompilationUnit unit = result?.unit; NavigationCollectorImpl collector = new NavigationCollectorImpl(); - computeDartNavigation(collector, unit, offset, length); + computeDartNavigation( + server.resourceProvider, collector, unit, offset, length); collector.createRegions(); allResults.add(new AnalysisNavigationParams( file, collector.regions, collector.targets, collector.files)); @@ -246,14 +245,15 @@ var params = new AnalysisGetSignatureParams.fromRequest(request); // Prepare the resolved units. - AnalysisResult result = await server.getAnalysisResult(params.file); - CompilationUnit unit = result?.unit; - if (unit == null) { + ResolvedUnitResult result = await server.getResolvedUnit(params.file); + + if (result?.state != ResultState.VALID) { server.sendResponse(new Response.getSignatureInvalidFile(request)); return; } // Ensure the offset provided is a valid location in the file. + final unit = result.unit; final computer = new DartUnitSignatureComputer(unit, params.offset); if (!computer.offsetIsValid) { server.sendResponse(new Response.getSignatureInvalidOffset(request));
diff --git a/pkg/analysis_server/lib/src/domain_completion.dart b/pkg/analysis_server/lib/src/domain_completion.dart index 10597e3..ce73d98 100644 --- a/pkg/analysis_server/lib/src/domain_completion.dart +++ b/pkg/analysis_server/lib/src/domain_completion.dart
@@ -15,6 +15,7 @@ import 'package:analysis_server/src/services/completion/completion_core.dart'; import 'package:analysis_server/src/services/completion/completion_performance.dart'; import 'package:analysis_server/src/services/completion/dart/completion_manager.dart'; +import 'package:analyzer/dart/analysis/results.dart'; import 'package:analyzer/src/dart/analysis/driver.dart'; import 'package:analyzer_plugin/protocol/protocol.dart' as plugin; import 'package:analyzer_plugin/protocol/protocol_common.dart'; @@ -172,9 +173,9 @@ String filePath = params.file; int offset = params.offset; - AnalysisResult result = await server.getAnalysisResult(filePath); + ResolvedUnitResult result = await server.getResolvedUnit(filePath); - if (result != null && result.exists) { + if (result?.state == ResultState.VALID) { if (offset < 0 || offset > result.content.length) { server.sendResponse(new Response.invalidParameter( request,
diff --git a/pkg/analysis_server/lib/src/domain_kythe.dart b/pkg/analysis_server/lib/src/domain_kythe.dart index c4fceb6..2bfc8c0 100644 --- a/pkg/analysis_server/lib/src/domain_kythe.dart +++ b/pkg/analysis_server/lib/src/domain_kythe.dart
@@ -13,7 +13,7 @@ import 'package:analysis_server/src/plugin/plugin_manager.dart'; import 'package:analysis_server/src/plugin/result_merger.dart'; import 'package:analysis_server/src/services/kythe/kythe_visitors.dart'; -import 'package:analyzer/dart/ast/ast.dart'; +import 'package:analyzer/dart/analysis/results.dart'; import 'package:analyzer/src/dart/analysis/driver.dart'; import 'package:analyzer/src/dart/element/inheritance_manager2.dart'; import 'package:analyzer/src/generated/type_system.dart'; @@ -56,10 +56,9 @@ // List<KytheGetKytheEntriesResult> allResults = <KytheGetKytheEntriesResult>[]; - AnalysisResult result = await server.getAnalysisResult(file); - CompilationUnit unit = result?.unit; - TypeSystem typeSystem = result.libraryElement.context.typeSystem; - if (unit != null && result.exists) { + ResolvedUnitResult result = await server.getResolvedUnit(file); + if (result?.state == ResultState.VALID) { + TypeSystem typeSystem = await result.libraryElement.session.typeSystem; List<KytheEntry> entries = <KytheEntry>[]; // TODO(brianwilkerson) Figure out how to get the list of files. List<String> files = <String>[];
diff --git a/pkg/analysis_server/lib/src/domains/analysis/navigation_dart.dart b/pkg/analysis_server/lib/src/domains/analysis/navigation_dart.dart index 46a455e..74bbf87 100644 --- a/pkg/analysis_server/lib/src/domains/analysis/navigation_dart.dart +++ b/pkg/analysis_server/lib/src/domains/analysis/navigation_dart.dart
@@ -8,17 +8,22 @@ import 'package:analyzer/dart/ast/visitor.dart'; import 'package:analyzer/dart/element/element.dart'; import 'package:analyzer/dart/element/type.dart'; +import 'package:analyzer/file_system/file_system.dart'; import 'package:analyzer/src/dart/ast/utilities.dart'; import 'package:analyzer/src/dart/element/element.dart'; import 'package:analyzer/src/generated/source.dart'; import 'package:analyzer_plugin/utilities/navigation/navigation.dart'; -NavigationCollector computeDartNavigation(NavigationCollector collector, - CompilationUnit unit, int offset, int length) { +NavigationCollector computeDartNavigation( + ResourceProvider resourceProvider, + NavigationCollector collector, + CompilationUnit unit, + int offset, + int length) { _DartNavigationCollector dartCollector = new _DartNavigationCollector(collector); _DartNavigationComputerVisitor visitor = - new _DartNavigationComputerVisitor(dartCollector); + new _DartNavigationComputerVisitor(resourceProvider, dartCollector); if (offset == null || length == null) { unit.accept(visitor); } else { @@ -87,9 +92,10 @@ } class _DartNavigationComputerVisitor extends RecursiveAstVisitor { + final ResourceProvider resourceProvider; final _DartNavigationCollector computer; - _DartNavigationComputerVisitor(this.computer); + _DartNavigationComputerVisitor(this.resourceProvider, this.computer); @override visitAnnotation(Annotation node) { @@ -352,7 +358,7 @@ void _addUriDirectiveRegion(UriBasedDirective node, Element element) { if (element != null) { Source source = element.source; - if (element.context.exists(source)) { + if (resourceProvider.getResource(source.fullName).exists) { computer._addRegionForNode(node.uri, element); } }
diff --git a/pkg/analysis_server/lib/src/domains/execution/completion.dart b/pkg/analysis_server/lib/src/domains/execution/completion.dart index c3a218e..a8a55f1 100644 --- a/pkg/analysis_server/lib/src/domains/execution/completion.dart +++ b/pkg/analysis_server/lib/src/domains/execution/completion.dart
@@ -14,6 +14,7 @@ import 'package:analysis_server/src/services/completion/completion_core.dart'; import 'package:analysis_server/src/services/completion/completion_performance.dart'; import 'package:analysis_server/src/services/completion/dart/completion_manager.dart'; +import 'package:analyzer/dart/analysis/results.dart'; import 'package:analyzer/file_system/file_system.dart'; import 'package:analyzer/src/dart/analysis/driver.dart'; import 'package:analyzer/src/dart/analysis/file_state.dart'; @@ -81,7 +82,7 @@ // Update the context file content to include the code being completed. // Then resolve it, and restore the file to its initial state. - AnalysisResult targetResult; + ResolvedUnitResult targetResult; String contentFileOverlay = fileContentOverlay[contextFile]; try { fileContentOverlay[contextFile] = targetCode;
diff --git a/pkg/analysis_server/lib/src/edit/edit_dartfix.dart b/pkg/analysis_server/lib/src/edit/edit_dartfix.dart index 2dc141b..72b62a6 100644 --- a/pkg/analysis_server/lib/src/edit/edit_dartfix.dart +++ b/pkg/analysis_server/lib/src/edit/edit_dartfix.dart
@@ -2,7 +2,6 @@ // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. -import 'package:analysis_server/plugin/edit/assist/assist_dart.dart'; import 'package:analysis_server/plugin/edit/fix/fix_core.dart'; import 'package:analysis_server/protocol/protocol.dart'; import 'package:analysis_server/protocol/protocol_generated.dart'; @@ -11,13 +10,15 @@ import 'package:analysis_server/src/edit/fix/prefer_mixin_fix.dart'; import 'package:analysis_server/src/services/correction/fix.dart'; import 'package:analysis_server/src/services/correction/fix_internal.dart'; -import 'package:analyzer/analyzer.dart'; +import 'package:analyzer/dart/analysis/results.dart'; import 'package:analyzer/dart/analysis/session.dart'; import 'package:analyzer/dart/ast/ast.dart'; import 'package:analyzer/dart/element/element.dart'; +import 'package:analyzer/error/error.dart'; +import 'package:analyzer/error/listener.dart'; import 'package:analyzer/file_system/file_system.dart'; -import 'package:analyzer/src/dart/analysis/ast_provider_driver.dart'; -import 'package:analyzer/src/dart/analysis/driver.dart'; +import 'package:analyzer/src/dart/ast/utilities.dart'; +import 'package:analyzer/src/error/codes.dart'; import 'package:analyzer/src/generated/source.dart'; import 'package:analyzer/src/lint/linter.dart'; import 'package:analyzer/src/lint/linter_visitor.dart'; @@ -124,32 +125,52 @@ } continue; } - AnalysisResult result = await server.getAnalysisResult(res.path); - CompilationUnit unit = result?.unit; - if (unit != null) { - if (!hasErrors) { - for (AnalysisError error in result.errors) { - if (!(await fixError(result, error))) { - if (error.errorCode.type == ErrorType.SYNTACTIC_ERROR) { - hasErrors = true; + + const maxAttempts = 3; + int attempt = 0; + while (attempt < maxAttempts) { + ResolvedUnitResult result = await server.getResolvedUnit(res.path); + + // TODO(danrubel): Investigate why InconsistentAnalysisException occurs + // and whether this is an appropriate way to handle the situation + ++attempt; + try { + CompilationUnit unit = result?.unit; + if (unit != null) { + if (!hasErrors) { + for (AnalysisError error in result.errors) { + if (!(await fixError(result, error))) { + if (error.errorCode.type == ErrorType.SYNTACTIC_ERROR) { + hasErrors = true; + } + } } } + Source source = result.unit.declaredElement.source; + for (Linter linter in linters) { + if (linter != null) { + linter.reporter.source = source; + } + } + var lintVisitors = lintVisitorsBySession[result.session] ??= + await _setupLintVisitors(result, linters); + if (lintVisitors.astVisitor != null) { + unit.accept(lintVisitors.astVisitor); + } + unit.accept(lintVisitors.linterVisitor); + for (LinterFix fix in fixes) { + await fix.applyLocalFixes(result); + } } - } - Source source = result.sourceFactory.forUri2(result.uri); - for (Linter linter in linters) { - if (linter != null) { - linter.reporter.source = source; + break; + } on InconsistentAnalysisException catch (_) { + if (attempt == maxAttempts) { + // TODO(danrubel): Consider improving the edit.dartfix protocol + // to gracefully report inconsistent results for a particular + // file rather than aborting the entire operation. + rethrow; } - } - var lintVisitors = lintVisitorsBySession[result.session] ??= - await _setupLintVisitors(result, linters); - if (lintVisitors.astVisitor != null) { - unit.accept(lintVisitors.astVisitor); - } - unit.accept(lintVisitors.linterVisitor); - for (LinterFix fix in fixes) { - await fix.applyLocalFixes(result); + // try again } } } @@ -177,7 +198,7 @@ .toResponse(request.id); } - Future<bool> fixError(AnalysisResult result, AnalysisError error) async { + Future<bool> fixError(ResolvedUnitResult result, AnalysisError error) async { if (error.errorCode == StaticTypeWarningCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS_CONSTRUCTOR) { // TODO(danrubel): Rather than comparing the error codes individually, @@ -190,11 +211,7 @@ return false; } - final dartContext = new DartFixContextImpl( - new FixContextImpl( - server.resourceProvider, result.driver, error, result.errors), - new AstProviderForDriver(result.driver), - result.unit); + final dartContext = new DartFixContextImpl(result, error); final processor = new FixProcessor(dartContext); Fix fix = await processor.computeFix(); final location = locationFor(result, error.offset, error.length); @@ -226,7 +243,7 @@ return false; } - Location locationFor(AnalysisResult result, int offset, int length) { + Location locationFor(ResolvedUnitResult result, int offset, int length) { final locInfo = result.unit.lineInfo.getLocation(offset); final location = new Location( result.path, offset, length, locInfo.lineNumber, locInfo.columnNumber); @@ -234,7 +251,7 @@ } Future<_LintVisitors> _setupLintVisitors( - AnalysisResult result, List<Linter> linters) async { + ResolvedUnitResult result, List<Linter> linters) async { final visitors = <AstVisitor>[]; final registry = new NodeLintRegistry(false); // TODO(paulberry): use an API that provides this information more readily @@ -246,7 +263,7 @@ if (identical(cu, unitElement)) { allUnits.add(currentUnit); } else { - var result = await session.getResolvedAst(cu.source.fullName); + var result = await session.getResolvedUnit(cu.source.fullName); allUnits.add(LinterContextUnit(result.content, result.unit)); } } @@ -258,11 +275,8 @@ if (visitor != null) { visitors.add(visitor); } - if (linter is NodeLintRuleWithContext) { - (linter as NodeLintRuleWithContext) - .registerNodeProcessors(registry, context); - } else if (linter is NodeLintRule) { - (linter as NodeLintRule).registerNodeProcessors(registry); + if (linter is NodeLintRule) { + (linter as NodeLintRule).registerNodeProcessors(registry, context); } } } @@ -276,29 +290,6 @@ } } -class EditDartFixAssistContext implements DartAssistContext { - @override - final AnalysisDriver analysisDriver; - - @override - final int selectionLength; - - @override - final int selectionOffset; - - @override - final Source source; - - @override - final CompilationUnit unit; - - EditDartFixAssistContext( - EditDartFix dartFix, this.source, this.unit, AstNode node) - : analysisDriver = dartFix.server.getAnalysisDriver(source.fullName), - selectionOffset = node.offset, - selectionLength = 0; -} - abstract class LinterFix implements ErrorReporter { final EditDartFix dartFix; @@ -308,7 +299,7 @@ LinterFix(this.dartFix); /// Apply fixes for the current compilation unit. - Future<void> applyLocalFixes(AnalysisResult result); + Future<void> applyLocalFixes(ResolvedUnitResult result); /// Apply any fixes remaining after analysis is complete. Future<void> applyRemainingFixes();
diff --git a/pkg/analysis_server/lib/src/edit/edit_domain.dart b/pkg/analysis_server/lib/src/edit/edit_domain.dart index f7a28e7..8f3a144 100644 --- a/pkg/analysis_server/lib/src/edit/edit_domain.dart +++ b/pkg/analysis_server/lib/src/edit/edit_domain.dart
@@ -5,9 +5,7 @@ import 'dart:async'; import 'package:analysis_server/plugin/edit/assist/assist_core.dart'; -import 'package:analysis_server/plugin/edit/assist/assist_dart.dart'; import 'package:analysis_server/plugin/edit/fix/fix_core.dart'; -import 'package:analysis_server/plugin/edit/fix/fix_dart.dart'; import 'package:analysis_server/protocol/protocol_constants.dart'; import 'package:analysis_server/src/analysis_server.dart'; import 'package:analysis_server/src/collections.dart'; @@ -19,22 +17,21 @@ import 'package:analysis_server/src/protocol_server.dart' hide Element; import 'package:analysis_server/src/services/completion/postfix/postfix_completion.dart'; import 'package:analysis_server/src/services/completion/statement/statement_completion.dart'; +import 'package:analysis_server/src/services/correction/assist.dart'; import 'package:analysis_server/src/services/correction/assist_internal.dart'; +import 'package:analysis_server/src/services/correction/fix.dart'; import 'package:analysis_server/src/services/correction/fix_internal.dart'; import 'package:analysis_server/src/services/correction/organize_directives.dart'; import 'package:analysis_server/src/services/correction/sort_members.dart'; import 'package:analysis_server/src/services/correction/status.dart'; import 'package:analysis_server/src/services/refactoring/refactoring.dart'; import 'package:analysis_server/src/services/search/search_engine.dart'; +import 'package:analyzer/dart/analysis/results.dart'; import 'package:analyzer/dart/analysis/session.dart'; import 'package:analyzer/dart/ast/ast.dart'; -import 'package:analyzer/dart/ast/standard_resolution_map.dart'; import 'package:analyzer/dart/element/element.dart'; import 'package:analyzer/error/error.dart' as engine; -import 'package:analyzer/file_system/file_system.dart'; -import 'package:analyzer/src/dart/analysis/ast_provider_driver.dart'; -import 'package:analyzer/src/dart/analysis/driver.dart'; -import 'package:analyzer/src/dart/element/ast_provider.dart'; +import 'package:analyzer/src/dart/ast/utilities.dart'; import 'package:analyzer/src/dart/scanner/scanner.dart' as engine; import 'package:analyzer/src/error/codes.dart' as engine; import 'package:analyzer/src/generated/engine.dart' as engine; @@ -175,7 +172,7 @@ Map<PluginInfo, Future<plugin.Response>> pluginFutures; plugin.EditGetAssistsParams requestParams = new plugin.EditGetAssistsParams(file, offset, length); - AnalysisDriver driver = server.getAnalysisDriver(file); + var driver = server.getAnalysisDriver(file); if (driver == null) { pluginFutures = <PluginInfo, Future<plugin.Response>>{}; } else { @@ -185,15 +182,11 @@ // // Compute fixes associated with server-generated errors. // - AnalysisResult result = await server.getAnalysisResult(file); + ResolvedUnitResult result = await server.getResolvedUnit(file); if (result != null) { - CompilationUnit unit = result.unit; - CompilationUnitElement compilationUnitElement = - resolutionMap.elementDeclaredByCompilationUnit(unit); - DartAssistContext dartAssistContext = new _DartAssistContextForValues( - compilationUnitElement.source, offset, length, driver, unit); + var context = new DartAssistContextImpl(result, offset, length); try { - AssistProcessor processor = new AssistProcessor(dartAssistContext); + AssistProcessor processor = new AssistProcessor(context); List<Assist> assists = await processor.compute(); assists.sort(Assist.SORT_BY_RELEVANCE); for (Assist assist in assists) { @@ -236,7 +229,7 @@ Map<PluginInfo, Future<plugin.Response>> pluginFutures; plugin.EditGetFixesParams requestParams = new plugin.EditGetFixesParams(file, offset); - AnalysisDriver driver = server.getAnalysisDriver(file); + var driver = server.getAnalysisDriver(file); if (driver == null) { pluginFutures = <PluginInfo, Future<plugin.Response>>{}; } else { @@ -249,7 +242,7 @@ List<AnalysisErrorFixes> errorFixesList = null; while (errorFixesList == null) { try { - errorFixesList = await _computeServerErrorFixes(driver, file, offset); + errorFixesList = await _computeServerErrorFixes(file, offset); } on InconsistentAnalysisException { // Loop around to try again to compute the fixes. } @@ -281,26 +274,17 @@ var params = new EditGetPostfixCompletionParams.fromRequest(request); SourceChange change; - AnalysisResult result = await server.getAnalysisResult(params.file); + ResolvedUnitResult result = await server.getResolvedUnit(params.file); if (result != null) { - CompilationUnit unit = result.unit; - CompilationUnitElement unitElement = - resolutionMap.elementDeclaredByCompilationUnit(unit); - if (unitElement.context != null) { - PostfixCompletionContext context = new PostfixCompletionContext( - params.file, - result.lineInfo, - params.offset, - params.key, - result.driver, - unit, - unitElement, - result.errors); - PostfixCompletionProcessor processor = - new PostfixCompletionProcessor(context); - PostfixCompletion completion = await processor.compute(); - change = completion?.change; - } + PostfixCompletionContext context = new PostfixCompletionContext( + result, + params.offset, + params.key, + ); + PostfixCompletionProcessor processor = + new PostfixCompletionProcessor(context); + PostfixCompletion completion = await processor.compute(); + change = completion?.change; } if (change == null) { change = new SourceChange("", edits: []); @@ -317,24 +301,13 @@ var params = new EditGetStatementCompletionParams.fromRequest(request); SourceChange change; - AnalysisResult result = await server.getAnalysisResult(params.file); + ResolvedUnitResult result = await server.getResolvedUnit(params.file); if (result != null) { - CompilationUnit unit = result.unit; - CompilationUnitElement unitElement = - resolutionMap.elementDeclaredByCompilationUnit(unit); - if (unitElement.context != null) { - StatementCompletionContext context = new StatementCompletionContext( - params.file, - result.lineInfo, - params.offset, - unit, - unitElement, - result.errors); - StatementCompletionProcessor processor = - new StatementCompletionProcessor(context); - StatementCompletion completion = await processor.compute(); - change = completion.change; - } + var context = new StatementCompletionContext(result, params.offset); + StatementCompletionProcessor processor = + new StatementCompletionProcessor(context); + StatementCompletion completion = await processor.compute(); + change = completion.change; } if (change == null) { change = new SourceChange("", edits: []); @@ -404,7 +377,7 @@ // // Prepare the resolved unit. // - AnalysisResult result = await server.getAnalysisResult(params.file); + ResolvedUnitResult result = await server.getResolvedUnit(params.file); if (result == null) { server.sendResponse(new Response.importElementsInvalidFile(request)); } @@ -413,7 +386,7 @@ if (libraryUnit != result.unit.declaredElement) { // The file in the request is a part of a library. We need to pass the // defining compilation unit to the computer, not the part. - result = await server.getAnalysisResult(libraryUnit.source.fullName); + result = await server.getResolvedUnit(libraryUnit.source.fullName); if (result == null) { server.sendResponse(new Response.importElementsInvalidFile(request)); } @@ -439,25 +412,15 @@ var params = new EditGetPostfixCompletionParams.fromRequest(request); bool value = false; - AnalysisResult result = await server.getAnalysisResult(params.file); + ResolvedUnitResult result = await server.getResolvedUnit(params.file); if (result != null) { - CompilationUnit unit = result.unit; - CompilationUnitElement unitElement = - resolutionMap.elementDeclaredByCompilationUnit(unit); - if (unitElement.context != null) { - PostfixCompletionContext context = new PostfixCompletionContext( - params.file, - result.lineInfo, - params.offset, - params.key, - result.driver, - unit, - unitElement, - result.errors); - PostfixCompletionProcessor processor = - new PostfixCompletionProcessor(context); - value = await processor.isApplicable(); - } + var context = new PostfixCompletionContext( + result, + params.offset, + params.key, + ); + var processor = new PostfixCompletionProcessor(context); + value = await processor.isApplicable(); } Response response = new EditIsPostfixCompletionApplicableResult(value) @@ -491,7 +454,7 @@ return; } // Prepare the file information. - AnalysisResult result = await server.getAnalysisResult(file); + ResolvedUnitResult result = await server.getResolvedUnit(file); if (result == null) { server.sendResponse(new Response.fileNotAnalyzed(request, file)); return; @@ -526,8 +489,8 @@ return; } // Prepare the file information. - AnalysisDriver driver = server.getAnalysisDriver(file); - ParseResult result = await driver?.parseFile(file); + var driver = server.getAnalysisDriver(file); + ParsedUnitResult result = await driver?.parseFile(file); if (result == null) { server.sendResponse(new Response.fileNotAnalyzed(request, file)); return; @@ -555,29 +518,20 @@ * Compute and return the fixes associated with server-generated errors. */ Future<List<AnalysisErrorFixes>> _computeServerErrorFixes( - AnalysisDriver driver, String file, int offset) async { + String file, int offset) async { // TODO(brianwilkerson) Determine whether this await is necessary. await null; List<AnalysisErrorFixes> errorFixesList = <AnalysisErrorFixes>[]; - AnalysisResult result = await server.getAnalysisResult(file); + var result = await server.getResolvedUnit(file); if (result != null) { - CompilationUnit unit = result.unit; LineInfo lineInfo = result.lineInfo; int requestLine = lineInfo.getLocation(offset).lineNumber; - List<engine.AnalysisError> errorsCopy = new List.from(result.errors); for (engine.AnalysisError error in result.errors) { int errorLine = lineInfo.getLocation(error.offset).lineNumber; if (errorLine == requestLine) { - AstProvider astProvider = new AstProviderForDriver(driver); - DartFixContext context = new _DartFixContextImpl( - server.resourceProvider, - result.driver, - astProvider, - unit, - error, - errorsCopy); + var context = new DartFixContextImpl(result, error); List<Fix> fixes = - await new DefaultFixContributor().internalComputeFixes(context); + await new DartFixContributor().computeFixes(context); if (fixes.isNotEmpty) { fixes.sort(Fix.SORT_BY_RELEVANCE); AnalysisError serverError = @@ -611,22 +565,22 @@ List<RefactoringKind> kinds = <RefactoringKind>[]; // Check nodes. { - var analysisResult = await server.getAnalysisResult(file); - if (analysisResult != null) { + var resolvedUnit = await server.getResolvedUnit(file); + if (resolvedUnit != null) { // Try EXTRACT_LOCAL_VARIABLE. - if (new ExtractLocalRefactoring(analysisResult, offset, length) + if (new ExtractLocalRefactoring(resolvedUnit, offset, length) .isAvailable()) { kinds.add(RefactoringKind.EXTRACT_LOCAL_VARIABLE); } // Try EXTRACT_METHOD. - if (new ExtractMethodRefactoring(searchEngine, - server.getAstProvider(file), analysisResult, offset, length) + if (new ExtractMethodRefactoring( + searchEngine, resolvedUnit, offset, length) .isAvailable()) { kinds.add(RefactoringKind.EXTRACT_METHOD); } // Try EXTRACT_WIDGETS. if (new ExtractWidgetRefactoring( - searchEngine, analysisResult, offset, length) + searchEngine, resolvedUnit, offset, length) .isAvailable()) { kinds.add(RefactoringKind.EXTRACT_WIDGET); } @@ -634,23 +588,28 @@ } // check elements { - Element element = await server.getElementAtOffset(file, offset); - if (element != null) { - // try CONVERT_METHOD_TO_GETTER - if (element is ExecutableElement) { - Refactoring refactoring = new ConvertMethodToGetterRefactoring( - searchEngine, server.getAstProvider(file), element); - RefactoringStatus status = await refactoring.checkInitialConditions(); - if (!status.hasFatalError) { - kinds.add(RefactoringKind.CONVERT_METHOD_TO_GETTER); + var resolvedUnit = await server.getResolvedUnit(file); + if (resolvedUnit != null) { + var node = new NodeLocator(offset).searchWithin(resolvedUnit.unit); + var element = server.getElementOfNode(node); + if (element != null) { + // try CONVERT_METHOD_TO_GETTER + if (element is ExecutableElement) { + Refactoring refactoring = new ConvertMethodToGetterRefactoring( + searchEngine, resolvedUnit.session, element); + RefactoringStatus status = + await refactoring.checkInitialConditions(); + if (!status.hasFatalError) { + kinds.add(RefactoringKind.CONVERT_METHOD_TO_GETTER); + } } - } - // try RENAME - { - RenameRefactoring renameRefactoring = new RenameRefactoring( - refactoringWorkspace, server.getAstProvider(file), element); - if (renameRefactoring != null) { - kinds.add(RefactoringKind.RENAME); + // try RENAME + { + RenameRefactoring renameRefactoring = new RenameRefactoring( + refactoringWorkspace, resolvedUnit.session, element); + if (renameRefactoring != null) { + kinds.add(RefactoringKind.RENAME); + } } } } @@ -689,60 +648,6 @@ } /** - * Implementation of [DartAssistContext] that is based on the values passed - * in the constructor, as opposite to be partially based on [AssistContext]. - */ -class _DartAssistContextForValues implements DartAssistContext { - @override - final Source source; - - @override - final int selectionOffset; - - @override - final int selectionLength; - - @override - final AnalysisDriver analysisDriver; - - @override - final CompilationUnit unit; - - _DartAssistContextForValues(this.source, this.selectionOffset, - this.selectionLength, this.analysisDriver, this.unit); -} - -/** - * And implementation of [DartFixContext]. - */ -class _DartFixContextImpl implements DartFixContext { - @override - final ResourceProvider resourceProvider; - - @override - final AnalysisDriver analysisDriver; - - @override - final AstProvider astProvider; - - @override - final CompilationUnit unit; - - @override - final engine.AnalysisError error; - - @override - final List<engine.AnalysisError> errors; - - _DartFixContextImpl(this.resourceProvider, this.analysisDriver, - this.astProvider, this.unit, this.error, this.errors); - - @override - GetTopLevelDeclarations get getTopLevelDeclarations => - analysisDriver.getTopLevelNameDeclarations; -} - -/** * An object managing a single [Refactoring] instance. * * The instance is identified by its kind, file, offset and length. @@ -940,28 +845,35 @@ } // create a new Refactoring instance if (kind == RefactoringKind.CONVERT_GETTER_TO_METHOD) { - Element element = await server.getElementAtOffset(file, offset); - if (element != null) { - if (element is ExecutableElement) { - refactoring = new ConvertGetterToMethodRefactoring( - searchEngine, server.getAstProvider(file), element); + var resolvedUnit = await server.getResolvedUnit(file); + if (resolvedUnit != null) { + var node = new NodeLocator(offset).searchWithin(resolvedUnit.unit); + var element = server.getElementOfNode(node); + if (element != null) { + if (element is ExecutableElement) { + refactoring = new ConvertGetterToMethodRefactoring( + searchEngine, resolvedUnit.session, element); + } } } } if (kind == RefactoringKind.CONVERT_METHOD_TO_GETTER) { - Element element = await server.getElementAtOffset(file, offset); - if (element != null) { - if (element is ExecutableElement) { - refactoring = new ConvertMethodToGetterRefactoring( - searchEngine, server.getAstProvider(file), element); + var resolvedUnit = await server.getResolvedUnit(file); + if (resolvedUnit != null) { + var node = new NodeLocator(offset).searchWithin(resolvedUnit.unit); + var element = server.getElementOfNode(node); + if (element != null) { + if (element is ExecutableElement) { + refactoring = new ConvertMethodToGetterRefactoring( + searchEngine, resolvedUnit.session, element); + } } } } if (kind == RefactoringKind.EXTRACT_LOCAL_VARIABLE) { - var analysisResult = await server.getAnalysisResult(file); - if (analysisResult != null) { - refactoring = - new ExtractLocalRefactoring(analysisResult, offset, length); + var resolvedUnit = await server.getResolvedUnit(file); + if (resolvedUnit != null) { + refactoring = new ExtractLocalRefactoring(resolvedUnit, offset, length); feedback = new ExtractLocalVariableFeedback( <String>[], <int>[], <int>[], coveringExpressionOffsets: <int>[], @@ -969,34 +881,40 @@ } } if (kind == RefactoringKind.EXTRACT_METHOD) { - var analysisResult = await server.getAnalysisResult(file); - if (analysisResult != null) { - refactoring = new ExtractMethodRefactoring(searchEngine, - server.getAstProvider(file), analysisResult, offset, length); + var resolvedUnit = await server.getResolvedUnit(file); + if (resolvedUnit != null) { + refactoring = new ExtractMethodRefactoring( + searchEngine, resolvedUnit, offset, length); feedback = new ExtractMethodFeedback(offset, length, '', <String>[], false, <RefactoringMethodParameter>[], <int>[], <int>[]); } } if (kind == RefactoringKind.EXTRACT_WIDGET) { - var analysisResult = await server.getAnalysisResult(file); - if (analysisResult != null) { + var resolvedUnit = await server.getResolvedUnit(file); + if (resolvedUnit != null) { refactoring = new ExtractWidgetRefactoring( - searchEngine, analysisResult, offset, length); + searchEngine, resolvedUnit, offset, length); feedback = new ExtractWidgetFeedback(); } } if (kind == RefactoringKind.INLINE_LOCAL_VARIABLE) { - var analysisResult = await server.getAnalysisResult(file); - if (analysisResult != null) { + var resolvedUnit = await server.getResolvedUnit(file); + if (resolvedUnit != null) { refactoring = new InlineLocalRefactoring( - searchEngine, server.getAstProvider(file), analysisResult, offset); + searchEngine, + resolvedUnit, + offset, + ); } } if (kind == RefactoringKind.INLINE_METHOD) { - var analysisResult = await server.getAnalysisResult(file); - if (analysisResult != null) { + var resolvedUnit = await server.getResolvedUnit(file); + if (resolvedUnit != null) { refactoring = new InlineMethodRefactoring( - searchEngine, server.getAstProvider(file), analysisResult, offset); + searchEngine, + resolvedUnit, + offset, + ); } } if (kind == RefactoringKind.MOVE_FILE) { @@ -1009,41 +927,44 @@ // server.resourceProvider, searchEngine, context, source, file); } if (kind == RefactoringKind.RENAME) { - AstNode node = await server.getNodeAtOffset(file, offset); - Element element = server.getElementOfNode(node); - if (node != null && element != null) { - int feedbackOffset = node.offset; - int feedbackLength = node.length; + var resolvedUnit = await server.getResolvedUnit(file); + if (resolvedUnit != null) { + var node = new NodeLocator(offset).searchWithin(resolvedUnit.unit); + var element = server.getElementOfNode(node); + if (node != null && element != null) { + int feedbackOffset = node.offset; + int feedbackLength = node.length; - if (element is FieldFormalParameterElement) { - element = (element as FieldFormalParameterElement).field; - } - - // Use the prefix offset/length when renaming an import directive. - if (node is ImportDirective && element is ImportElement) { - if (node.prefix != null) { - feedbackOffset = node.prefix.offset; - feedbackLength = node.prefix.length; - } else { - feedbackOffset = -1; - feedbackLength = 0; + if (element is FieldFormalParameterElement) { + element = (element as FieldFormalParameterElement).field; } - } - // Rename the class when on `new` in an instance creation. - if (node is InstanceCreationExpression) { - InstanceCreationExpression creation = node; - var typeIdentifier = creation.constructorName.type.name; - element = typeIdentifier.staticElement; - feedbackOffset = typeIdentifier.offset; - feedbackLength = typeIdentifier.length; - } + // Use the prefix offset/length when renaming an import directive. + if (node is ImportDirective && element is ImportElement) { + if (node.prefix != null) { + feedbackOffset = node.prefix.offset; + feedbackLength = node.prefix.length; + } else { + feedbackOffset = -1; + feedbackLength = 0; + } + } - // do create the refactoring - refactoring = new RenameRefactoring( - refactoringWorkspace, server.getAstProvider(file), element); - feedback = new RenameFeedback( - feedbackOffset, feedbackLength, 'kind', 'oldName'); + // Rename the class when on `new` in an instance creation. + if (node is InstanceCreationExpression) { + InstanceCreationExpression creation = node; + var typeIdentifier = creation.constructorName.type.name; + element = typeIdentifier.staticElement; + feedbackOffset = typeIdentifier.offset; + feedbackLength = typeIdentifier.length; + } + + // do create the refactoring + refactoring = new RenameRefactoring( + refactoringWorkspace, resolvedUnit.session, element); + feedback = new RenameFeedback( + feedbackOffset, feedbackLength, 'kind', 'oldName'); + } } } if (refactoring == null) {
diff --git a/pkg/analysis_server/lib/src/edit/fix/prefer_int_literals_fix.dart b/pkg/analysis_server/lib/src/edit/fix/prefer_int_literals_fix.dart index 52dda1f..fa2ba99 100644 --- a/pkg/analysis_server/lib/src/edit/fix/prefer_int_literals_fix.dart +++ b/pkg/analysis_server/lib/src/edit/fix/prefer_int_literals_fix.dart
@@ -1,4 +1,4 @@ -// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. @@ -6,9 +6,9 @@ import 'package:analysis_server/src/edit/edit_dartfix.dart'; import 'package:analysis_server/src/services/correction/assist.dart'; import 'package:analysis_server/src/services/correction/assist_internal.dart'; -import 'package:analyzer/analyzer.dart'; +import 'package:analyzer/dart/analysis/results.dart'; import 'package:analyzer/dart/ast/ast.dart'; -import 'package:analyzer/src/dart/analysis/driver.dart'; +import 'package:analyzer/error/error.dart'; class PreferIntLiteralsFix extends LinterFix { final literalsToConvert = <DoubleLiteral>[]; @@ -16,11 +16,12 @@ PreferIntLiteralsFix(EditDartFix dartFix) : super(dartFix); @override - Future<void> applyLocalFixes(AnalysisResult result) async { + Future<void> applyLocalFixes(ResolvedUnitResult result) async { while (literalsToConvert.isNotEmpty) { DoubleLiteral literal = literalsToConvert.removeLast(); AssistProcessor processor = new AssistProcessor( - new EditDartFixAssistContext(dartFix, source, result.unit, literal)); + new DartAssistContextImpl(result, literal.offset, 0), + ); List<Assist> assists = await processor.computeAssist(DartAssistKind.CONVERT_TO_INT_LITERAL); final location =
diff --git a/pkg/analysis_server/lib/src/edit/fix/prefer_mixin_fix.dart b/pkg/analysis_server/lib/src/edit/fix/prefer_mixin_fix.dart index 52f924a..c929ff1 100644 --- a/pkg/analysis_server/lib/src/edit/fix/prefer_mixin_fix.dart +++ b/pkg/analysis_server/lib/src/edit/fix/prefer_mixin_fix.dart
@@ -1,4 +1,4 @@ -// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. @@ -6,10 +6,10 @@ import 'package:analysis_server/src/edit/edit_dartfix.dart'; import 'package:analysis_server/src/services/correction/assist.dart'; import 'package:analysis_server/src/services/correction/assist_internal.dart'; -import 'package:analyzer/analyzer.dart'; +import 'package:analyzer/dart/analysis/results.dart'; import 'package:analyzer/dart/ast/ast.dart'; import 'package:analyzer/dart/element/element.dart'; -import 'package:analyzer/src/dart/analysis/driver.dart'; +import 'package:analyzer/error/error.dart'; class PreferMixinFix extends LinterFix { final classesToConvert = new Set<Element>(); @@ -17,7 +17,7 @@ PreferMixinFix(EditDartFix dartFix) : super(dartFix); @override - Future<void> applyLocalFixes(AnalysisResult result) { + Future<void> applyLocalFixes(ResolvedUnitResult result) { // All fixes applied in [applyRemainingFixes] return null; } @@ -30,15 +30,15 @@ } Future<void> convertClassToMixin(Element elem) async { - AnalysisResult result = - await dartFix.server.getAnalysisResult(elem.source?.fullName); + ResolvedUnitResult result = + await dartFix.server.getResolvedUnit(elem.source?.fullName); for (CompilationUnitMember declaration in result.unit.declarations) { if (declaration is ClassOrMixinDeclaration && declaration.name.name == elem.name) { AssistProcessor processor = new AssistProcessor( - new EditDartFixAssistContext( - dartFix, elem.source, result.unit, declaration.name)); + new DartAssistContextImpl(result, declaration.name.offset, 0), + ); List<Assist> assists = await processor .computeAssist(DartAssistKind.CONVERT_CLASS_TO_MIXIN); final location =
diff --git a/pkg/analysis_server/lib/src/flutter/flutter_correction.dart b/pkg/analysis_server/lib/src/flutter/flutter_correction.dart index 459baf7..34e2864 100644 --- a/pkg/analysis_server/lib/src/flutter/flutter_correction.dart +++ b/pkg/analysis_server/lib/src/flutter/flutter_correction.dart
@@ -5,46 +5,34 @@ import 'dart:async'; import 'package:analysis_server/src/services/correction/util.dart'; -import 'package:analyzer/dart/analysis/session.dart'; +import 'package:analyzer/dart/analysis/results.dart'; import 'package:analyzer/dart/ast/ast.dart'; import 'package:analyzer/src/dart/ast/utilities.dart'; -import 'package:analyzer/src/generated/source.dart'; import 'package:analyzer_plugin/protocol/protocol_common.dart' hide Element; import 'package:analyzer_plugin/utilities/change_builder/change_builder_dart.dart'; import 'package:meta/meta.dart'; class FlutterCorrections { - final String file; - final String fileContent; - + final ResolvedUnitResult resolveResult; final int selectionOffset; final int selectionLength; final int selectionEnd; - final SourceRange selectionRange; - final AnalysisSession session; - final CompilationUnit unit; + final CorrectionUtils utils; AstNode node; - CorrectionUtils utils; FlutterCorrections( - {@required this.file, - @required this.fileContent, + {@required this.resolveResult, @required this.selectionOffset, - @required this.selectionLength, - @required this.session, - @required this.unit}) - : assert(file != null), - assert(fileContent != null), + @required this.selectionLength}) + : assert(resolveResult != null), assert(selectionOffset != null), assert(selectionLength != null), - assert(session != null), - assert(unit != null), selectionEnd = selectionOffset + selectionLength, - selectionRange = new SourceRange(selectionOffset, selectionLength) { - node = new NodeLocator(selectionOffset, selectionEnd).searchWithin(unit); - utils = new CorrectionUtils(unit, buffer: fileContent); + utils = new CorrectionUtils(resolveResult) { + node = new NodeLocator(selectionOffset, selectionEnd) + .searchWithin(resolveResult.unit); } /** @@ -59,8 +47,8 @@ if (node is ClassDeclaration) { var className = node.name.name; var location = utils.prepareNewConstructorLocation(node); - var changeBuilder = new DartChangeBuilder(session); - await changeBuilder.addFileEdit(file, (builder) { + var changeBuilder = new DartChangeBuilder(resolveResult.session); + await changeBuilder.addFileEdit(resolveResult.path, (builder) { builder.addInsertion(location.offset, (builder) { builder.write(location.prefix);
diff --git a/pkg/analysis_server/lib/src/flutter/flutter_domain.dart b/pkg/analysis_server/lib/src/flutter/flutter_domain.dart index 45698c4..7bc3713 100644 --- a/pkg/analysis_server/lib/src/flutter/flutter_domain.dart +++ b/pkg/analysis_server/lib/src/flutter/flutter_domain.dart
@@ -33,15 +33,13 @@ String file = params.file; int offset = params.offset; - ResolveResult result = await server.getAnalysisResult(file); + ResolvedUnitResult result = await server.getResolvedUnit(file); if (result != null) { var corrections = new FlutterCorrections( - file: file, - fileContent: result.content, - selectionOffset: offset, - selectionLength: 0, - session: result.session, - unit: result.unit); + resolveResult: result, + selectionOffset: offset, + selectionLength: 0, + ); SourceChange change = await corrections.addForDesignTimeConstructor(); if (change != null) { server.sendResponse(
diff --git a/pkg/analysis_server/lib/src/flutter/flutter_notifications.dart b/pkg/analysis_server/lib/src/flutter/flutter_notifications.dart index a468fd4..b387156 100644 --- a/pkg/analysis_server/lib/src/flutter/flutter_notifications.dart +++ b/pkg/analysis_server/lib/src/flutter/flutter_notifications.dart
@@ -6,13 +6,19 @@ import 'package:analysis_server/src/flutter/flutter_outline_computer.dart'; import 'package:analysis_server/src/protocol_server.dart' as protocol; import 'package:analyzer/dart/ast/ast.dart'; +import 'package:analyzer/src/generated/resolver.dart'; import 'package:analyzer/src/generated/source.dart'; -void sendFlutterNotificationOutline(AnalysisServer server, String file, - String content, LineInfo lineInfo, CompilationUnit dartUnit) { +void sendFlutterNotificationOutline( + AnalysisServer server, + String file, + String content, + LineInfo lineInfo, + CompilationUnit dartUnit, + TypeProvider typeProvider) { _sendNotification(server, () { - var computer = - new FlutterOutlineComputer(file, content, lineInfo, dartUnit); + var computer = new FlutterOutlineComputer( + file, content, lineInfo, dartUnit, typeProvider); protocol.FlutterOutline outline = computer.compute(); // send notification var params = new protocol.FlutterOutlineParams(file, outline,
diff --git a/pkg/analysis_server/lib/src/flutter/flutter_outline_computer.dart b/pkg/analysis_server/lib/src/flutter/flutter_outline_computer.dart index f1d5470..5d503b4 100644 --- a/pkg/analysis_server/lib/src/flutter/flutter_outline_computer.dart +++ b/pkg/analysis_server/lib/src/flutter/flutter_outline_computer.dart
@@ -45,8 +45,8 @@ final List<protocol.SourceEdit> instrumentationEdits = []; String instrumentedCode; - FlutterOutlineComputer(this.file, this.content, this.lineInfo, this.unit) - : typeProvider = unit.declaredElement.context.typeProvider; + FlutterOutlineComputer( + this.file, this.content, this.lineInfo, this.unit, this.typeProvider); protocol.FlutterOutline compute() { protocol.Outline dartOutline = new DartUnitOutlineComputer(
diff --git a/pkg/analysis_server/lib/src/lsp/channel/lsp_byte_stream_channel.dart b/pkg/analysis_server/lib/src/lsp/channel/lsp_byte_stream_channel.dart new file mode 100644 index 0000000..7861d0d --- /dev/null +++ b/pkg/analysis_server/lib/src/lsp/channel/lsp_byte_stream_channel.dart
@@ -0,0 +1,140 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'dart:async'; +import 'dart:convert'; +import 'dart:io'; + +import 'package:analysis_server/lsp_protocol/protocol_generated.dart'; +import 'package:analysis_server/lsp_protocol/protocol_special.dart'; +import 'package:analysis_server/src/analysis_server.dart'; +import 'package:analysis_server/src/lsp/channel/lsp_channel.dart'; +import 'package:analysis_server/src/lsp/lsp_packet_transformer.dart'; +import 'package:analyzer/instrumentation/instrumentation.dart'; + +/** + * Instances of the class [LspByteStreamServerChannel] implement an + * [LspServerCommunicationChannel] that uses a stream and a sink (typically, + * standard input and standard output) to communicate with clients. + */ +class LspByteStreamServerChannel implements LspServerCommunicationChannel { + final Stream _input; + + final IOSink _output; + + final InstrumentationService _instrumentationService; + + /** + * Completer that will be signalled when the input stream is closed. + */ + final Completer _closed = new Completer(); + + /** + * True if [close] has been called. + */ + bool _closeRequested = false; + + LspByteStreamServerChannel( + this._input, this._output, this._instrumentationService); + + /** + * Future that will be completed when the input stream is closed. + */ + Future get closed { + return _closed.future; + } + + @override + void close() { + if (!_closeRequested) { + _closeRequested = true; + assert(!_closed.isCompleted); + _closed.complete(); + } + } + + @override + void listen(void onMessage(IncomingMessage message), + {Function onError, void onDone()}) { + _input.transform(new LspPacketTransformer()).listen( + (String data) => _readMessage(data, onMessage), + onError: onError, + onDone: () { + close(); + onDone(); + }, + ); + } + + @override + void sendNotification(NotificationMessage notification) => + _sendLsp(notification.toJson()); + + @override + void sendResponse(ResponseMessage response) => _sendLsp(response.toJson()); + + /** + * Read a request from the given [data] and use the given function to handle + * the message. + */ + void _readMessage(String data, void onMessage(IncomingMessage request)) { + // Ignore any further requests after the communication channel is closed. + if (_closed.isCompleted) { + return; + } + ServerPerformanceStatistics.serverChannel.makeCurrentWhile(() { + _instrumentationService.logRequest(data); + final Map<String, Object> json = jsonDecode(data); + if (RequestMessage.canParse(json)) { + onMessage(RequestMessage.fromJson(json)); + } else if (NotificationMessage.canParse(json)) { + onMessage(NotificationMessage.fromJson(json)); + } else { + _sendParseError(); + } + }); + } + + /// Sends a message prefixed with the required LSP headers. + void _sendLsp(Map<String, Object> json) { + // Don't send any further responses after the communication channel is + // closed. + if (_closeRequested) { + return; + } + ServerPerformanceStatistics.serverChannel.makeCurrentWhile(() { + final jsonEncodedBody = jsonEncode(json); + final utf8EncodedBody = utf8.encode(jsonEncodedBody); + final header = 'Content-Length: ${utf8EncodedBody.length}\r\n' + 'Content-Type: application/vscode-jsonrpc; charset=utf-8\r\n\r\n'; + final asciiEncodedHeader = ascii.encode(header); + + // Header is always ascii, body is always utf8! + _write(asciiEncodedHeader); + _write(utf8EncodedBody); + + _instrumentationService.logResponse(jsonEncodedBody); + }); + } + + void _sendParseError() { + final error = new ResponseMessage( + null, + null, + new ResponseError( + ErrorCodes.ParseError, 'Unable to parse message', null), + jsonRpcVersion); + sendResponse(error); + } + + /** + * Send [bytes] to [_output]. + */ + void _write(List<int> bytes) { + runZoned( + () => _output.add(bytes), + onError: (e) => close(), + ); + } +}
diff --git a/pkg/analysis_server/lib/src/lsp/channel/lsp_channel.dart b/pkg/analysis_server/lib/src/lsp/channel/lsp_channel.dart new file mode 100644 index 0000000..dd23b812 --- /dev/null +++ b/pkg/analysis_server/lib/src/lsp/channel/lsp_channel.dart
@@ -0,0 +1,40 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:analysis_server/lsp_protocol/protocol_generated.dart'; +import 'package:analysis_server/lsp_protocol/protocol_special.dart'; +import 'package:analysis_server/src/lsp/lsp_analysis_server.dart'; + +/** + * The abstract class [LspServerCommunicationChannel] defines the behavior of + * objects that allow an [LspAnalysisServer] to receive [RequestMessage]s and + * [NotificationMessage]s and to return both [ResponseMessage]s and + * [NotificationMessage]s. + */ +abstract class LspServerCommunicationChannel { + /** + * Close the communication channel. + */ + void close(); + + /** + * Listen to the channel for messages. If a message is received, invoke the + * [onMessage] function. If an error is encountered while trying to read from + * the socket, invoke the [onError] function. If the socket is closed by the + * client, invoke the [onDone] function. + * Only one listener is allowed per channel. + */ + void listen(void onMessage(IncomingMessage message), + {Function onError, void onDone()}); + + /** + * Send the given [notification] to the client. + */ + void sendNotification(NotificationMessage notification); + + /** + * Send the given [response] to the client. + */ + void sendResponse(ResponseMessage response); +}
diff --git a/pkg/analysis_server/lib/src/lsp/dartdoc.dart b/pkg/analysis_server/lib/src/lsp/dartdoc.dart new file mode 100644 index 0000000..dd2de9e --- /dev/null +++ b/pkg/analysis_server/lib/src/lsp/dartdoc.dart
@@ -0,0 +1,24 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +final _dartdocCodeBlockSections = new RegExp(r'(```\w+) +\w+'); +final _dartdocDirectives = + new RegExp(r'(\n *{@.*?}$)|(^{@.*?}\n)', multiLine: true); + +String cleanDartdoc(String doc) { + if (doc == null) { + return null; + } + // Remove any dartdoc directives like {@template xxx} + doc = doc.replaceAll(_dartdocDirectives, ''); + + // Remove any code block section names like ```dart preamble that Flutter + // docs contain. + doc = doc.replaceAllMapped( + _dartdocCodeBlockSections, + (match) => match.group(1), + ); + + return doc; +}
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_completion.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_completion.dart new file mode 100644 index 0000000..6d7d0be --- /dev/null +++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_completion.dart
@@ -0,0 +1,100 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'dart:async'; +import 'dart:collection'; + +import 'package:analysis_server/lsp_protocol/protocol_generated.dart'; +import 'package:analysis_server/lsp_protocol/protocol_special.dart'; +import 'package:analysis_server/src/lsp/handlers/handlers.dart'; +import 'package:analysis_server/src/lsp/lsp_analysis_server.dart'; +import 'package:analysis_server/src/lsp/mapping.dart'; +import 'package:analysis_server/src/provisional/completion/completion_core.dart'; +import 'package:analysis_server/src/services/completion/completion_core.dart'; +import 'package:analysis_server/src/services/completion/completion_performance.dart'; +import 'package:analysis_server/src/services/completion/dart/completion_manager.dart'; +import 'package:analyzer/dart/analysis/results.dart'; + +// If the client does not provide capabilities.completion.completionItemKind.valueSet +// then we must never send a kind that's not in this list. +final defaultSupportedCompletionKinds = new HashSet<CompletionItemKind>.of([ + CompletionItemKind.Text, + CompletionItemKind.Method, + CompletionItemKind.Function, + CompletionItemKind.Constructor, + CompletionItemKind.Field, + CompletionItemKind.Variable, + CompletionItemKind.Class, + CompletionItemKind.Interface, + CompletionItemKind.Module, + CompletionItemKind.Property, + CompletionItemKind.Unit, + CompletionItemKind.Value, + CompletionItemKind.Enum, + CompletionItemKind.Keyword, + CompletionItemKind.Snippet, + CompletionItemKind.Color, + CompletionItemKind.File, + CompletionItemKind.Reference, +]); + +class CompletionHandler + extends MessageHandler<CompletionParams, List<CompletionItem>> { + CompletionHandler(LspAnalysisServer server) : super(server); + Method get handlesMessage => Method.textDocument_completion; + + @override + CompletionParams convertParams(Map<String, dynamic> json) => + CompletionParams.fromJson(json); + + Future<ErrorOr<List<CompletionItem>>> handle(CompletionParams params) async { + final completionCapabilities = + server?.clientCapabilities?.textDocument?.completion; + + final clientSupportedCompletionKinds = + completionCapabilities?.completionItemKind?.valueSet != null + ? new HashSet<CompletionItemKind>.of( + completionCapabilities.completionItemKind.valueSet) + : defaultSupportedCompletionKinds; + + final pos = params.position; + final path = pathOf(params.textDocument); + final unit = await path.mapResult(requireUnit); + final offset = await unit.mapResult((unit) => toOffset(unit.lineInfo, pos)); + return offset.mapResult((offset) => _getItems( + completionCapabilities, + clientSupportedCompletionKinds, + unit.result, + offset, + )); + } + + Future<ErrorOr<List<CompletionItem>>> _getItems( + TextDocumentClientCapabilitiesCompletion completionCapabilities, + HashSet<CompletionItemKind> clientSupportedCompletionKinds, + ResolvedUnitResult unit, + int offset, + ) async { + final performance = new CompletionPerformance(); + final completionRequest = + new CompletionRequestImpl(unit, offset, performance); + + try { + CompletionContributor contributor = new DartCompletionManager(); + final items = await contributor.computeSuggestions(completionRequest); + return success(items + .map((item) => toCompletionItem( + completionCapabilities, + clientSupportedCompletionKinds, + unit.lineInfo, + item, + completionRequest.replacementOffset, + completionRequest.replacementLength, + )) + .toList()); + } on AbortCompletion { + return success([]); + } + } +}
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_definition.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_definition.dart new file mode 100644 index 0000000..f06f364 --- /dev/null +++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_definition.dart
@@ -0,0 +1,46 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'dart:async'; + +import 'package:analysis_server/lsp_protocol/protocol_generated.dart'; +import 'package:analysis_server/lsp_protocol/protocol_special.dart'; +import 'package:analysis_server/src/domains/analysis/navigation_dart.dart'; +import 'package:analysis_server/src/lsp/handlers/handlers.dart'; +import 'package:analysis_server/src/lsp/lsp_analysis_server.dart'; +import 'package:analysis_server/src/lsp/mapping.dart'; +import 'package:analysis_server/src/protocol_server.dart' show NavigationTarget; +import 'package:analyzer_plugin/src/utilities/navigation/navigation.dart'; + +class DefinitionHandler + extends MessageHandler<TextDocumentPositionParams, List<Location>> { + DefinitionHandler(LspAnalysisServer server) : super(server); + Method get handlesMessage => Method.textDocument_definition; + + @override + TextDocumentPositionParams convertParams(Map<String, dynamic> json) => + TextDocumentPositionParams.fromJson(json); + + Future<ErrorOr<List<Location>>> handle( + TextDocumentPositionParams params) async { + final pos = params.position; + final path = pathOf(params.textDocument); + final unit = await path.mapResult(requireUnit); + final offset = await unit.mapResult((unit) => toOffset(unit.lineInfo, pos)); + + return offset.mapResult((offset) { + NavigationCollectorImpl collector = new NavigationCollectorImpl(); + computeDartNavigation( + server.resourceProvider, collector, unit.result.unit, offset, 0); + + Location toLocation(NavigationTarget target) { + final targetFilePath = collector.files[target.fileIndex]; + final lineInfo = server.getLineInfo(targetFilePath); + return navigationTargetToLocation(targetFilePath, target, lineInfo); + } + + return success(convert(collector.targets, toLocation).toList()); + }); + } +}
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_document_symbols.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_document_symbols.dart new file mode 100644 index 0000000..f805495 --- /dev/null +++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_document_symbols.dart
@@ -0,0 +1,157 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'dart:async'; +import 'dart:collection'; + +import 'package:analysis_server/lsp_protocol/protocol_generated.dart'; +import 'package:analysis_server/lsp_protocol/protocol_special.dart'; +import 'package:analysis_server/src/computer/computer_outline.dart'; +import 'package:analysis_server/src/lsp/handlers/handlers.dart'; +import 'package:analysis_server/src/lsp/lsp_analysis_server.dart'; +import 'package:analysis_server/src/lsp/mapping.dart'; +import 'package:analysis_server/src/protocol_server.dart' show Outline; +import 'package:analyzer/dart/analysis/results.dart'; +import 'package:analyzer/source/line_info.dart'; + +// If the client does not provide capabilities.documentSymbol.symbolKind.valueSet +// then we must never send a kind that's not in this list. +final defaultSupportedSymbolKinds = new HashSet<SymbolKind>.of([ + SymbolKind.File, + SymbolKind.Module, + SymbolKind.Namespace, + SymbolKind.Package, + SymbolKind.Class, + SymbolKind.Method, + SymbolKind.Property, + SymbolKind.Field, + SymbolKind.Constructor, + SymbolKind.Enum, + SymbolKind.Interface, + SymbolKind.Function, + SymbolKind.Variable, + SymbolKind.Constant, + SymbolKind.Str, + SymbolKind.Number, + SymbolKind.Boolean, + SymbolKind.Array, +]); + +class DocumentSymbolHandler extends MessageHandler<DocumentSymbolParams, + Either2<List<DocumentSymbol>, List<SymbolInformation>>> { + DocumentSymbolHandler(LspAnalysisServer server) : super(server); + Method get handlesMessage => Method.textDocument_documentSymbol; + + @override + DocumentSymbolParams convertParams(Map<String, dynamic> json) => + DocumentSymbolParams.fromJson(json); + + Future<ErrorOr<Either2<List<DocumentSymbol>, List<SymbolInformation>>>> + handle(DocumentSymbolParams params) async { + final symbolCapabilities = + server?.clientCapabilities?.textDocument?.documentSymbol; + + final clientSupportedSymbolKinds = + symbolCapabilities?.symbolKind?.valueSet != null + ? new HashSet<SymbolKind>.of(symbolCapabilities.symbolKind.valueSet) + : defaultSupportedSymbolKinds; + + final clientSupportsDocumentSymbol = + symbolCapabilities?.hierarchicalDocumentSymbolSupport ?? false; + + final path = pathOf(params.textDocument); + final unit = await path.mapResult(requireUnit); + return unit.mapResult((unit) => _getSymbols(clientSupportedSymbolKinds, + clientSupportsDocumentSymbol, path.result, unit)); + } + + DocumentSymbol _asDocumentSymbol( + HashSet<SymbolKind> clientSupportedSymbolKinds, + LineInfo lineInfo, + Outline outline, + ) { + return new DocumentSymbol( + outline.element.name, + outline.element.parameters, + elementKindToSymbolKind(clientSupportedSymbolKinds, outline.element.kind), + outline.element.isDeprecated, + toRange(lineInfo, outline.codeOffset, outline.codeLength), + toRange(lineInfo, outline.element.location.offset, + outline.element.location.length), + outline.children + ?.map((child) => + _asDocumentSymbol(clientSupportedSymbolKinds, lineInfo, child)) + ?.toList(), + ); + } + + SymbolInformation _asSymbolInformation( + String containerName, + HashSet<SymbolKind> clientSupportedSymbolKinds, + String documentUri, + LineInfo lineInfo, + Outline outline, + ) { + return new SymbolInformation( + outline.element.name, + elementKindToSymbolKind(clientSupportedSymbolKinds, outline.element.kind), + outline.element.isDeprecated, + new Location( + documentUri, + toRange(lineInfo, outline.element.location.offset, + outline.element.location.length), + ), + containerName, + ); + } + + ErrorOr<Either2<List<DocumentSymbol>, List<SymbolInformation>>> _getSymbols( + HashSet<SymbolKind> clientSupportedSymbolKinds, + bool clientSupportsDocumentSymbol, + String path, + ResolvedUnitResult unit, + ) { + final computer = + new DartUnitOutlineComputer(path, unit.lineInfo, unit.unit); + final outline = computer.compute(); + + if (clientSupportsDocumentSymbol) { + // Return a tree of DocumentSymbol only if the client shows explicit support + // for it. + return success( + Either2<List<DocumentSymbol>, List<SymbolInformation>>.t1( + outline?.children + ?.map((child) => _asDocumentSymbol( + clientSupportedSymbolKinds, unit.lineInfo, child)) + ?.toList(), + ), + ); + } else { + // Otherwise, we need to use the original flat SymbolInformation. + final allSymbols = <SymbolInformation>[]; + final documentUri = new Uri.file(path).toString(); + + // Adds a symbol and it's children recursively, supplying the parent + // name as required by SymbolInformation. + addSymbol(Outline outline, {String parentName}) { + allSymbols.add(_asSymbolInformation( + parentName, + clientSupportedSymbolKinds, + documentUri, + unit.lineInfo, + outline, + )); + outline.children?.forEach( + (c) => addSymbol(c, parentName: outline.element.name), + ); + } + + outline?.children?.forEach(addSymbol); + + return success( + Either2<List<DocumentSymbol>, List<SymbolInformation>>.t2(allSymbols), + ); + } + } +}
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_exit.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_exit.dart new file mode 100644 index 0000000..f2b3579 --- /dev/null +++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_exit.dart
@@ -0,0 +1,24 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'dart:async'; + +import 'package:analysis_server/lsp_protocol/protocol_generated.dart'; +import 'package:analysis_server/lsp_protocol/protocol_special.dart'; +import 'package:analysis_server/src/lsp/handlers/handlers.dart'; +import 'package:analysis_server/src/lsp/lsp_analysis_server.dart'; + +class ExitMessageHandler extends MessageHandler<void, void> { + ExitMessageHandler(LspAnalysisServer server) : super(server); + Method get handlesMessage => Method.exit; + + @override + void convertParams(Map<String, dynamic> json) => null; + + @override + Future<ErrorOr<void>> handle(void _) async { + await server.shutdown(); + return success(); + } +}
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_format_on_type.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_format_on_type.dart new file mode 100644 index 0000000..f704f06 --- /dev/null +++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_format_on_type.dart
@@ -0,0 +1,37 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'dart:async'; + +import 'package:analysis_server/lsp_protocol/protocol_generated.dart'; +import 'package:analysis_server/lsp_protocol/protocol_special.dart'; +import 'package:analysis_server/src/lsp/handlers/handlers.dart'; +import 'package:analysis_server/src/lsp/lsp_analysis_server.dart'; +import 'package:analysis_server/src/lsp/mapping.dart'; +import 'package:analysis_server/src/lsp/source_edits.dart'; +import 'package:analyzer/dart/analysis/results.dart'; + +class FormatOnTypeHandler + extends MessageHandler<DocumentOnTypeFormattingParams, List<TextEdit>> { + FormatOnTypeHandler(LspAnalysisServer server) : super(server); + Method get handlesMessage => Method.textDocument_onTypeFormatting; + + @override + DocumentOnTypeFormattingParams convertParams(Map<String, dynamic> json) => + DocumentOnTypeFormattingParams.fromJson(json); + + ErrorOr<List<TextEdit>> formatFile(String path, ResolvedUnitResult unit) { + final unformattedSource = server.fileContentOverlay[path] ?? + server.resourceProvider.getFile(path).readAsStringSync(); + + return success(generateEditsForFormatting(unformattedSource)); + } + + Future<ErrorOr<List<TextEdit>>> handle( + DocumentOnTypeFormattingParams params) async { + final path = pathOf(params.textDocument); + final unit = await path.mapResult(requireUnit); + return unit.mapResult((unit) => formatFile(path.result, unit)); + } +}
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_formatting.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_formatting.dart new file mode 100644 index 0000000..a0078c0 --- /dev/null +++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_formatting.dart
@@ -0,0 +1,37 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'dart:async'; + +import 'package:analysis_server/lsp_protocol/protocol_generated.dart'; +import 'package:analysis_server/lsp_protocol/protocol_special.dart'; +import 'package:analysis_server/src/lsp/handlers/handlers.dart'; +import 'package:analysis_server/src/lsp/lsp_analysis_server.dart'; +import 'package:analysis_server/src/lsp/mapping.dart'; +import 'package:analysis_server/src/lsp/source_edits.dart'; +import 'package:analyzer/dart/analysis/results.dart'; + +class FormattingHandler + extends MessageHandler<DocumentFormattingParams, List<TextEdit>> { + FormattingHandler(LspAnalysisServer server) : super(server); + Method get handlesMessage => Method.textDocument_formatting; + + @override + DocumentFormattingParams convertParams(Map<String, dynamic> json) => + DocumentFormattingParams.fromJson(json); + + ErrorOr<List<TextEdit>> formatFile(String path, ResolvedUnitResult unit) { + final unformattedSource = server.fileContentOverlay[path] ?? + server.resourceProvider.getFile(path).readAsStringSync(); + + return success(generateEditsForFormatting(unformattedSource)); + } + + Future<ErrorOr<List<TextEdit>>> handle( + DocumentFormattingParams params) async { + final path = pathOf(params.textDocument); + final unit = await path.mapResult(requireUnit); + return unit.mapResult((unit) => formatFile(path.result, unit)); + } +}
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_hover.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_hover.dart new file mode 100644 index 0000000..682bbdb --- /dev/null +++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_hover.dart
@@ -0,0 +1,84 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'dart:async'; + +import 'package:analysis_server/lsp_protocol/protocol_generated.dart'; +import 'package:analysis_server/lsp_protocol/protocol_special.dart'; +import 'package:analysis_server/protocol/protocol_generated.dart'; +import 'package:analysis_server/src/computer/computer_hover.dart'; +import 'package:analysis_server/src/lsp/dartdoc.dart'; +import 'package:analysis_server/src/lsp/handlers/handlers.dart'; +import 'package:analysis_server/src/lsp/lsp_analysis_server.dart'; +import 'package:analysis_server/src/lsp/mapping.dart'; +import 'package:analyzer/dart/analysis/results.dart'; +import 'package:analyzer/source/line_info.dart'; + +class HoverHandler extends MessageHandler<TextDocumentPositionParams, Hover> { + HoverHandler(LspAnalysisServer server) : super(server); + Method get handlesMessage => Method.textDocument_hover; + + @override + TextDocumentPositionParams convertParams(Map<String, dynamic> json) => + TextDocumentPositionParams.fromJson(json); + + Future<ErrorOr<Hover>> handle(TextDocumentPositionParams params) async { + final pos = params.position; + final path = pathOf(params.textDocument); + final unit = await path.mapResult(requireUnit); + final offset = await unit.mapResult((unit) => toOffset(unit.lineInfo, pos)); + return offset.mapResult((offset) => _getHover(unit.result, offset)); + } + + Hover toHover(LineInfo lineInfo, HoverInformation hover) { + if (hover == null) { + return null; + } + + // Import prefix tooltips are not useful currently. + // https://github.com/dart-lang/sdk/issues/32735 + if (hover.elementKind == 'import prefix') { + return null; + } + + final content = new StringBuffer(); + + // Description. + if (hover.elementDescription != null) { + content.writeln('```dart'); + if (hover.isDeprecated) { + content.write('(deprecated) '); + } + content..writeln(hover.elementDescription)..writeln('```')..writeln(); + } + + // Source library. + if (hover.containingLibraryName != null && + hover.containingLibraryName.isNotEmpty) { + content..writeln('*${hover.containingLibraryName}*')..writeln(); + } else if (hover.containingLibraryPath != null) { + // TODO(dantup): Support displaying the package name (probably by adding + // containingPackageName to the main hover?) once the analyzer work to + // support this (inc Bazel/Gn) is done. + // content..writeln('*${hover.containingPackageName}*')..writeln(); + } + + // Doc comments. + if (hover.dartdoc != null) { + content.writeln(cleanDartdoc(hover.dartdoc)); + } + + final formats = + server?.clientCapabilities?.textDocument?.hover?.contentFormat; + return new Hover( + asStringOrMarkupContent(formats, content.toString().trimRight()), + toRange(lineInfo, hover.offset, hover.length), + ); + } + + ErrorOr<Hover> _getHover(ResolvedUnitResult unit, int offset) { + final hover = new DartUnitHoverComputer(unit.unit, offset).compute(); + return success(toHover(unit.lineInfo, hover)); + } +}
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_initialize.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_initialize.dart new file mode 100644 index 0000000..9c4a555 --- /dev/null +++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_initialize.dart
@@ -0,0 +1,84 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:analysis_server/lsp_protocol/protocol_generated.dart'; +import 'package:analysis_server/lsp_protocol/protocol_special.dart'; +import 'package:analysis_server/src/lsp/handlers/handler_states.dart'; +import 'package:analysis_server/src/lsp/handlers/handlers.dart'; +import 'package:analysis_server/src/lsp/lsp_analysis_server.dart'; + +class InitializeMessageHandler + extends MessageHandler<InitializeParams, InitializeResult> { + InitializeMessageHandler(LspAnalysisServer server) : super(server); + + Method get handlesMessage => Method.initialize; + + @override + InitializeParams convertParams(Map<String, dynamic> json) => + InitializeParams.fromJson(json); + + ErrorOr<InitializeResult> handle(InitializeParams params) { + final openWorkspacePaths = <String>[]; + + if (params.workspaceFolders != null) { + params.workspaceFolders.forEach((wf) { + openWorkspacePaths.add(Uri.parse(wf.uri).toFilePath()); + }); + } + if (params.rootUri != null) { + openWorkspacePaths.add(Uri.parse(params.rootUri).toFilePath()); + // ignore: deprecated_member_use + } else if (params.rootPath != null) { + openWorkspacePaths.add(params.rootUri); + } + + server.setClientCapabilities(params.capabilities); + server.messageHandler = + new InitializingStateMessageHandler(server, openWorkspacePaths); + + return success(new InitializeResult(new ServerCapabilities( + Either2<TextDocumentSyncOptions, num>.t1(new TextDocumentSyncOptions( + true, + TextDocumentSyncKind.Incremental, + false, + false, + null, + )), + true, // hoverProvider + new CompletionOptions( + false, + // Set the characters that will cause the editor to automatically + // trigger completion. + // TODO(dantup): This is quite eager and may need filtering in the + // completion handler. + // See https://github.com/Dart-Code/Dart-Code/blob/c616c93c87972713454eb0518f97c0278201a99a/src/providers/dart_completion_item_provider.ts#L36 + r'''.: =(${'"/\'''.split(''), + ), + new SignatureHelpOptions( + // TODO(dantup): Signature help triggering is even more sensitive to + // bad chars, so we'll need to implement the logic described here: + // https://github.com/dart-lang/sdk/issues/34241 + [], + ), + true, // definitionProvider + null, + null, + true, // referencesProvider + null, + true, // documentSymbolProvider + null, + null, + null, + true, // documentFormattingProvider + false, // documentRangeFormattingProvider + new DocumentOnTypeFormattingOptions('}', [';']), + null, + null, + null, + null, + null, + null, + null))); + } +}
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_initialized.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_initialized.dart new file mode 100644 index 0000000..8201ae8 --- /dev/null +++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_initialized.dart
@@ -0,0 +1,28 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:analysis_server/lsp_protocol/protocol_generated.dart'; +import 'package:analysis_server/lsp_protocol/protocol_special.dart'; +import 'package:analysis_server/src/lsp/handlers/handler_states.dart'; +import 'package:analysis_server/src/lsp/handlers/handlers.dart'; +import 'package:analysis_server/src/lsp/lsp_analysis_server.dart'; + +class IntializedMessageHandler extends MessageHandler<InitializedParams, void> { + final List<String> openWorkspacePaths; + IntializedMessageHandler(LspAnalysisServer server, this.openWorkspacePaths) + : super(server); + Method get handlesMessage => Method.initialized; + + @override + InitializedParams convertParams(Map<String, dynamic> json) => + InitializedParams.fromJson(json); + + ErrorOr<void> handle(InitializedParams params) { + server.messageHandler = new InitializedStateMessageHandler(server); + + server.setAnalysisRoots(openWorkspacePaths, [], {}); + + return success(); + } +}
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_references.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_references.dart new file mode 100644 index 0000000..ec5dc37 --- /dev/null +++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_references.dart
@@ -0,0 +1,84 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'dart:async'; + +import 'package:analysis_server/lsp_protocol/protocol_generated.dart'; +import 'package:analysis_server/lsp_protocol/protocol_special.dart'; +import 'package:analysis_server/src/domains/analysis/navigation_dart.dart'; +import 'package:analysis_server/src/lsp/handlers/handlers.dart'; +import 'package:analysis_server/src/lsp/lsp_analysis_server.dart'; +import 'package:analysis_server/src/lsp/mapping.dart'; +import 'package:analysis_server/src/protocol_server.dart' show SearchResult; +import 'package:analysis_server/src/protocol_server.dart' show NavigationTarget; +import 'package:analysis_server/src/search/element_references.dart'; +import 'package:analyzer/dart/analysis/results.dart'; +import 'package:analyzer/dart/ast/ast.dart'; +import 'package:analyzer/dart/element/element.dart'; +import 'package:analyzer_plugin/src/utilities/navigation/navigation.dart'; + +class ReferencesHandler + extends MessageHandler<ReferenceParams, List<Location>> { + ReferencesHandler(LspAnalysisServer server) : super(server); + Method get handlesMessage => Method.textDocument_references; + + @override + ReferenceParams convertParams(Map<String, dynamic> json) => + ReferenceParams.fromJson(json); + + @override + Future<ErrorOr<List<Location>>> handle(ReferenceParams params) async { + final pos = params.position; + final path = pathOf(params.textDocument); + final unit = await path.mapResult(requireUnit); + final offset = await unit.mapResult((unit) => toOffset(unit.lineInfo, pos)); + return offset.mapResult( + (offset) => _getRefererences(path.result, offset, params, unit.result)); + } + + List<Location> _getDeclarations(CompilationUnit unit, int offset) { + final collector = new NavigationCollectorImpl(); + computeDartNavigation(server.resourceProvider, collector, unit, offset, 0); + + return convert(collector.targets, (NavigationTarget target) { + final targetFilePath = collector.files[target.fileIndex]; + final lineInfo = server.getLineInfo(targetFilePath); + return navigationTargetToLocation(targetFilePath, target, lineInfo); + }).toList(); + } + + Future<ErrorOr<List<Location>>> _getRefererences(String path, int offset, + ReferenceParams params, ResolvedUnitResult unit) async { + Element element = await server.getElementAtOffset(path, offset); + if (element is ImportElement) { + element = (element as ImportElement).prefix; + } + if (element is FieldFormalParameterElement) { + element = (element as FieldFormalParameterElement).field; + } + if (element is PropertyAccessorElement) { + element = (element as PropertyAccessorElement).variable; + } + if (element == null) { + return success(); + } + + final computer = new ElementReferencesComputer(server.searchEngine); + final results = await computer.compute(element, false); + + Location toLocation(SearchResult result) { + final lineInfo = server.getLineInfo(result.location.file); + return searchResultToLocation(result, lineInfo); + } + + final referenceResults = convert(results, toLocation).toList(); + + if (params.context?.includeDeclaration == true) { + // Also include the definition for the symbol at this location. + referenceResults.addAll(_getDeclarations(unit.unit, offset)); + } + + return success(referenceResults); + } +}
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_reject.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_reject.dart new file mode 100644 index 0000000..8cd06e5 --- /dev/null +++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_reject.dart
@@ -0,0 +1,27 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:analysis_server/lsp_protocol/protocol_generated.dart'; +import 'package:analysis_server/lsp_protocol/protocol_special.dart'; +import 'package:analysis_server/src/lsp/handlers/handlers.dart'; +import 'package:analysis_server/src/lsp/lsp_analysis_server.dart'; + +/// A [MessageHandler] that rejects specific tpyes of messages with a given +/// error code/message. +class RejectMessageHandler extends MessageHandler<Object, void> { + final Method handlesMessage; + final ErrorCodes errorCode; + final String errorMessage; + RejectMessageHandler(LspAnalysisServer server, this.handlesMessage, + this.errorCode, this.errorMessage) + : super(server); + + @override + void convertParams(Map<String, dynamic> json) => null; + + @override + ErrorOr<void> handle(void _) { + return error(errorCode, errorMessage, null); + } +}
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_shutdown.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_shutdown.dart new file mode 100644 index 0000000..82e50f6 --- /dev/null +++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_shutdown.dart
@@ -0,0 +1,23 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:analysis_server/lsp_protocol/protocol_generated.dart'; +import 'package:analysis_server/lsp_protocol/protocol_special.dart'; +import 'package:analysis_server/src/lsp/handlers/handlers.dart'; +import 'package:analysis_server/src/lsp/lsp_analysis_server.dart'; + +class ShutdownMessageHandler extends MessageHandler<void, void> { + ShutdownMessageHandler(LspAnalysisServer server) : super(server); + Method get handlesMessage => Method.shutdown; + + @override + void convertParams(Map<String, dynamic> json) => null; + + @override + ErrorOr<void> handle(void _) { + // We can clean up and shut down here, but we cannot terminate the server + // because that must be done after the exit notification. + return success(); + } +}
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_signature_help.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_signature_help.dart new file mode 100644 index 0000000..c5e0caf --- /dev/null +++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_signature_help.dart
@@ -0,0 +1,44 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'dart:async'; + +import 'package:analysis_server/lsp_protocol/protocol_generated.dart'; +import 'package:analysis_server/lsp_protocol/protocol_special.dart'; +import 'package:analysis_server/src/computer/computer_signature.dart'; +import 'package:analysis_server/src/lsp/handlers/handlers.dart'; +import 'package:analysis_server/src/lsp/lsp_analysis_server.dart'; +import 'package:analysis_server/src/lsp/mapping.dart'; + +class SignatureHelpHandler + extends MessageHandler<TextDocumentPositionParams, SignatureHelp> { + SignatureHelpHandler(LspAnalysisServer server) : super(server); + Method get handlesMessage => Method.textDocument_signatureHelp; + + @override + TextDocumentPositionParams convertParams(Map<String, dynamic> json) => + TextDocumentPositionParams.fromJson(json); + + Future<ErrorOr<SignatureHelp>> handle( + TextDocumentPositionParams params) async { + final pos = params.position; + final path = pathOf(params.textDocument); + final unit = await path.mapResult(requireUnit); + final offset = await unit.mapResult((unit) => toOffset(unit.lineInfo, pos)); + + return offset.mapResult((offset) { + final computer = new DartUnitSignatureComputer(unit.result.unit, offset); + if (!computer.offsetIsValid) { + return success(); // No error, just no valid hover. + } + final signature = computer.compute(); + if (signature == null) { + return success(); // No error, just no valid hover. + } + final formats = server?.clientCapabilities?.textDocument?.signatureHelp + ?.signatureInformation?.documentationFormat; + return success(toSignatureHelp(formats, signature)); + }); + } +}
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_states.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_states.dart new file mode 100644 index 0000000..af58e9c --- /dev/null +++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_states.dart
@@ -0,0 +1,82 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'dart:async'; + +import 'package:analysis_server/lsp_protocol/protocol_generated.dart'; +import 'package:analysis_server/lsp_protocol/protocol_special.dart'; +import 'package:analysis_server/src/lsp/handlers/handler_completion.dart'; +import 'package:analysis_server/src/lsp/handlers/handler_definition.dart'; +import 'package:analysis_server/src/lsp/handlers/handler_document_symbols.dart'; +import 'package:analysis_server/src/lsp/handlers/handler_format_on_type.dart'; +import 'package:analysis_server/src/lsp/handlers/handler_formatting.dart'; +import 'package:analysis_server/src/lsp/handlers/handler_hover.dart'; +import 'package:analysis_server/src/lsp/handlers/handler_initialize.dart'; +import 'package:analysis_server/src/lsp/handlers/handler_initialized.dart'; +import 'package:analysis_server/src/lsp/handlers/handler_references.dart'; +import 'package:analysis_server/src/lsp/handlers/handler_signature_help.dart'; +import 'package:analysis_server/src/lsp/handlers/handler_text_document_changes.dart'; +import 'package:analysis_server/src/lsp/handlers/handlers.dart'; +import 'package:analysis_server/src/lsp/lsp_analysis_server.dart'; + +class InitializedStateMessageHandler extends ServerStateMessageHandler { + InitializedStateMessageHandler(LspAnalysisServer server) : super(server) { + reject(Method.initialize, ServerErrorCodes.ServerAlreadyInitialized, + 'Server already initialized'); + reject(Method.initialized, ServerErrorCodes.ServerAlreadyInitialized, + 'Server already initialized'); + registerHandler(new TextDocumentOpenHandler(server)); + registerHandler(new TextDocumentChangeHandler(server)); + registerHandler(new TextDocumentCloseHandler(server)); + registerHandler(new HoverHandler(server)); + registerHandler(new CompletionHandler(server)); + registerHandler(new SignatureHelpHandler(server)); + registerHandler(new DefinitionHandler(server)); + registerHandler(new ReferencesHandler(server)); + registerHandler(new FormattingHandler(server)); + registerHandler(new FormatOnTypeHandler(server)); + registerHandler(new DocumentSymbolHandler(server)); + } +} + +class InitializingStateMessageHandler extends ServerStateMessageHandler { + InitializingStateMessageHandler( + LspAnalysisServer server, List<String> openWorkspacePaths) + : super(server) { + reject(Method.initialize, ServerErrorCodes.ServerAlreadyInitialized, + 'Server already initialized'); + registerHandler(new IntializedMessageHandler(server, openWorkspacePaths)); + } + + @override + ErrorOr<void> handleUnknownMessage(IncomingMessage message) { + // Silently drop non-requests. + if (message is! RequestMessage) { + return success(); + } + return failure( + ErrorCodes.ServerNotInitialized, + 'Unable to handle ${message.method} before the server is initialized ' + 'and the client has sent the initialized notification', + null); + } +} + +class UninitializedStateMessageHandler extends ServerStateMessageHandler { + UninitializedStateMessageHandler(LspAnalysisServer server) : super(server) { + registerHandler(new InitializeMessageHandler(server)); + } + + @override + FutureOr<ErrorOr<Object>> handleUnknownMessage(IncomingMessage message) { + // Silently drop non-requests. + if (message is! RequestMessage) { + return success(); + } + return failure( + ErrorCodes.ServerNotInitialized, + 'Unable to handle ${message.method} before client has sent initialize request', + null); + } +}
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_text_document_changes.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_text_document_changes.dart new file mode 100644 index 0000000..28ae74c --- /dev/null +++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_text_document_changes.dart
@@ -0,0 +1,91 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:analysis_server/lsp_protocol/protocol_generated.dart'; +import 'package:analysis_server/lsp_protocol/protocol_special.dart'; +import 'package:analysis_server/src/lsp/handlers/handlers.dart'; +import 'package:analysis_server/src/lsp/lsp_analysis_server.dart'; +import 'package:analysis_server/src/lsp/mapping.dart'; +import 'package:analysis_server/src/lsp/source_edits.dart'; + +class TextDocumentChangeHandler + extends MessageHandler<DidChangeTextDocumentParams, void> { + TextDocumentChangeHandler(LspAnalysisServer server) : super(server); + Method get handlesMessage => Method.textDocument_didChange; + + @override + DidChangeTextDocumentParams convertParams(Map<String, dynamic> json) => + DidChangeTextDocumentParams.fromJson(json); + + ErrorOr<void> handle(DidChangeTextDocumentParams params) { + final path = pathOf(params.textDocument); + return path.mapResult((path) => _changeFile(path, params)); + } + + ErrorOr<void> _changeFile(String path, DidChangeTextDocumentParams params) { + final oldContents = server.fileContentOverlay[path]; + // TODO(dantup): Should we be tracking the version? + + // Visual Studio has been seen to skip didOpen notifications for files that + // were already open when the LSP server initialized, so handle this with + // a specific message to make it clear what's happened. + if (oldContents == null) { + return error( + ErrorCodes.InvalidParams, + 'Unable to edit document because the file was not previously opened: $path', + null, + ); + } + final newContents = applyEdits(oldContents, params.contentChanges); + return newContents.mapResult((newcontents) { + server.updateOverlay(path, newContents.result); + return success(); + }); + } +} + +class TextDocumentCloseHandler + extends MessageHandler<DidCloseTextDocumentParams, void> { + TextDocumentCloseHandler(LspAnalysisServer server) : super(server); + Method get handlesMessage => Method.textDocument_didClose; + + @override + DidCloseTextDocumentParams convertParams(Map<String, dynamic> json) => + DidCloseTextDocumentParams.fromJson(json); + + ErrorOr<void> handle(DidCloseTextDocumentParams params) { + final path = pathOf(params.textDocument); + return path.mapResult((path) { + server.updateOverlay(path, null); + return success(); + }); + } +} + +class TextDocumentOpenHandler + extends MessageHandler<DidOpenTextDocumentParams, void> { + TextDocumentOpenHandler(LspAnalysisServer server) : super(server); + Method get handlesMessage => Method.textDocument_didOpen; + + @override + DidOpenTextDocumentParams convertParams(Map<String, dynamic> json) => + DidOpenTextDocumentParams.fromJson(json); + + ErrorOr<void> handle(DidOpenTextDocumentParams params) { + final doc = params.textDocument; + // TODO(dantup): This needs similar error handling to pathOf() + final path = Uri.parse(doc.uri).toFilePath(); + // TODO(dantup): Keep track of versions, so that when we compute fixes etc. + // we can send them back versions so the client can drop them if the document + // has been modified. + + server.updateOverlay(path, doc.text); + + // If the file did not exist, and is "overlay only", it still should be + // analyzed. Add it to driver to which it should have been added. + server.contextManager.getDriverFor(path)?.addFile(path); + + return success(); + } +}
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handlers.dart b/pkg/analysis_server/lib/src/lsp/handlers/handlers.dart new file mode 100644 index 0000000..d58569d --- /dev/null +++ b/pkg/analysis_server/lib/src/lsp/handlers/handlers.dart
@@ -0,0 +1,118 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'dart:async'; + +import 'package:analysis_server/lsp_protocol/protocol_generated.dart'; +import 'package:analysis_server/lsp_protocol/protocol_special.dart'; +import 'package:analysis_server/src/lsp/handlers/handler_exit.dart'; +import 'package:analysis_server/src/lsp/handlers/handler_reject.dart'; +import 'package:analysis_server/src/lsp/handlers/handler_shutdown.dart'; +import 'package:analysis_server/src/lsp/lsp_analysis_server.dart'; +import 'package:analyzer/dart/analysis/results.dart'; + +/// An object that can handle messages and produce responses for requests. +/// +/// Clients may not extend, implement or mix-in this class. +abstract class MessageHandler<P, R> { + LspAnalysisServer server; + + MessageHandler(this.server); + + /// The method that this handler can handle. + Method get handlesMessage; + + /// Converts an iterable using the provided function and skipping over any + /// null values. + Iterable<T> convert<T, E>(Iterable<E> items, T Function(E) converter) { + return items.map(converter).where((item) => item != null); + } + + P convertParams(Map<String, dynamic> json); + + ErrorOr<R> error<R>(ErrorCodes code, String message, Object data) => + new ErrorOr<R>.error(new ResponseError(code, message, data)); + + ErrorOr<R> failure<R>(ErrorOr<dynamic> error) => + new ErrorOr<R>.error(error.error); + + FutureOr<ErrorOr<R>> handle(P params); + + /// Handle the given [message]. If the [message] is a [RequestMessage], then the + /// return value will be sent back in a [ResponseMessage]. + /// [NotificationMessage]s are not expected to return results. + FutureOr<ErrorOr<R>> handleMessage(IncomingMessage message) { + final params = convertParams(message.params); + return handle(params); + } + + Future<ErrorOr<ResolvedUnitResult>> requireUnit(String path) async { + final result = await server.getResolvedUnit(path); + if (result?.state != ResultState.VALID) { + return error(ServerErrorCodes.InvalidFilePath, 'Invalid file path', path); + } + return success(result); + } + + ErrorOr<R> success<R>([R t]) => new ErrorOr<R>.success(t); +} + +/// A message handler that handles all messages for a given server state. +abstract class ServerStateMessageHandler { + final LspAnalysisServer server; + Map<Method, MessageHandler> _messageHandlers = {}; + + ServerStateMessageHandler(this.server) { + // All server states support shutdown and exit. + registerHandler(new ShutdownMessageHandler(server)); + registerHandler(new ExitMessageHandler(server)); + } + + ErrorOr<Object> failure<Object>( + ErrorCodes code, String message, Object data) => + new ErrorOr<Object>.error(new ResponseError(code, message, data)); + + /// Handle the given [message]. If the [message] is a [RequestMessage], then the + /// return value will be sent back in a [ResponseMessage]. + /// [NotificationMessage]s are not expected to return results. + FutureOr<ErrorOr<Object>> handleMessage(IncomingMessage message) async { + final handler = _messageHandlers[message.method]; + return handler != null + ? handler.handleMessage(message) + : handleUnknownMessage(message); + } + + FutureOr<ErrorOr<Object>> handleUnknownMessage(IncomingMessage message) { + // TODO(dantup): How should we handle unknown notifications that do + // *not* start with $/? + // https://github.com/Microsoft/language-server-protocol/issues/608 + if (!_isOptionalRequest(message)) { + return failure( + ErrorCodes.MethodNotFound, 'Unknown method ${message.method}', null); + } + return success(); + } + + registerHandler(MessageHandler handler) { + assert( + handler.handlesMessage != null, + 'Unable to register handler ${handler.runtimeType} because it does ' + 'not declare which messages it can handle'); + + _messageHandlers[handler.handlesMessage] = handler; + } + + reject(Method method, ErrorCodes code, String message) { + registerHandler(new RejectMessageHandler(server, method, code, message)); + } + + ErrorOr<Object> success<Object>([Object t]) => new ErrorOr<Object>.success(t); + + bool _isOptionalRequest(IncomingMessage message) { + // Messages that start with $/ are optional and can be silently ignored + // if we don't know how to handle them. + final stringValue = message.method.toJson(); + return stringValue is String && stringValue.startsWith(r'$/'); + } +}
diff --git a/pkg/analysis_server/lib/src/lsp/lsp_analysis_server.dart b/pkg/analysis_server/lib/src/lsp/lsp_analysis_server.dart new file mode 100644 index 0000000..3e1d0e7 --- /dev/null +++ b/pkg/analysis_server/lib/src/lsp/lsp_analysis_server.dart
@@ -0,0 +1,431 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'dart:async'; +import 'dart:io' as io; + +import 'package:analysis_server/lsp_protocol/protocol_generated.dart'; +import 'package:analysis_server/lsp_protocol/protocol_special.dart'; +import 'package:analysis_server/protocol/protocol_generated.dart' as protocol; +import 'package:analysis_server/src/analysis_server.dart'; +import 'package:analysis_server/src/analysis_server_abstract.dart'; +import 'package:analysis_server/src/context_manager.dart'; +import 'package:analysis_server/src/lsp/channel/lsp_channel.dart'; +import 'package:analysis_server/src/lsp/handlers/handler_states.dart'; +import 'package:analysis_server/src/lsp/handlers/handlers.dart'; +import 'package:analysis_server/src/lsp/mapping.dart'; +import 'package:analysis_server/src/plugin/notification_manager.dart'; +import 'package:analysis_server/src/protocol_server.dart' as protocol; +import 'package:analysis_server/src/services/search/search_engine.dart'; +import 'package:analysis_server/src/services/search/search_engine_internal.dart'; +import 'package:analysis_server/src/utilities/null_string_sink.dart'; +import 'package:analyzer/file_system/file_system.dart'; +import 'package:analyzer/instrumentation/instrumentation.dart'; +import 'package:analyzer/source/line_info.dart'; +import 'package:analyzer/src/context/builder.dart'; +import 'package:analyzer/src/context/context_root.dart'; +import 'package:analyzer/src/dart/analysis/byte_store.dart'; +import 'package:analyzer/src/dart/analysis/driver.dart' as nd; +import 'package:analyzer/src/dart/analysis/file_state.dart' as nd; +import 'package:analyzer/src/dart/analysis/performance_logger.dart'; +import 'package:analyzer/src/dart/analysis/status.dart' as nd; +import 'package:analyzer/src/generated/engine.dart'; +import 'package:analyzer/src/generated/sdk.dart'; +import 'package:analyzer/src/plugin/resolver_provider.dart'; +import 'package:watcher/watcher.dart'; + +/** + * Instances of the class [LspAnalysisServer] implement an LSP-based server that + * listens on a [CommunicationChannel] for LSP messages and processes them. + */ +class LspAnalysisServer extends AbstractAnalysisServer { + /// The capabilities of the LSP client. Will be null prior to initialization. + ClientCapabilities _clientCapabilities; + + /** + * The options of this server instance. + */ + AnalysisServerOptions options; + + /** + * The channel from which messages are received and to which responses should + * be sent. + */ + final LspServerCommunicationChannel channel; + + /// The [SearchEngine] for this server, may be `null` if indexing is disabled. + SearchEngine searchEngine; + + final NotificationManager notificationManager = new NullNotificationManager(); + + /** + * The object used to manage the SDK's known to this server. + */ + final DartSdkManager sdkManager; + + /** + * The instrumentation service that is to be used by this analysis server. + */ + final InstrumentationService instrumentationService; + + /** + * The content overlay for all analysis drivers. + */ + final nd.FileContentOverlay fileContentOverlay = new nd.FileContentOverlay(); + + /** + * The default options used to create new analysis contexts. This object is + * also referenced by the ContextManager. + */ + final AnalysisOptionsImpl defaultContextOptions = new AnalysisOptionsImpl(); + + /** + * The file resolver provider used to override the way file URI's are + * resolved in some contexts. + */ + ResolverProvider fileResolverProvider; + + /** + * The package resolver provider used to override the way package URI's are + * resolved in some contexts. + */ + ResolverProvider packageResolverProvider; + + PerformanceLog _analysisPerformanceLogger; + + ByteStore byteStore; + + nd.AnalysisDriverScheduler analysisDriverScheduler; + + ServerStateMessageHandler messageHandler; + + /** + * Initialize a newly created server to send and receive messages to the given + * [channel]. + */ + LspAnalysisServer( + this.channel, + ResourceProvider resourceProvider, + this.options, + this.sdkManager, + this.instrumentationService, { + ResolverProvider packageResolverProvider: null, + }) : super(resourceProvider) { + messageHandler = new UninitializedStateMessageHandler(this); + defaultContextOptions.generateImplicitErrors = false; + defaultContextOptions.useFastaParser = options.useFastaParser; + + { + String name = options.newAnalysisDriverLog; + StringSink sink = new NullStringSink(); + if (name != null) { + if (name == 'stdout') { + sink = io.stdout; + } else if (name.startsWith('file:')) { + String path = name.substring('file:'.length); + sink = new io.File(path).openWrite(mode: io.FileMode.append); + } + } + _analysisPerformanceLogger = new PerformanceLog(sink); + } + byteStore = createByteStore(resourceProvider); + analysisDriverScheduler = + new nd.AnalysisDriverScheduler(_analysisPerformanceLogger); + analysisDriverScheduler.start(); + + contextManager = new ContextManagerImpl( + resourceProvider, + fileContentOverlay, + sdkManager, + packageResolverProvider, + analyzedFilesGlobs, + instrumentationService, + defaultContextOptions); + final contextManagerCallbacks = + new LspServerContextManagerCallbacks(this, resourceProvider); + contextManager.callbacks = contextManagerCallbacks; + searchEngine = new SearchEngineImpl(driverMap.values); + + channel.listen(handleMessage, onDone: done, onError: error); + } + + /// The capabilities of the LSP client. Will be null prior to initialization. + ClientCapabilities get clientCapabilities => _clientCapabilities; + + /** + * The socket from which messages are being read has been closed. + */ + void done() {} + + /** + * There was an error related to the socket from which messages are being + * read. + */ + void error(error, stack) { + sendServerErrorNotification('Server error', error, stack); + } + + /// Return the LineInfo for the file with the given [path]. The file is + /// analyzed in one of the analysis drivers to which the file was added, + /// otherwise in the first driver, otherwise `null` is returned. + LineInfo getLineInfo(String path) { + if (!AnalysisEngine.isDartFileName(path)) { + return null; + } + + return getAnalysisDriver(path)?.getFileSync(path)?.lineInfo; + } + + /** + * Handle a [message] that was read from the communication channel. + */ + void handleMessage(IncomingMessage message) { + // TODO(dantup): Put in all the things this server is missing, like: + // _performance.logRequest(message); + runZoned(() { + ServerPerformanceStatistics.serverRequests.makeCurrentWhile(() async { + try { + final result = await messageHandler.handleMessage(message); + if (result.isError) { + sendErrorResponse(message, result.error); + } else if (message is RequestMessage) { + channel.sendResponse(new ResponseMessage( + message.id, result.result, null, jsonRpcVersion)); + } + } catch (error, stackTrace) { + sendErrorResponse( + message, + new ResponseError( + ServerErrorCodes.UnhandledError, + 'An error occurred while handling ${message.method} message', + null)); + logError(error.toString()); + if (stackTrace != null) { + logError(stackTrace.toString()); + } + } + }); + }, onError: error); + } + + void logError(String message) { + channel.sendNotification(new NotificationMessage( + Method.window_logMessage, + new LogMessageParams(MessageType.Error, message), + jsonRpcVersion, + )); + } + + void sendErrorResponse(IncomingMessage message, ResponseError error) { + if (message is RequestMessage) { + channel.sendResponse( + new ResponseMessage(message.id, null, error, jsonRpcVersion)); + // Since the LSP client might not show the failed requests to the user, + // also ensure the error is logged to the client. + logError(error.message); + } else { + // For notifications where we couldn't respond with an error, send it as + // show instead of log. + showError(error.message); + } + } + + /** + * Send the given [notification] to the client. + */ + void sendNotification(NotificationMessage notification) { + channel.sendNotification(notification); + } + + /** + * Send the given [response] to the client. + */ + void sendResponse(ResponseMessage response) { + channel.sendResponse(response); + } + + void sendServerErrorNotification(String message, exception, stackTrace) { + final fullError = new StringBuffer(); + fullError.writeln(message); + if (exception != null) { + fullError.writeln(exception.toString()); + } + if (stackTrace != null) { + fullError.writeln(stackTrace.toString()); + } + showError(message); // Show message to the user. + logError(fullError.toString()); // Log the full message. + } + + void setAnalysisRoots(List<String> includedPaths, List<String> excludedPaths, + Map<String, String> packageRoots) { + contextManager.setRoots(includedPaths, excludedPaths, packageRoots); + } + + void setClientCapabilities(ClientCapabilities capabilities) { + _clientCapabilities = capabilities; + } + + /** + * Returns `true` if errors should be reported for [file] with the given + * absolute path. + */ + bool shouldSendErrorsNotificationFor(String file) { + return contextManager.isInAnalysisRoot(file); + } + + void showError(String message) { + channel.sendNotification(new NotificationMessage( + Method.window_showMessage, + new ShowMessageParams(MessageType.Error, message), + jsonRpcVersion, + )); + } + + Future<void> shutdown() { + // Defer closing the channel so that the shutdown response can be sent and + // logged. + new Future(() { + channel.close(); + }); + + return new Future.value(); + } + + void updateOverlay(String path, String contents) { + fileContentOverlay[path] = contents; + driverMap.values.forEach((driver) => driver.changeFile(path)); + } +} + +class LspServerContextManagerCallbacks extends ContextManagerCallbacks { + // TODO(dantup): Lots of copy/paste from the Analysis Server one here. + + final LspAnalysisServer analysisServer; + + /** + * The [ResourceProvider] by which paths are converted into [Resource]s. + */ + final ResourceProvider resourceProvider; + + LspServerContextManagerCallbacks(this.analysisServer, this.resourceProvider); + + @override + NotificationManager get notificationManager => + analysisServer.notificationManager; + + @override + nd.AnalysisDriver addAnalysisDriver( + Folder folder, ContextRoot contextRoot, AnalysisOptions options) { + ContextBuilder builder = createContextBuilder(folder, options); + nd.AnalysisDriver analysisDriver = builder.buildDriver(contextRoot); + analysisDriver.results.listen((result) { + String path = result.path; + if (analysisServer.shouldSendErrorsNotificationFor(path)) { + final serverErrors = protocol.mapEngineErrors( + result.session.analysisContext.analysisOptions, + result.lineInfo, + result.errors, + toDiagnostic); + + final params = new PublishDiagnosticsParams( + Uri.file(result.path).toString(), serverErrors); + // TODO(dantup): Move all these method names to constants. + final message = new NotificationMessage( + Method.textDocument_publishDiagnostics, + params, + jsonRpcVersion, + ); + analysisServer.sendNotification(message); + } + }); + analysisDriver.exceptions.listen((nd.ExceptionResult result) { + String message = 'Analysis failed: ${result.path}'; + if (result.contextKey != null) { + message += ' context: ${result.contextKey}'; + } + AnalysisEngine.instance.logger.logError(message, result.exception); + }); + analysisServer.driverMap[folder] = analysisDriver; + return analysisDriver; + } + + @override + void afterWatchEvent(WatchEvent event) { + // TODO: implement afterWatchEvent + } + + @override + void applyChangesToContext(Folder contextFolder, ChangeSet changeSet) { + nd.AnalysisDriver analysisDriver = analysisServer.driverMap[contextFolder]; + if (analysisDriver != null) { + changeSet.addedSources.forEach((source) { + analysisDriver.addFile(source.fullName); + }); + changeSet.changedSources.forEach((source) { + analysisDriver.changeFile(source.fullName); + }); + changeSet.removedSources.forEach((source) { + analysisDriver.removeFile(source.fullName); + }); + } + } + + @override + void applyFileRemoved(nd.AnalysisDriver driver, String file) { + driver.removeFile(file); + // sendAnalysisNotificationFlushResults(analysisServer, [file]); + } + + @override + void broadcastWatchEvent(WatchEvent event) { + // TODO: implement broadcastWatchEvent + } + + @override + ContextBuilder createContextBuilder(Folder folder, AnalysisOptions options) { + String defaultPackageFilePath = null; + String defaultPackagesDirectoryPath = null; + String path = (analysisServer.contextManager as ContextManagerImpl) + .normalizedPackageRoots[folder.path]; + if (path != null) { + Resource resource = resourceProvider.getResource(path); + if (resource.exists) { + if (resource is File) { + defaultPackageFilePath = path; + } else { + defaultPackagesDirectoryPath = path; + } + } + } + + ContextBuilderOptions builderOptions = new ContextBuilderOptions(); + builderOptions.defaultOptions = options; + builderOptions.defaultPackageFilePath = defaultPackageFilePath; + builderOptions.defaultPackagesDirectoryPath = defaultPackagesDirectoryPath; + ContextBuilder builder = new ContextBuilder( + resourceProvider, analysisServer.sdkManager, null, + options: builderOptions); + builder.fileResolverProvider = analysisServer.fileResolverProvider; + builder.packageResolverProvider = analysisServer.packageResolverProvider; + builder.analysisDriverScheduler = analysisServer.analysisDriverScheduler; + builder.performanceLog = analysisServer._analysisPerformanceLogger; + builder.byteStore = analysisServer.byteStore; + builder.enableIndex = true; + builder.fileContentOverlay = analysisServer.fileContentOverlay; + return builder; + } + + @override + void removeContext(Folder folder, List<String> flushedFiles) { + // sendAnalysisNotificationFlushResults(analysisServer, flushedFiles); + nd.AnalysisDriver driver = analysisServer.driverMap.remove(folder); + driver.dispose(); + } +} + +class NullNotificationManager implements NotificationManager { + @override + noSuchMethod(Invocation invocation) {} +}
diff --git a/pkg/analysis_server/lib/src/lsp/lsp_packet_transformer.dart b/pkg/analysis_server/lib/src/lsp/lsp_packet_transformer.dart new file mode 100644 index 0000000..c766875 --- /dev/null +++ b/pkg/analysis_server/lib/src/lsp/lsp_packet_transformer.dart
@@ -0,0 +1,73 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'dart:async'; +import 'dart:convert'; + +/// Transforms a stream of LSP data in the form: +/// +/// Content-Length: xxx\r\n +/// Content-Type: application/vscode-jsonrpc; charset=utf-8\r\n +/// \r\n +/// { JSON payload } +/// +/// into just the JSON payload, decoded with the specified encoding. Line endings +/// for headers must be \r\n on all platforms as defined in the LSP spec. +class LspPacketTransformer extends StreamTransformerBase<List<int>, String> { + @override + Stream<String> bind(Stream<List<int>> stream) { + StreamSubscription<int> input; + StreamController<String> _output; + final buffer = <int>[]; + bool isParsingHeaders = true; + int contentLength; + _output = StreamController<String>( + onListen: () { + input = stream.expand((b) => b).listen( + (codeUnit) { + buffer.add(codeUnit); + if (isParsingHeaders && _endsWithCrLfCrLf(buffer)) { + contentLength = _parseContentLength(buffer); + buffer.clear(); + isParsingHeaders = false; + } else if (!isParsingHeaders && buffer.length >= contentLength) { + // LSP Spec: "It defaults to utf-8, which is the only encoding + // supported right now". + _output.add(utf8.decode(buffer)); + buffer.clear(); + isParsingHeaders = true; + } + }, + onError: _output.addError, + onDone: _output.close, + ); + }, + onPause: () => input.pause(), + onResume: () => input.resume(), + onCancel: () => input.cancel(), + ); + return _output.stream; + } + + /// Whether [buffer] ends in '\r\n\r\n'. + static bool _endsWithCrLfCrLf(List<int> buffer) { + var l = buffer.length; + return l > 4 && + buffer[l - 1] == 10 && + buffer[l - 2] == 13 && + buffer[l - 3] == 10 && + buffer[l - 4] == 13; + } + + /// Decodes [buffer] into a String and returns the 'Content-Length' header value. + static int _parseContentLength(List<int> buffer) { + // Headers are specified as always ASCII in LSP. + var asString = ascii.decode(buffer); + var headers = asString.split('\r\n'); + var lengthHeader = + headers.firstWhere((h) => h.startsWith('Content-Length')); + var length = lengthHeader.split(':').last.trim(); + return int.parse(length); + } +}
diff --git a/pkg/analysis_server/lib/src/lsp/lsp_socket_server.dart b/pkg/analysis_server/lib/src/lsp/lsp_socket_server.dart new file mode 100644 index 0000000..1831321 --- /dev/null +++ b/pkg/analysis_server/lib/src/lsp/lsp_socket_server.dart
@@ -0,0 +1,82 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:analysis_server/lsp_protocol/protocol_generated.dart'; +import 'package:analysis_server/lsp_protocol/protocol_special.dart'; +import 'package:analysis_server/src/analysis_server.dart'; +import 'package:analysis_server/src/lsp/channel/lsp_channel.dart'; +import 'package:analysis_server/src/lsp/lsp_analysis_server.dart'; +import 'package:analysis_server/src/socket_server.dart'; +import 'package:analyzer/file_system/physical_file_system.dart'; +import 'package:analyzer/instrumentation/instrumentation.dart'; +import 'package:analyzer/src/generated/sdk.dart'; + +/** + * Instances of the class [SocketServer] implement the common parts of + * http-based and stdio-based analysis servers. The primary responsibility of + * the SocketServer is to manage the lifetime of the AnalysisServer and to + * encode and decode the JSON messages exchanged with the client. + */ +class LspSocketServer { + final AnalysisServerOptions analysisServerOptions; + /** + * The analysis server that was created when a client established a + * connection, or `null` if no such connection has yet been established. + */ + LspAnalysisServer analysisServer; + + /** + * The function used to create a new SDK using the default SDK. + */ + final DartSdkManager sdkManager; + + final InstrumentationService instrumentationService; + + LspSocketServer( + this.analysisServerOptions, + this.sdkManager, + this.instrumentationService, + ); + + /** + * Create an analysis server which will communicate with the client using the + * given serverChannel. + */ + void createAnalysisServer(LspServerCommunicationChannel serverChannel) { + if (analysisServer != null) { + ResponseError error = new ResponseError<void>( + ServerErrorCodes.ServerAlreadyStarted, + 'Server already started', + null); + serverChannel.sendNotification(new NotificationMessage( + Method.window_showMessage, + new ShowMessageParams(MessageType.Error, error.message), + jsonRpcVersion, + )); + serverChannel.listen((IncomingMessage message) { + if (message is RequestMessage) { + serverChannel.sendResponse( + new ResponseMessage(message.id, null, error, jsonRpcVersion)); + } + }); + return; + } + + PhysicalResourceProvider resourceProvider; + if (analysisServerOptions.fileReadMode == 'as-is') { + resourceProvider = new PhysicalResourceProvider(null, + stateLocation: analysisServerOptions.cacheFolder); + } else if (analysisServerOptions.fileReadMode == 'normalize-eol-always') { + resourceProvider = new PhysicalResourceProvider( + PhysicalResourceProvider.NORMALIZE_EOL_ALWAYS, + stateLocation: analysisServerOptions.cacheFolder); + } else { + throw new Exception( + 'File read mode was set to the unknown mode: $analysisServerOptions.fileReadMode'); + } + + analysisServer = new LspAnalysisServer(serverChannel, resourceProvider, + analysisServerOptions, sdkManager, instrumentationService); + } +}
diff --git a/pkg/analysis_server/lib/src/lsp/mapping.dart b/pkg/analysis_server/lib/src/lsp/mapping.dart new file mode 100644 index 0000000..414ba60 --- /dev/null +++ b/pkg/analysis_server/lib/src/lsp/mapping.dart
@@ -0,0 +1,499 @@ +import 'dart:collection'; + +import 'package:analysis_server/lsp_protocol/protocol_generated.dart' as lsp; +import 'package:analysis_server/lsp_protocol/protocol_generated.dart'; +import 'package:analysis_server/lsp_protocol/protocol_special.dart' as lsp; +import 'package:analysis_server/lsp_protocol/protocol_special.dart'; +import 'package:analysis_server/src/lsp/dartdoc.dart'; +import 'package:analysis_server/src/lsp/lsp_analysis_server.dart' as lsp; +import 'package:analysis_server/src/protocol_server.dart' as server + hide AnalysisError; +import 'package:analyzer/dart/analysis/results.dart' as server; +import 'package:analyzer/error/error.dart' as server; +import 'package:analyzer/source/line_info.dart' as server; +import 'package:analyzer/src/generated/source.dart' as server; + +const languageSourceName = 'dart'; + +lsp.Either2<String, lsp.MarkupContent> asStringOrMarkupContent( + List<lsp.MarkupKind> preferredFormats, String content) { + if (content == null) { + return null; + } + + return preferredFormats == null + ? new lsp.Either2<String, lsp.MarkupContent>.t1(content) + : new lsp.Either2<String, lsp.MarkupContent>.t2( + _asMarkup(preferredFormats, content)); +} + +lsp.CompletionItemKind elementKindToCompletionItemKind( + HashSet<lsp.CompletionItemKind> clientSupportedCompletionKinds, + server.ElementKind kind, +) { + bool isSupported(lsp.CompletionItemKind kind) => + clientSupportedCompletionKinds.contains(kind); + + List<lsp.CompletionItemKind> getKindPreferences() { + switch (kind) { + case server.ElementKind.CLASS: + case server.ElementKind.CLASS_TYPE_ALIAS: + return const [lsp.CompletionItemKind.Class]; + case server.ElementKind.COMPILATION_UNIT: + return const [lsp.CompletionItemKind.Module]; + case server.ElementKind.CONSTRUCTOR: + case server.ElementKind.CONSTRUCTOR_INVOCATION: + return const [lsp.CompletionItemKind.Constructor]; + case server.ElementKind.ENUM: + case server.ElementKind.ENUM_CONSTANT: + return const [lsp.CompletionItemKind.Enum]; + case server.ElementKind.FIELD: + return const [lsp.CompletionItemKind.Field]; + case server.ElementKind.FILE: + return const [lsp.CompletionItemKind.File]; + case server.ElementKind.FUNCTION: + return const [lsp.CompletionItemKind.Function]; + case server.ElementKind.FUNCTION_TYPE_ALIAS: + return const [lsp.CompletionItemKind.Class]; + case server.ElementKind.GETTER: + return const [lsp.CompletionItemKind.Property]; + case server.ElementKind.LABEL: + // There isn't really a good CompletionItemKind for labels so we'll + // just use the Text option. + return const [lsp.CompletionItemKind.Text]; + case server.ElementKind.LIBRARY: + return const [lsp.CompletionItemKind.Module]; + case server.ElementKind.LOCAL_VARIABLE: + return const [lsp.CompletionItemKind.Variable]; + case server.ElementKind.METHOD: + return const [lsp.CompletionItemKind.Method]; + case server.ElementKind.PARAMETER: + case server.ElementKind.PREFIX: + return const [lsp.CompletionItemKind.Variable]; + case server.ElementKind.SETTER: + return const [lsp.CompletionItemKind.Property]; + case server.ElementKind.TOP_LEVEL_VARIABLE: + return const [lsp.CompletionItemKind.Variable]; + case server.ElementKind.TYPE_PARAMETER: + return const [ + lsp.CompletionItemKind.TypeParameter, + lsp.CompletionItemKind.Variable, + ]; + case server.ElementKind.UNIT_TEST_GROUP: + case server.ElementKind.UNIT_TEST_TEST: + return const [lsp.CompletionItemKind.Method]; + default: + return null; + } + } + + return getKindPreferences().firstWhere(isSupported, orElse: () => null); +} + +lsp.SymbolKind elementKindToSymbolKind( + HashSet<lsp.SymbolKind> clientSupportedSymbolKinds, + server.ElementKind kind, +) { + bool isSupported(lsp.SymbolKind kind) => + clientSupportedSymbolKinds.contains(kind); + + List<lsp.SymbolKind> getKindPreferences() { + switch (kind) { + case server.ElementKind.CLASS: + case server.ElementKind.CLASS_TYPE_ALIAS: + return const [lsp.SymbolKind.Class]; + case server.ElementKind.COMPILATION_UNIT: + return const [lsp.SymbolKind.Module]; + case server.ElementKind.CONSTRUCTOR: + case server.ElementKind.CONSTRUCTOR_INVOCATION: + return const [lsp.SymbolKind.Constructor]; + case server.ElementKind.ENUM: + case server.ElementKind.ENUM_CONSTANT: + return const [lsp.SymbolKind.Enum]; + case server.ElementKind.FIELD: + return const [lsp.SymbolKind.Field]; + case server.ElementKind.FILE: + return const [lsp.SymbolKind.File]; + case server.ElementKind.FUNCTION: + case server.ElementKind.FUNCTION_INVOCATION: + return const [lsp.SymbolKind.Function]; + case server.ElementKind.FUNCTION_TYPE_ALIAS: + return const [lsp.SymbolKind.Class]; + case server.ElementKind.GETTER: + return const [lsp.SymbolKind.Property]; + case server.ElementKind.LABEL: + // There isn't really a good SymbolKind for labels so we'll + // just use the Null option. + return const [lsp.SymbolKind.Null]; + case server.ElementKind.LIBRARY: + return const [lsp.SymbolKind.Namespace]; + case server.ElementKind.LOCAL_VARIABLE: + return const [lsp.SymbolKind.Variable]; + case server.ElementKind.METHOD: + return const [lsp.SymbolKind.Method]; + case server.ElementKind.MIXIN: + return const [lsp.SymbolKind.Class]; + case server.ElementKind.PARAMETER: + case server.ElementKind.PREFIX: + return const [lsp.SymbolKind.Variable]; + case server.ElementKind.SETTER: + return const [lsp.SymbolKind.Property]; + case server.ElementKind.TOP_LEVEL_VARIABLE: + return const [lsp.SymbolKind.Variable]; + case server.ElementKind.TYPE_PARAMETER: + return const [ + lsp.SymbolKind.TypeParameter, + lsp.SymbolKind.Variable, + ]; + case server.ElementKind.UNIT_TEST_GROUP: + case server.ElementKind.UNIT_TEST_TEST: + return const [lsp.SymbolKind.Method]; + default: + // TODO(dantup): Do we want an assert here to crash in test runs? It's + // valid to return null but we should aim to have everything above. + return null; + } + } + + return getKindPreferences().firstWhere(isSupported, orElse: () => null); +} + +String getCompletionDetail( + server.CompletionSuggestion suggestion, + lsp.CompletionItemKind completionKind, + bool clientSupportsDeprecated, +) { + final hasElement = suggestion.element != null; + final hasParameters = hasElement && + suggestion.element.parameters != null && + suggestion.element.parameters.isNotEmpty; + final hasReturnType = hasElement && + suggestion.element.returnType != null && + suggestion.element.returnType.isNotEmpty; + final hasParameterType = + suggestion.parameterType != null && suggestion.parameterType.isNotEmpty; + + final prefix = clientSupportsDeprecated || !suggestion.isDeprecated + ? '' + : '(Deprecated) '; + + if (completionKind == lsp.CompletionItemKind.Property) { + // Setters appear as methods with one arg but they also cause getters to not + // appear in the completion list, so displaying them as setters is misleading. + // To avoid this, always show only the return type, whether it's a getter + // or a setter. + return prefix + + (suggestion.element.kind == server.ElementKind.GETTER + ? suggestion.element.returnType + // Don't assume setters always have parameters + // See https://github.com/dart-lang/sdk/issues/27747 + : suggestion.element.parameters != null && + suggestion.element.parameters.isNotEmpty + // Extract the type part from '(MyType value)` + ? suggestion.element.parameters.substring( + 1, suggestion.element.parameters.lastIndexOf(" ")) + : ''); + } else if (hasParameters && hasReturnType) { + return '$prefix${suggestion.element.parameters} → ${suggestion.element.returnType}'; + } else if (hasReturnType) { + return '$prefix${suggestion.element.returnType}'; + } else if (hasParameterType) { + return '$prefix${suggestion.parameterType}'; + } else { + return prefix; + } +} + +lsp.Location navigationTargetToLocation(String targetFilePath, + server.NavigationTarget target, server.LineInfo lineInfo) { + if (lineInfo == null) { + return null; + } + + return new Location( + Uri.file(targetFilePath).toString(), + toRange(lineInfo, target.offset, target.length), + ); +} + +/// Returns the file system path for a TextDocumentIdentifier. +ErrorOr<String> pathOf(lsp.TextDocumentIdentifier doc) { + final uri = Uri.tryParse(doc.uri); + final isValidFileUri = (uri?.isScheme('file') ?? false); + if (!isValidFileUri) { + return new ErrorOr<String>.error(new ResponseError( + lsp.ServerErrorCodes.InvalidFilePath, + 'URI was not a valid file:// URI', + doc.uri)); + } + try { + return new ErrorOr<String>.success(uri.toFilePath()); + } catch (e) { + // Even if tryParse() works and file == scheme, toFilePath() can throw on + // Windows if there are invalid characters. + return new ErrorOr<String>.error(new ResponseError( + lsp.ServerErrorCodes.InvalidFilePath, + 'File URI did not contain a valid file path', + doc.uri)); + } +} + +lsp.Location searchResultToLocation( + server.SearchResult result, server.LineInfo lineInfo) { + final location = result.location; + + if (lineInfo == null) { + return null; + } + + return new Location( + Uri.file(result.location.file).toString(), + toRange(lineInfo, location.offset, location.length), + ); +} + +lsp.CompletionItemKind suggestionKindToCompletionItemKind( + HashSet<lsp.CompletionItemKind> clientSupportedCompletionKinds, + server.CompletionSuggestionKind kind, + String label, +) { + bool isSupported(lsp.CompletionItemKind kind) => + clientSupportedCompletionKinds.contains(kind); + + List<lsp.CompletionItemKind> getKindPreferences() { + switch (kind) { + case server.CompletionSuggestionKind.ARGUMENT_LIST: + return const [lsp.CompletionItemKind.Variable]; + case server.CompletionSuggestionKind.IMPORT: + // For package/relative URIs, we can send File/Folder kinds for better icons. + if (!label.startsWith('dart:')) { + return label.endsWith('.dart') + ? const [ + lsp.CompletionItemKind.File, + lsp.CompletionItemKind.Module, + ] + : const [ + lsp.CompletionItemKind.Folder, + lsp.CompletionItemKind.Module, + ]; + } + return const [lsp.CompletionItemKind.Module]; + case server.CompletionSuggestionKind.IDENTIFIER: + return const [lsp.CompletionItemKind.Variable]; + case server.CompletionSuggestionKind.INVOCATION: + return const [lsp.CompletionItemKind.Method]; + case server.CompletionSuggestionKind.KEYWORD: + return const [lsp.CompletionItemKind.Keyword]; + case server.CompletionSuggestionKind.NAMED_ARGUMENT: + return const [lsp.CompletionItemKind.Variable]; + case server.CompletionSuggestionKind.OPTIONAL_ARGUMENT: + return const [lsp.CompletionItemKind.Variable]; + case server.CompletionSuggestionKind.PARAMETER: + return const [lsp.CompletionItemKind.Value]; + default: + return null; + } + } + + return getKindPreferences().firstWhere(isSupported, orElse: () => null); +} + +lsp.CompletionItem toCompletionItem( + lsp.TextDocumentClientCapabilitiesCompletion completionCapabilities, + HashSet<lsp.CompletionItemKind> supportedCompletionItemKinds, + server.LineInfo lineInfo, + server.CompletionSuggestion suggestion, + int replacementOffset, + int replacementLength, +) { + final label = suggestion.displayText != null + ? suggestion.displayText + : suggestion.completion; + + final useSnippets = + completionCapabilities?.completionItem?.snippetSupport == true; + final useDeprecated = + completionCapabilities?.completionItem?.deprecatedSupport == true; + final formats = completionCapabilities?.completionItem?.documentationFormat; + + final completionKind = suggestion.element != null + ? elementKindToCompletionItemKind( + supportedCompletionItemKinds, suggestion.element.kind) + : suggestionKindToCompletionItemKind( + supportedCompletionItemKinds, suggestion.kind, label); + + return new lsp.CompletionItem( + label, + completionKind, + getCompletionDetail(suggestion, completionKind, useDeprecated), + asStringOrMarkupContent(formats, cleanDartdoc(suggestion.docComplete)), + useDeprecated ? suggestion.isDeprecated : null, + false, // preselect + // Relevance is a number, highest being best. LSP does text sort so subtract + // from a large number so that a text sort will result in the correct order. + // 555 -> 999455 + // 10 -> 999990 + // 1 -> 999999 + (1000000 - suggestion.relevance).toString(), + null, // filterText uses label if not set + null, // insertText is deprecated, but also uses label if not set + useSnippets ? lsp.InsertTextFormat.Snippet : lsp.InsertTextFormat.PlainText, + new lsp.TextEdit( + // TODO(dantup): If `clientSupportsSnippets == true` then we should map + // `selection` in to a snippet (see how Dart Code does this). + toRange(lineInfo, replacementOffset, replacementLength), + suggestion.completion, + ), + [], // additionalTextEdits, used for adding imports, etc. + [], // commitCharacters + null, // command + null, // data, useful for if using lazy resolve, this comes back to us + ); +} + +lsp.Diagnostic toDiagnostic( + server.LineInfo lineInfo, server.AnalysisError error, + [server.ErrorSeverity errorSeverity]) { + server.ErrorCode errorCode = error.errorCode; + + // Default to the error's severity if none is specified. + errorSeverity ??= errorCode.errorSeverity; + + return new lsp.Diagnostic( + toRange(lineInfo, error.offset, error.length), + toDiagnosticSeverity(errorSeverity), + errorCode.name.toLowerCase(), + languageSourceName, + error.message, + null, + ); +} + +lsp.DiagnosticSeverity toDiagnosticSeverity(server.ErrorSeverity severity) { + switch (severity) { + case server.ErrorSeverity.ERROR: + return lsp.DiagnosticSeverity.Error; + case server.ErrorSeverity.WARNING: + return lsp.DiagnosticSeverity.Warning; + case server.ErrorSeverity.INFO: + return lsp.DiagnosticSeverity.Information; + // Note: LSP also supports "Hint", but they won't render in things like the + // VS Code errors list as they're apparently intended to communicate + // non-visible diagnostics back (for example, if you wanted to grey out + // unreachable code without producing an item in the error list). + default: + throw 'Unknown AnalysisErrorSeverity: $severity'; + } +} + +ErrorOr<int> toOffset(server.LineInfo lineInfo, lsp.Position pos) { + if (pos.line > lineInfo.lineCount) { + return new ErrorOr<int>.error(new lsp.ResponseError( + lsp.ServerErrorCodes.InvalidFileLineCol, + 'Invalid line number', + pos.line)); + } + // TODO(dantup): Is there any way to validate the character? We could ensure + // it's less than the offset of the next line, but that would only work for + // all lines except the last one. + return new ErrorOr<int>.success( + lineInfo.getOffsetOfLine(pos.line) + pos.character); +} + +lsp.Position toPosition(server.CharacterLocation location) { + // LSP is zero-based, but analysis server is 1-based. + return new lsp.Position(location.lineNumber - 1, location.columnNumber - 1); +} + +lsp.Range toRange(server.LineInfo lineInfo, int offset, int length) { + server.CharacterLocation start = lineInfo.getLocation(offset); + server.CharacterLocation end = lineInfo.getLocation(offset + length); + + return new lsp.Range( + toPosition(start), + toPosition(end), + ); +} + +lsp.SignatureHelp toSignatureHelp(List<lsp.MarkupKind> preferredFormats, + server.AnalysisGetSignatureResult signature) { + // For now, we only support returning one (though we may wish to use named + // args. etc. to provide one for each possible "next" option when the cursor + // is at the end ready to provide another argument). + + /// Gets the label for an individual parameter in the form + /// String s = 'foo' + String getParamLabel(server.ParameterInfo p) { + final def = p.defaultValue != null ? ' = ${p.defaultValue}' : ''; + return '${p.type} ${p.name}$def'; + } + + /// Gets the full signature label in the form + /// foo(String s, int i, bool a = true) + String getSignatureLabel(server.AnalysisGetSignatureResult resp) { + final req = signature.parameters + .where((p) => p.kind == server.ParameterKind.REQUIRED) + .toList(); + final opt = signature.parameters + .where((p) => p.kind == server.ParameterKind.OPTIONAL) + .toList(); + final named = signature.parameters + .where((p) => p.kind == server.ParameterKind.NAMED) + .toList(); + final params = []; + if (req.isNotEmpty) { + params.add(req.map(getParamLabel).join(", ")); + } + if (opt.isNotEmpty) { + params.add("[" + opt.map(getParamLabel).join(", ") + "]"); + } + if (named.isNotEmpty) { + params.add("{" + named.map(getParamLabel).join(", ") + "}"); + } + return '${resp.name}(${params.join(", ")})'; + } + + lsp.ParameterInformation toParameterInfo(server.ParameterInfo param) { + return new lsp.ParameterInformation(getParamLabel(param), null); + } + + final cleanDoc = cleanDartdoc(signature.dartdoc); + + return new lsp.SignatureHelp( + [ + new lsp.SignatureInformation( + getSignatureLabel(signature), + asStringOrMarkupContent(preferredFormats, cleanDoc), + signature.parameters.map(toParameterInfo).toList(), + ), + ], + 0, // activeSignature + null, // activeParameter + ); +} + +lsp.MarkupContent _asMarkup( + List<lsp.MarkupKind> preferredFormats, String content) { + // It's not valid to call this function with a null format, as null formats + // do not support MarkupContent. [asStringOrMarkupContent] is probably the + // better choice. + assert(preferredFormats != null); + + if (content == null) { + return null; + } + + if (preferredFormats.isEmpty) { + preferredFormats.add(lsp.MarkupKind.Markdown); + } + + final supportsMarkdown = preferredFormats.contains(lsp.MarkupKind.Markdown); + final supportsPlain = preferredFormats.contains(lsp.MarkupKind.PlainText); + // Since our PlainText version is actually just Markdown, only advertise it + // as PlainText if the client explicitly supports PlainText and not Markdown. + final format = supportsPlain && !supportsMarkdown + ? lsp.MarkupKind.PlainText + : lsp.MarkupKind.Markdown; + + return new lsp.MarkupContent(format, content); +}
diff --git a/pkg/analysis_server/lib/src/lsp/source_edits.dart b/pkg/analysis_server/lib/src/lsp/source_edits.dart new file mode 100644 index 0000000..200ac92 --- /dev/null +++ b/pkg/analysis_server/lib/src/lsp/source_edits.dart
@@ -0,0 +1,61 @@ +import 'package:analysis_server/lsp_protocol/protocol_generated.dart'; +import 'package:analysis_server/lsp_protocol/protocol_special.dart'; +import 'package:analysis_server/src/lsp/mapping.dart'; +import 'package:analyzer/source/line_info.dart'; +import 'package:dart_style/dart_style.dart'; + +final DartFormatter formatter = new DartFormatter(); + +ErrorOr<String> applyEdits( + String oldContent, List<TextDocumentContentChangeEvent> changes) { + String newContent = oldContent; + for (var change in changes) { + if (change.range == null && change.rangeLength == null) { + newContent = change.text; + } else { + final lines = LineInfo.fromContent(newContent); + final offsetStart = toOffset(lines, change.range.start); + final offsetEnd = toOffset(lines, change.range.end); + if (offsetStart.isError) { + return new ErrorOr<String>.error(offsetStart.error); + } + if (offsetEnd.isError) { + return new ErrorOr<String>.error(offsetEnd.error); + } + newContent = newContent.replaceRange( + offsetStart.result, offsetEnd.result, change.text); + } + } + return new ErrorOr<String>.success(newContent); +} + +List<TextEdit> generateEditsForFormatting(String unformattedSource) { + final lineInfo = new LineInfo.fromContent(unformattedSource); + final code = + new SourceCode(unformattedSource, uri: null, isCompilationUnit: true); + SourceCode formattedResult; + try { + formattedResult = formatter.formatSource(code); + } on FormatterException { + // If the document fails to parse, just return no edits to avoid the the + // use seeing edits on every save with invalid code (if LSP gains the + // ability to pass a context to know if the format was manually invoked + // we may wish to change this to return an error for that case). + return null; + } + final formattedSource = formattedResult.text; + + if (formattedSource == unformattedSource) { + return null; + } + + // We don't currently support returning "minimal" edits, we just replace + // entire document. + final end = lineInfo.getLocation(unformattedSource.length); + return [ + new TextEdit( + new Range(new Position(0, 0), toPosition(end)), + formattedSource, + ) + ]; +}
diff --git a/pkg/analysis_server/lib/src/operation/operation_analysis.dart b/pkg/analysis_server/lib/src/operation/operation_analysis.dart index 32b9153..9943cbd 100644 --- a/pkg/analysis_server/lib/src/operation/operation_analysis.dart +++ b/pkg/analysis_server/lib/src/operation/operation_analysis.dart
@@ -27,7 +27,7 @@ return; } for (String file in files) { - CompilationUnit unit = server.getCachedAnalysisResult(file)?.unit; + CompilationUnit unit = server.getCachedResolvedUnit(file)?.unit; CompilationUnitElement unitElement = unit?.declaredElement; if (unitElement != null) { try {
diff --git a/pkg/analysis_server/lib/src/plugin/plugin_manager.dart b/pkg/analysis_server/lib/src/plugin/plugin_manager.dart index 6f95fd4a..63be71f 100644 --- a/pkg/analysis_server/lib/src/plugin/plugin_manager.dart +++ b/pkg/analysis_server/lib/src/plugin/plugin_manager.dart
@@ -12,11 +12,11 @@ import 'package:analyzer/file_system/file_system.dart'; import 'package:analyzer/instrumentation/instrumentation.dart'; import 'package:analyzer/src/context/context_root.dart' as analyzer; -import 'package:analyzer/src/generated/bazel.dart'; -import 'package:analyzer/src/generated/gn.dart'; import 'package:analyzer/src/generated/source.dart'; -import 'package:analyzer/src/generated/workspace.dart'; import 'package:analyzer/src/util/glob.dart'; +import 'package:analyzer/src/workspace/bazel.dart'; +import 'package:analyzer/src/workspace/gn.dart'; +import 'package:analyzer/src/workspace/workspace.dart'; import 'package:analyzer_plugin/channel/channel.dart'; import 'package:analyzer_plugin/protocol/protocol.dart'; import 'package:analyzer_plugin/protocol/protocol_common.dart';
diff --git a/pkg/analysis_server/lib/src/plugin/result_collector.dart b/pkg/analysis_server/lib/src/plugin/result_collector.dart index c2e3274..04c3f09 100644 --- a/pkg/analysis_server/lib/src/plugin/result_collector.dart +++ b/pkg/analysis_server/lib/src/plugin/result_collector.dart
@@ -30,7 +30,7 @@ * the plugin that provided the partial results. The value is the partial * results contributed by the plugin for the file. */ - Map<String, Map<String, E>> resultMap = <String, Map<String, E>>{}; + final Map<String, Map<String, E>> resultMap = <String, Map<String, E>>{}; /** * Initialize a newly created result manager.
diff --git a/pkg/analysis_server/lib/src/protocol_server.dart b/pkg/analysis_server/lib/src/protocol_server.dart index 9ff7232..fc2d22a 100644 --- a/pkg/analysis_server/lib/src/protocol_server.dart +++ b/pkg/analysis_server/lib/src/protocol_server.dart
@@ -1,4 +1,4 @@ -// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file +// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. @@ -35,7 +35,21 @@ engine.AnalysisOptions analysisOptions, engine.LineInfo lineInfo, List<engine.AnalysisError> errors) { - List<AnalysisError> serverErrors = <AnalysisError>[]; + return mapEngineErrors( + analysisOptions, lineInfo, errors, newAnalysisError_fromEngine); +} + +/** + * Translates engine errors through the ErrorProcessor. + */ +List<T> mapEngineErrors<T>( + engine.AnalysisOptions analysisOptions, + engine.LineInfo lineInfo, + List<engine.AnalysisError> errors, + T Function(engine.LineInfo lineInfo, engine.AnalysisError error, + [engine.ErrorSeverity errorSeverity]) + constructor) { + List<T> serverErrors = <T>[]; for (engine.AnalysisError error in errors) { ErrorProcessor processor = ErrorProcessor.getProcessor(analysisOptions, error); @@ -44,11 +58,10 @@ // Errors with null severity are filtered out. if (severity != null) { // Specified severities override. - serverErrors - .add(newAnalysisError_fromEngine(lineInfo, error, severity)); + serverErrors.add(constructor(lineInfo, error, severity)); } } else { - serverErrors.add(newAnalysisError_fromEngine(lineInfo, error)); + serverErrors.add(constructor(lineInfo, error)); } } return serverErrors; @@ -163,7 +176,7 @@ */ Location newLocation_fromNode(engine.AstNode node) { engine.CompilationUnit unit = - node.getAncestor((node) => node is engine.CompilationUnit); + node.thisOrAncestorOfType<engine.CompilationUnit>(); engine.CompilationUnitElement unitElement = unit.declaredElement; engine.SourceRange range = new engine.SourceRange(node.offset, node.length); return _locationForArgs(unitElement, range);
diff --git a/pkg/analysis_server/lib/src/provisional/completion/completion_core.dart b/pkg/analysis_server/lib/src/provisional/completion/completion_core.dart index f100d1e..2d6adce 100644 --- a/pkg/analysis_server/lib/src/provisional/completion/completion_core.dart +++ b/pkg/analysis_server/lib/src/provisional/completion/completion_core.dart
@@ -4,8 +4,8 @@ import 'dart:async'; +import 'package:analyzer/dart/analysis/results.dart'; import 'package:analyzer/file_system/file_system.dart'; -import 'package:analyzer/src/dart/analysis/driver.dart'; import 'package:analyzer/src/generated/source.dart'; import 'package:analyzer_plugin/protocol/protocol_common.dart'; @@ -53,7 +53,7 @@ * The analysis result for the file in which the completion is being * requested. */ - AnalysisResult get result; + ResolvedUnitResult get result; /** * Return the source in which the completion is being requested.
diff --git a/pkg/analysis_server/lib/src/server/driver.dart b/pkg/analysis_server/lib/src/server/driver.dart index de0500c..3f6e67d 100644 --- a/pkg/analysis_server/lib/src/server/driver.dart +++ b/pkg/analysis_server/lib/src/server/driver.dart
@@ -9,10 +9,13 @@ import 'package:analysis_server/protocol/protocol_constants.dart' show PROTOCOL_VERSION; import 'package:analysis_server/src/analysis_server.dart'; +import 'package:analysis_server/src/lsp/lsp_analysis_server.dart'; +import 'package:analysis_server/src/lsp/lsp_socket_server.dart'; import 'package:analysis_server/src/server/detachable_filesystem_manager.dart'; import 'package:analysis_server/src/server/dev_server.dart'; import 'package:analysis_server/src/server/diagnostic_server.dart'; import 'package:analysis_server/src/server/http_server.dart'; +import 'package:analysis_server/src/server/lsp_stdio_server.dart'; import 'package:analysis_server/src/server/stdio_server.dart'; import 'package:analysis_server/src/services/completion/dart/uri_contributor.dart' show UriContributor; @@ -263,6 +266,11 @@ static const String USE_FASTA_PARSER = "use-fasta-parser"; /** + * The name of the flag to use the Language Server Protocol (LSP). + */ + static const String USE_LSP = "lsp"; + + /** * A directory to analyze in order to train an analysis server snapshot. */ static const String TRAIN_USING = "train-using"; @@ -303,20 +311,14 @@ */ DetachableFileSystemManager detachableFileSystemManager; - SocketServer socketServer; - HttpAnalysisServer httpServer; Driver(); /** * Use the given command-line [arguments] to start this server. - * - * At least temporarily returns AnalysisServer so that consumers of the - * starter API can then use the server, this is done as a stopgap for the - * angular plugin until the official plugin API is finished. */ - AnalysisServer start(List<String> arguments) { + void start(List<String> arguments) { CommandLineParser parser = _createArgParser(); ArgResults results = parser.parse(arguments, <String, String>{}); @@ -330,6 +332,7 @@ analysisServerOptions.clientVersion = results[CLIENT_VERSION]; analysisServerOptions.cacheFolder = results[CACHE_FOLDER]; analysisServerOptions.useFastaParser = results[USE_FASTA_PARSER]; + analysisServerOptions.useLanguageServerProtocol = results[USE_LSP]; analysisServerOptions.enableUXExperiment1 = results[UX_EXPERIMENT_1]; analysisServerOptions.enableUXExperiment2 = results[UX_EXPERIMENT_2]; @@ -372,6 +375,54 @@ return null; } + final defaultSdkPath = _getSdkPath(results); + final dartSdkManager = new DartSdkManager(defaultSdkPath, true); + + // TODO(brianwilkerson) It would be nice to avoid creating an SDK that + // cannot be re-used, but the SDK is needed to create a package map provider + // in the case where we need to run `pub` in order to get the package map. + DartSdk defaultSdk = _createDefaultSdk(defaultSdkPath, true); + // + // Initialize the instrumentation service. + // + String logFilePath = results[INSTRUMENTATION_LOG_FILE]; + if (logFilePath != null) { + _rollLogFiles(logFilePath, 5); + FileInstrumentationServer fileBasedServer = + new FileInstrumentationServer(logFilePath); + instrumentationServer = instrumentationServer != null + ? new MulticastInstrumentationServer( + [instrumentationServer, fileBasedServer]) + : fileBasedServer; + } + InstrumentationService instrumentationService = + new InstrumentationService(instrumentationServer); + instrumentationService.logVersion( + results[TRAIN_USING] != null + ? 'training-0' + : _readUuid(instrumentationService), + analysisServerOptions.clientId, + analysisServerOptions.clientVersion, + PROTOCOL_VERSION, + defaultSdk.sdkVersion); + AnalysisEngine.instance.instrumentationService = instrumentationService; + + if (analysisServerOptions.useLanguageServerProtocol) { + startLspServer(results, analysisServerOptions, dartSdkManager, + instrumentationService); + } else { + startAnalysisServer(results, analysisServerOptions, parser, + dartSdkManager, instrumentationService, analytics); + } + } + + void startAnalysisServer( + ArgResults results, + AnalysisServerOptions analysisServerOptions, + CommandLineParser parser, + DartSdkManager dartSdkManager, + InstrumentationService instrumentationService, + telemetry.Analytics analytics) { String trainDirectory = results[TRAIN_USING]; if (trainDirectory != null) { if (!FileSystemEntity.isDirectorySync(trainDirectory)) { @@ -403,45 +454,6 @@ manager.processPlugins(AnalysisEngine.instance.requiredPlugins); linter.registerLintRules(); - String defaultSdkPath; - if (results[SDK_OPTION] != null) { - defaultSdkPath = results[SDK_OPTION]; - } else { - // No path to the SDK was provided. - // Use FolderBasedDartSdk.defaultSdkDirectory, which will make a guess. - defaultSdkPath = FolderBasedDartSdk.defaultSdkDirectory( - PhysicalResourceProvider.INSTANCE) - .path; - } - // TODO(brianwilkerson) It would be nice to avoid creating an SDK that - // cannot be re-used, but the SDK is needed to create a package map provider - // in the case where we need to run `pub` in order to get the package map. - DartSdk defaultSdk = _createDefaultSdk(defaultSdkPath, true); - // - // Initialize the instrumentation service. - // - String logFilePath = results[INSTRUMENTATION_LOG_FILE]; - if (logFilePath != null) { - _rollLogFiles(logFilePath, 5); - FileInstrumentationServer fileBasedServer = - new FileInstrumentationServer(logFilePath); - instrumentationServer = instrumentationServer != null - ? new MulticastInstrumentationServer( - [instrumentationServer, fileBasedServer]) - : fileBasedServer; - } - InstrumentationService instrumentationService = - new InstrumentationService(instrumentationServer); - instrumentationService.logVersion( - trainDirectory != null - ? 'training-0' - : _readUuid(instrumentationService), - analysisServerOptions.clientId, - analysisServerOptions.clientVersion, - PROTOCOL_VERSION, - defaultSdk.sdkVersion); - AnalysisEngine.instance.instrumentationService = instrumentationService; - _DiagnosticServerImpl diagnosticServer = new _DiagnosticServerImpl(); // Ping analytics with our initial call. @@ -450,9 +462,9 @@ // // Create the sockets and start listening for requests. // - socketServer = new SocketServer( + final socketServer = new SocketServer( analysisServerOptions, - new DartSdkManager(defaultSdkPath, true), + dartSdkManager, instrumentationService, diagnosticServer, fileResolverProvider, @@ -502,7 +514,7 @@ exit(exitCode); }(); } else { - _captureExceptions(instrumentationService, () { + _captureExceptions(socketServer, instrumentationService, () { StdioAnalysisServer stdioServer = new StdioAnalysisServer(socketServer); stdioServer.serveStdio().then((_) async { // TODO(brianwilkerson) Determine whether this await is necessary. @@ -520,8 +532,28 @@ ? null : httpServer.recordPrint); } + } - return socketServer.analysisServer; + void startLspServer( + ArgResults args, + AnalysisServerOptions analysisServerOptions, + DartSdkManager dartSdkManager, + InstrumentationService instrumentationService, + ) { + final socketServer = new LspSocketServer( + analysisServerOptions, + dartSdkManager, + instrumentationService, + ); + + _captureLspExceptions(socketServer, instrumentationService, () { + LspStdioAnalysisServer stdioServer = + new LspStdioAnalysisServer(socketServer); + stdioServer.serveStdio().then((_) async { + socketServer.analysisServer.shutdown(); + exit(0); + }); + }); } /** @@ -530,13 +562,13 @@ * instrumentation [service]. If a [print] function is provided, then also * capture any data printed by the callback and redirect it to the function. */ - dynamic _captureExceptions(InstrumentationService service, dynamic callback(), + dynamic _captureExceptions(SocketServer socketServer, + InstrumentationService service, dynamic callback(), {void print(String line)}) { void errorFunction(Zone self, ZoneDelegate parent, Zone zone, dynamic exception, StackTrace stackTrace) { service.logPriorityException(exception, stackTrace); - AnalysisServer analysisServer = socketServer.analysisServer; - analysisServer.sendServerErrorNotification( + socketServer.analysisServer.sendServerErrorNotification( 'Captured exception', exception, stackTrace); throw exception; } @@ -554,6 +586,33 @@ } /** + * Execute the given [callback] within a zone that will capture any unhandled + * exceptions and both report them to the client and send them to the given + * instrumentation [service]. If a [print] function is provided, then also + * capture any data printed by the callback and redirect it to the function. + */ + dynamic _captureLspExceptions( + // TODO(dantup): This is a copy/paste of the above with some minor changes. + // We should either factor these out, or if we end up with an LspDriver, put + // this there. + LspSocketServer socketServer, + InstrumentationService service, + dynamic callback()) { + void errorFunction(Zone self, ZoneDelegate parent, Zone zone, + dynamic exception, StackTrace stackTrace) { + service.logPriorityException(exception, stackTrace); + LspAnalysisServer analysisServer = socketServer.analysisServer; + analysisServer.sendServerErrorNotification( + 'Captured exception', exception, stackTrace); + throw exception; + } + + ZoneSpecification zoneSpecification = + new ZoneSpecification(handleUncaughtError: errorFunction); + return runZoned(callback, zoneSpecification: zoneSpecification); + } + + /** * Create and return the parser used to parse the command-line arguments. */ CommandLineParser _createArgParser() { @@ -615,6 +674,8 @@ parser.addFlag(USE_FASTA_PARSER, defaultsTo: true, help: "Whether to enable parsing via the Fasta parser"); + parser.addFlag(USE_LSP, + defaultsTo: false, help: "Whether to use the Language Server Protocol"); parser.addOption(TRAIN_USING, help: "Pass in a directory to analyze for purposes of training an " "analysis server snapshot."); @@ -641,6 +702,18 @@ return sdk; } + String _getSdkPath(ArgResults args) { + if (args[SDK_OPTION] != null) { + return args[SDK_OPTION]; + } else { + // No path to the SDK was provided. + // Use FolderBasedDartSdk.defaultSdkDirectory, which will make a guess. + return FolderBasedDartSdk.defaultSdkDirectory( + PhysicalResourceProvider.INSTANCE, + ).path; + } + } + /** * Print information about how to use the server. */
diff --git a/pkg/analysis_server/lib/src/server/lsp_stdio_server.dart b/pkg/analysis_server/lib/src/server/lsp_stdio_server.dart new file mode 100644 index 0000000..016bd11 --- /dev/null +++ b/pkg/analysis_server/lib/src/server/lsp_stdio_server.dart
@@ -0,0 +1,40 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'dart:async'; +import 'dart:io'; + +import 'package:analysis_server/src/lsp/channel/lsp_byte_stream_channel.dart'; +import 'package:analysis_server/src/lsp/lsp_socket_server.dart'; + +/** + * Instances of the class [StdioServer] implement a simple server operating + * over standard input and output. The primary responsibility of this server + * is to split incoming messages on newlines and pass them along to the + * analysis server. + */ +class LspStdioAnalysisServer { + /** + * An object that can handle either a WebSocket connection or a connection + * to the client over stdio. + */ + LspSocketServer socketServer; + + /** + * Initialize a newly created stdio server. + */ + LspStdioAnalysisServer(this.socketServer); + + /** + * Begin serving requests over stdio. + * + * Return a future that will be completed when stdin closes. + */ + Future serveStdio() { + LspByteStreamServerChannel serverChannel = new LspByteStreamServerChannel( + stdin, stdout, socketServer.instrumentationService); + socketServer.createAnalysisServer(serverChannel); + return serverChannel.closed; + } +}
diff --git a/pkg/analysis_server/lib/src/services/completion/completion_core.dart b/pkg/analysis_server/lib/src/services/completion/completion_core.dart index 1403f86..02e617b 100644 --- a/pkg/analysis_server/lib/src/services/completion/completion_core.dart +++ b/pkg/analysis_server/lib/src/services/completion/completion_core.dart
@@ -4,8 +4,8 @@ import 'package:analysis_server/src/provisional/completion/completion_core.dart'; import 'package:analysis_server/src/services/completion/completion_performance.dart'; +import 'package:analyzer/dart/analysis/results.dart'; import 'package:analyzer/file_system/file_system.dart'; -import 'package:analyzer/src/dart/analysis/driver.dart'; import 'package:analyzer/src/generated/source.dart'; /** @@ -13,7 +13,7 @@ */ class CompletionRequestImpl implements CompletionRequest { @override - final AnalysisResult result; + final ResolvedUnitResult result; @override final int offset;
diff --git a/pkg/analysis_server/lib/src/services/completion/completion_performance.dart b/pkg/analysis_server/lib/src/services/completion/completion_performance.dart index 24b952f..37ee54e 100644 --- a/pkg/analysis_server/lib/src/services/completion/completion_performance.dart +++ b/pkg/analysis_server/lib/src/services/completion/completion_performance.dart
@@ -25,11 +25,6 @@ int get elapsedInMilliseconds => operations.length > 0 ? operations.last.elapsed.inMilliseconds : 0; - int get firstNotificationInMilliseconds => - _firstNotification != null ? _firstNotification.inMilliseconds : 0; - - String get startTimeAndMs => '${start.millisecondsSinceEpoch} - $start'; - String get suggestionCount { if (notificationCount < 1) return ''; if (notificationCount == 1) return '$suggestionCountFirst';
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/combinator_contributor.dart b/pkg/analysis_server/lib/src/services/completion/dart/combinator_contributor.dart index 18ba66b..fc4e494 100644 --- a/pkg/analysis_server/lib/src/services/completion/dart/combinator_contributor.dart +++ b/pkg/analysis_server/lib/src/services/completion/dart/combinator_contributor.dart
@@ -1,4 +1,4 @@ -// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file +// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. @@ -27,7 +27,7 @@ } // Build list of suggestions - var directive = node.getAncestor((parent) => parent is NamespaceDirective); + var directive = node.thisOrAncestorOfType<NamespaceDirective>(); if (directive is NamespaceDirective) { LibraryElement library = directive.uriElement; if (library != null) {
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/completion_manager.dart b/pkg/analysis_server/lib/src/services/completion/dart/completion_manager.dart index 306c6b3..fe34f79 100644 --- a/pkg/analysis_server/lib/src/services/completion/dart/completion_manager.dart +++ b/pkg/analysis_server/lib/src/services/completion/dart/completion_manager.dart
@@ -29,11 +29,12 @@ import 'package:analysis_server/src/services/completion/dart/type_member_contributor.dart'; import 'package:analysis_server/src/services/completion/dart/uri_contributor.dart'; import 'package:analysis_server/src/services/completion/dart/variable_name_contributor.dart'; +import 'package:analyzer/dart/analysis/results.dart'; import 'package:analyzer/dart/ast/ast.dart'; import 'package:analyzer/dart/element/element.dart'; import 'package:analyzer/dart/element/type.dart'; import 'package:analyzer/file_system/file_system.dart'; -import 'package:analyzer/src/dart/analysis/driver.dart'; +import 'package:analyzer/src/dart/analysis/driver_based_analysis_context.dart'; import 'package:analyzer/src/generated/engine.dart' hide AnalysisResult; import 'package:analyzer/src/generated/source.dart'; import 'package:analyzer/src/task/api/model.dart'; @@ -178,7 +179,7 @@ */ class DartCompletionRequestImpl implements DartCompletionRequest { @override - final AnalysisResult result; + final ResolvedUnitResult result; @override final ResourceProvider resourceProvider; @@ -249,7 +250,10 @@ String get sourceContents => result.content; @override - SourceFactory get sourceFactory => result.sourceFactory; + SourceFactory get sourceFactory { + DriverBasedAnalysisContext context = result.session.analysisContext; + return context.driver.sourceFactory; + } /** * Throw [AbortCompletion] if the completion request has been aborted.
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/field_formal_contributor.dart b/pkg/analysis_server/lib/src/services/completion/dart/field_formal_contributor.dart index 2a45ee0..64ed46a 100644 --- a/pkg/analysis_server/lib/src/services/completion/dart/field_formal_contributor.dart +++ b/pkg/analysis_server/lib/src/services/completion/dart/field_formal_contributor.dart
@@ -1,4 +1,4 @@ -// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file +// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. @@ -28,7 +28,7 @@ // If this is a constructor declaration // then compute fields already referenced ConstructorDeclaration constructorDecl = - node.getAncestor((p) => p is ConstructorDeclaration); + node.thisOrAncestorOfType<ConstructorDeclaration>(); if (constructorDecl == null) { return const <CompletionSuggestion>[]; } @@ -53,7 +53,7 @@ // Add suggestions for fields that are not already referenced ClassDeclaration classDecl = - constructorDecl.getAncestor((p) => p is ClassDeclaration); + constructorDecl.thisOrAncestorOfType<ClassDeclaration>(); List<CompletionSuggestion> suggestions = <CompletionSuggestion>[]; for (ClassMember member in classDecl.members) { if (member is FieldDeclaration && !member.isStatic) {
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/keyword_contributor.dart b/pkg/analysis_server/lib/src/services/completion/dart/keyword_contributor.dart index 1db3c05..64bac8e 100644 --- a/pkg/analysis_server/lib/src/services/completion/dart/keyword_contributor.dart +++ b/pkg/analysis_server/lib/src/services/completion/dart/keyword_contributor.dart
@@ -1,4 +1,4 @@ -// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file +// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. @@ -329,7 +329,7 @@ @override visitFormalParameterList(FormalParameterList node) { AstNode constructorDeclaration = - node.getAncestor((p) => p is ConstructorDeclaration); + node.thisOrAncestorOfType<ConstructorDeclaration>(); if (constructorDeclaration != null) { _addSuggestions([Keyword.THIS]); } @@ -746,21 +746,21 @@ } bool _inAsyncMethodOrFunction(AstNode node) { - FunctionBody body = node.getAncestor((n) => n is FunctionBody); + FunctionBody body = node.thisOrAncestorOfType<FunctionBody>(); return body != null && body.isAsynchronous && body.star == null; } bool _inAsyncStarOrSyncStarMethodOrFunction(AstNode node) { - FunctionBody body = node.getAncestor((n) => n is FunctionBody); + FunctionBody body = node.thisOrAncestorOfType<FunctionBody>(); return body != null && body.keyword != null && body.star != null; } bool _inCatchClause(Block node) => - node.getAncestor((p) => p is CatchClause) != null; + node.thisOrAncestorOfType<CatchClause>() != null; bool _inClassMemberBody(AstNode node) { while (true) { - AstNode body = node.getAncestor((n) => n is FunctionBody); + AstNode body = node.thisOrAncestorOfType<FunctionBody>(); if (body == null) { return false; } @@ -773,23 +773,24 @@ } bool _inDoLoop(AstNode node) => - node.getAncestor((p) => p is DoStatement) != null; + node.thisOrAncestorOfType<DoStatement>() != null; bool _inForLoop(AstNode node) => - node.getAncestor((p) => p is ForStatement || p is ForEachStatement) != + node.thisOrAncestorMatching( + (p) => p is ForStatement || p is ForEachStatement) != null; bool _inLoop(AstNode node) => _inDoLoop(node) || _inForLoop(node) || _inWhileLoop(node); bool _inSwitch(AstNode node) => - node.getAncestor((p) => p is SwitchStatement) != null; + node.thisOrAncestorOfType<SwitchStatement>() != null; bool _inWhileLoop(AstNode node) => - node.getAncestor((p) => p is WhileStatement) != null; + node.thisOrAncestorOfType<WhileStatement>() != null; bool _isEntityAfterIfWithoutElse(AstNode node) { - Block block = node?.getAncestor((n) => n is Block); + Block block = node?.thisOrAncestorOfType<Block>(); if (block == null) { return false; }
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/label_contributor.dart b/pkg/analysis_server/lib/src/services/completion/dart/label_contributor.dart index 4dead0e..d580fcd 100644 --- a/pkg/analysis_server/lib/src/services/completion/dart/label_contributor.dart +++ b/pkg/analysis_server/lib/src/services/completion/dart/label_contributor.dart
@@ -91,6 +91,11 @@ } @override + void declaredGenericTypeAlias(GenericTypeAlias declaration) { + // ignored + } + + @override void declaredLabel(Label label, bool isCaseLabel) { if (isCaseLabel ? includeCaseLabels : includeStatementLabels) { CompletionSuggestion suggestion = _addSuggestion(label.label);
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/local_constructor_contributor.dart b/pkg/analysis_server/lib/src/services/completion/dart/local_constructor_contributor.dart index aeda775..4d8b351 100644 --- a/pkg/analysis_server/lib/src/services/completion/dart/local_constructor_contributor.dart +++ b/pkg/analysis_server/lib/src/services/completion/dart/local_constructor_contributor.dart
@@ -84,6 +84,9 @@ void declaredFunctionTypeAlias(FunctionTypeAlias declaration) {} @override + void declaredGenericTypeAlias(GenericTypeAlias declaration) {} + + @override void declaredLabel(Label label, bool isCaseLabel) {} @override
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/local_reference_contributor.dart b/pkg/analysis_server/lib/src/services/completion/dart/local_reference_contributor.dart index cee82af..66a5fc6 100644 --- a/pkg/analysis_server/lib/src/services/completion/dart/local_reference_contributor.dart +++ b/pkg/analysis_server/lib/src/services/completion/dart/local_reference_contributor.dart
@@ -226,6 +226,20 @@ } @override + void declaredGenericTypeAlias(GenericTypeAlias declaration) { + if (optype.includeTypeNameSuggestions) { + // TODO (danrubel) determine parameters and return type + _addLocalSuggestion_includeTypeNameSuggestions( + declaration.documentationComment, + declaration.name, + declaration.functionType.returnType, + protocol.ElementKind.FUNCTION_TYPE_ALIAS, + isAbstract: true, + isDeprecated: isDeprecated(declaration)); + } + } + + @override void declaredLabel(Label label, bool isCaseLabel) { // ignored }
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/override_contributor.dart b/pkg/analysis_server/lib/src/services/completion/dart/override_contributor.dart index 34d1ffb..8bee14b2 100644 --- a/pkg/analysis_server/lib/src/services/completion/dart/override_contributor.dart +++ b/pkg/analysis_server/lib/src/services/completion/dart/override_contributor.dart
@@ -9,10 +9,10 @@ import 'package:analysis_server/src/protocol_server.dart' as protocol hide CompletionSuggestion, CompletionSuggestionKind; import 'package:analysis_server/src/provisional/completion/dart/completion_dart.dart'; +import 'package:analyzer/dart/analysis/results.dart'; import 'package:analyzer/dart/ast/ast.dart'; import 'package:analyzer/dart/element/element.dart'; import 'package:analyzer/dart/element/type.dart'; -import 'package:analyzer/src/dart/analysis/driver.dart'; import 'package:analyzer/src/dart/element/inheritance_manager2.dart'; import 'package:analyzer/src/generated/source.dart'; import 'package:analyzer_plugin/src/utilities/completion/completion_target.dart'; @@ -34,13 +34,15 @@ return const <CompletionSuggestion>[]; } ClassDeclaration classDecl = - targetId.getAncestor((p) => p is ClassDeclaration); + targetId.thisOrAncestorOfType<ClassDeclaration>(); if (classDecl == null) { return const <CompletionSuggestion>[]; } + // TODO(brianwilkerson) Consider making the type system visible from the + // request.result. var inheritance = new InheritanceManager2( - request.result.libraryElement.context.typeSystem); + await request.result.libraryElement.session.typeSystem); // Generate a collection of inherited members ClassElement classElem = classDecl.declaredElement; @@ -68,14 +70,13 @@ * the template will replace [targetId]. */ Future<DartChangeBuilder> _buildReplacementText( - AnalysisResult result, + ResolvedUnitResult result, SimpleIdentifier targetId, FunctionType signature, StringBuffer displayTextBuffer) async { // TODO(brianwilkerson) Determine whether this await is necessary. await null; - DartChangeBuilder builder = - new DartChangeBuilder(result.driver.currentSession); + DartChangeBuilder builder = new DartChangeBuilder(result.session); await builder.addFileEdit(result.path, (DartFileEditBuilder builder) { builder.addReplacement(range.node(targetId), (DartEditBuilder builder) { ExecutableElement element = signature.element;
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/suggestion_builder.dart b/pkg/analysis_server/lib/src/services/completion/dart/suggestion_builder.dart index ef91fd7..e1ba6f9 100644 --- a/pkg/analysis_server/lib/src/services/completion/dart/suggestion_builder.dart +++ b/pkg/analysis_server/lib/src/services/completion/dart/suggestion_builder.dart
@@ -110,9 +110,9 @@ } /** - * Common mixin for sharing behavior + * Common mixin for sharing behavior. */ -abstract class ElementSuggestionBuilder { +mixin ElementSuggestionBuilder { /** * A collection of completion suggestions. */
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/type_member_contributor.dart b/pkg/analysis_server/lib/src/services/completion/dart/type_member_contributor.dart index d0b3d04..a4e03b3 100644 --- a/pkg/analysis_server/lib/src/services/completion/dart/type_member_contributor.dart +++ b/pkg/analysis_server/lib/src/services/completion/dart/type_member_contributor.dart
@@ -83,7 +83,7 @@ // Determine the name of the containing method because // the most likely completion is a super expression with same name MethodDeclaration containingMethod = - expression.getAncestor((p) => p is MethodDeclaration); + expression.thisOrAncestorOfType<MethodDeclaration>(); if (containingMethod != null) { SimpleIdentifier id = containingMethod.name; if (id != null) { @@ -174,6 +174,17 @@ } @override + void declaredGenericTypeAlias(GenericTypeAlias declaration) { + if (declaration.name.name == targetName) { + TypeAnnotation typeName = declaration.functionType.returnType; + if (typeName != null) { + typeFound = typeName.type; + } + finished(); + } + } + + @override void declaredLabel(Label label, bool isCaseLabel) { if (label.label.name == targetName) { // no type
diff --git a/pkg/analysis_server/lib/src/services/completion/postfix/postfix_completion.dart b/pkg/analysis_server/lib/src/services/completion/postfix/postfix_completion.dart index 1a690a8..1c15d65 100644 --- a/pkg/analysis_server/lib/src/services/completion/postfix/postfix_completion.dart +++ b/pkg/analysis_server/lib/src/services/completion/postfix/postfix_completion.dart
@@ -6,12 +6,11 @@ import 'package:analysis_server/src/protocol_server.dart' hide Element; import 'package:analysis_server/src/services/correction/util.dart'; +import 'package:analyzer/dart/analysis/results.dart'; import 'package:analyzer/dart/analysis/session.dart'; import 'package:analyzer/dart/ast/ast.dart'; import 'package:analyzer/dart/element/element.dart'; import 'package:analyzer/dart/element/type.dart'; -import 'package:analyzer/error/error.dart' as engine; -import 'package:analyzer/src/dart/analysis/driver.dart'; import 'package:analyzer/src/dart/ast/utilities.dart'; import 'package:analyzer/src/generated/java_core.dart'; import 'package:analyzer/src/generated/resolver.dart'; @@ -256,21 +255,11 @@ * The context for computing a postfix completion. */ class PostfixCompletionContext { - final String file; - final LineInfo lineInfo; + final ResolvedUnitResult resolveResult; final int selectionOffset; final String key; - final AnalysisDriver driver; - final CompilationUnit unit; - final CompilationUnitElement unitElement; - final List<engine.AnalysisError> errors; - PostfixCompletionContext(this.file, this.lineInfo, this.selectionOffset, - this.key, this.driver, this.unit, this.unitElement, this.errors) { - if (unitElement.context == null) { - throw new Error(); // not reached - } - } + PostfixCompletionContext(this.resolveResult, this.selectionOffset, this.key); } /** @@ -309,40 +298,25 @@ AstNode node; PostfixCompletion completion; SourceChange change = new SourceChange('postfix-completion'); - final Map<String, LinkedEditGroup> linkedPositionGroups = - <String, LinkedEditGroup>{}; + final Map<String, LinkedEditGroup> linkedPositionGroups = {}; Position exitPosition = null; - TypeProvider _typeProvider; PostfixCompletionProcessor(this.completionContext) - : utils = new CorrectionUtils(completionContext.unit); - - AnalysisDriver get driver => completionContext.driver; + : utils = new CorrectionUtils(completionContext.resolveResult); String get eol => utils.endOfLine; - String get file => completionContext.file; + String get file => completionContext.resolveResult.path; String get key => completionContext.key; - LineInfo get lineInfo => completionContext.lineInfo; + LineInfo get lineInfo => completionContext.resolveResult.lineInfo; int get selectionOffset => completionContext.selectionOffset; - /** - * Return the analysis session to be used to create the change builder. - */ - AnalysisSession get session => driver.currentSession; + AnalysisSession get session => completionContext.resolveResult.session; - Source get source => completionContext.unitElement.source; - - TypeProvider get typeProvider { - return _typeProvider ??= unitElement.context.typeProvider; - } - - CompilationUnit get unit => completionContext.unit; - - CompilationUnitElement get unitElement => completionContext.unitElement; + TypeProvider get typeProvider => completionContext.resolveResult.typeProvider; Future<PostfixCompletion> compute() async { // TODO(brianwilkerson) Determine whether this await is necessary. @@ -591,7 +565,8 @@ } AstNode _selectedNode({int at: null}) => - new NodeLocator(at == null ? selectionOffset : at).searchWithin(unit); + new NodeLocator(at == null ? selectionOffset : at) + .searchWithin(completionContext.resolveResult.unit); void _setCompletionFromBuilder( DartChangeBuilder builder, PostfixCompletionKind kind,
diff --git a/pkg/analysis_server/lib/src/services/completion/statement/statement_completion.dart b/pkg/analysis_server/lib/src/services/completion/statement/statement_completion.dart index 929f1fe..303ddd5 100644 --- a/pkg/analysis_server/lib/src/services/completion/statement/statement_completion.dart +++ b/pkg/analysis_server/lib/src/services/completion/statement/statement_completion.dart
@@ -1,4 +1,4 @@ -// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file +// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. @@ -8,6 +8,7 @@ import 'package:analysis_server/src/protocol_server.dart' hide Element; import 'package:analysis_server/src/services/correction/source_buffer.dart'; import 'package:analysis_server/src/services/correction/util.dart'; +import 'package:analyzer/dart/analysis/results.dart'; import 'package:analyzer/dart/ast/ast.dart'; import 'package:analyzer/dart/ast/token.dart'; import 'package:analyzer/dart/element/element.dart'; @@ -81,19 +82,10 @@ * The context for computing a statement completion. */ class StatementCompletionContext { - final String file; - final LineInfo lineInfo; + final ResolvedUnitResult resolveResult; final int selectionOffset; - final CompilationUnit unit; - final CompilationUnitElement unitElement; - final List<engine.AnalysisError> errors; - StatementCompletionContext(this.file, this.lineInfo, this.selectionOffset, - this.unit, this.unitElement, this.errors) { - if (unitElement.context == null) { - throw new Error(); // not reached; see getStatementCompletion() - } - } + StatementCompletionContext(this.resolveResult, this.selectionOffset); } /** @@ -143,21 +135,22 @@ Position exitPosition = null; StatementCompletionProcessor(this.statementContext) - : utils = new CorrectionUtils(statementContext.unit); + : utils = new CorrectionUtils(statementContext.resolveResult); String get eol => utils.endOfLine; - String get file => statementContext.file; + String get file => statementContext.resolveResult.path; - LineInfo get lineInfo => statementContext.lineInfo; + LineInfo get lineInfo => statementContext.resolveResult.lineInfo; int get selectionOffset => statementContext.selectionOffset; - Source get source => statementContext.unitElement.source; + Source get source => unitElement.source; - CompilationUnit get unit => statementContext.unit; + CompilationUnit get unit => statementContext.resolveResult.unit; - CompilationUnitElement get unitElement => statementContext.unitElement; + CompilationUnitElement get unitElement => + statementContext.resolveResult.unit.declaredElement; Future<StatementCompletion> compute() async { // TODO(brianwilkerson) Determine whether this await is necessary. @@ -166,8 +159,8 @@ if (node == null) { return NO_COMPLETION; } - node = node - .getAncestor((n) => n is Statement || _isNonStatementDeclaration(n)); + node = node.thisOrAncestorMatching( + (n) => n is Statement || _isNonStatementDeclaration(n)); if (node == null) { return _complete_simpleEnter() ? completion : NO_COMPLETION; } @@ -180,7 +173,7 @@ if (_isEmptyStatementOrEmptyBlock(node)) { node = node.parent; } - for (engine.AnalysisError error in statementContext.errors) { + for (engine.AnalysisError error in statementContext.resolveResult.errors) { if (error.offset >= node.offset && error.offset <= node.end) { if (error.errorCode is! HintCode) { errors.add(error); @@ -282,7 +275,7 @@ return null; } AstNode expr = _selectedNode(); - return (expr.getAncestor((n) => n is StringInterpolation) == null) + return (expr.thisOrAncestorOfType<StringInterpolation>() == null) ? expr : null; } @@ -319,7 +312,7 @@ expr = errorMatching(ParserErrorCode.EXPECTED_TOKEN, partialMatch: "']'") ?? errorMatching(ScannerErrorCode.EXPECTED_TOKEN, partialMatch: "']'"); if (expr != null) { - expr = expr.getAncestor((n) => n is ListLiteral); + expr = expr.thisOrAncestorOfType<ListLiteral>(); if (expr != null) { ListLiteral lit = expr; if (lit.rightBracket.isSynthetic) { @@ -861,13 +854,13 @@ if (parenError == null) { return false; } - AstNode argList = _selectedNode(at: selectionOffset) - .getAncestor((n) => n is ArgumentList); + AstNode argList = + _selectedNode(at: selectionOffset).thisOrAncestorOfType<ArgumentList>(); if (argList == null) { argList = _selectedNode(at: parenError.offset) - .getAncestor((n) => n is ArgumentList); + .thisOrAncestorOfType<ArgumentList>(); } - if (argList?.getAncestor((n) => n == node) == null) { + if (argList?.thisOrAncestorMatching((n) => n == node) == null) { return false; } int previousInsertions = _lengthOfInsertions(); @@ -1107,31 +1100,12 @@ orElse: () => null); } - LinkedEditGroup _getLinkedPosition(String groupId) { - LinkedEditGroup group = linkedPositionGroups[groupId]; - if (group == null) { - group = new LinkedEditGroup.empty(); - linkedPositionGroups[groupId] = group; - } - return group; - } - void _insertBuilder(SourceBuilder builder, [int length = 0]) { { SourceRange range = new SourceRange(builder.offset, length); String text = builder.toString(); _addReplaceEdit(range, text); } - // add linked positions - builder.linkedPositionGroups.forEach((String id, LinkedEditGroup group) { - LinkedEditGroup fixGroup = _getLinkedPosition(id); - group.positions.forEach((Position position) { - fixGroup.addPosition(position, group.length); - }); - group.suggestions.forEach((LinkedEditSuggestion suggestion) { - fixGroup.addSuggestion(suggestion); - }); - }); // add exit position { int exitOffset = builder.exitOffset;
diff --git a/pkg/analysis_server/lib/src/services/correction/assist.dart b/pkg/analysis_server/lib/src/services/correction/assist.dart index 772299c..0d09721 100644 --- a/pkg/analysis_server/lib/src/services/correction/assist.dart +++ b/pkg/analysis_server/lib/src/services/correction/assist.dart
@@ -2,9 +2,28 @@ // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. +import 'package:analysis_server/plugin/edit/assist/assist_dart.dart'; +import 'package:analyzer/dart/analysis/results.dart'; import 'package:analyzer_plugin/utilities/assist/assist.dart'; /** + * The implementation of [DartAssistContext]. + */ +class DartAssistContextImpl implements DartAssistContext { + @override + final ResolvedUnitResult resolveResult; + + @override + final int selectionOffset; + + @override + final int selectionLength; + + DartAssistContextImpl( + this.resolveResult, this.selectionOffset, this.selectionLength); +} + +/** * An enumeration of possible assist kinds. */ class DartAssistKind { @@ -28,10 +47,10 @@ 'dart.assist.convert.bodyToBlock', 30, "Convert to block body"); static const CONVERT_INTO_EXPRESSION_BODY = const AssistKind( 'dart.assist.convert.bodyToExpression', 30, "Convert to expression body"); - static const CONVERT_INTO_FOR_INDEX = const AssistKind( - 'dart.assist.convert.forEachToForIndex', 30, "Convert to for-index loop"); static const CONVERT_INTO_FINAL_FIELD = const AssistKind( 'dart.assist.convert.getterToFinalField', 30, "Convert to final field"); + static const CONVERT_INTO_FOR_INDEX = const AssistKind( + 'dart.assist.convert.forEachToForIndex', 30, "Convert to for-index loop"); static const CONVERT_INTO_GENERIC_FUNCTION_SYNTAX = const AssistKind( 'dart.assist.convert.toGenericFunctionSyntax', 30, @@ -96,6 +115,8 @@ const AssistKind('dart.assist.flutter.wrap.padding', 30, "Add padding"); static const FLUTTER_WRAP_ROW = const AssistKind('dart.assist.flutter.wrap.row', 30, "Wrap with Row"); + static const FLUTTER_WRAP_STREAM_BUILDER = const AssistKind( + 'dart.assist.flutter.wrap.streamBuilder', 30, "Wrap with StreamBuilder"); static const IMPORT_ADD_SHOW = const AssistKind( 'dart.assist.addShowCombinator', 30, "Add explicit 'show' combinator"); static const INTRODUCE_LOCAL_CAST_TYPE = const AssistKind(
diff --git a/pkg/analysis_server/lib/src/services/correction/assist_internal.dart b/pkg/analysis_server/lib/src/services/correction/assist_internal.dart index b9a6be5..b9616861 100644 --- a/pkg/analysis_server/lib/src/services/correction/assist_internal.dart +++ b/pkg/analysis_server/lib/src/services/correction/assist_internal.dart
@@ -1,4 +1,4 @@ -// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file +// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. @@ -16,12 +16,10 @@ import 'package:analysis_server/src/utilities/flutter.dart' as flutter; import 'package:analyzer/dart/analysis/session.dart'; import 'package:analyzer/dart/ast/ast.dart'; -import 'package:analyzer/dart/ast/standard_resolution_map.dart'; import 'package:analyzer/dart/ast/token.dart'; import 'package:analyzer/dart/ast/visitor.dart'; import 'package:analyzer/dart/element/element.dart'; import 'package:analyzer/dart/element/type.dart'; -import 'package:analyzer/src/dart/analysis/driver.dart'; import 'package:analyzer/src/dart/analysis/session_helper.dart'; import 'package:analyzer/src/dart/ast/token.dart'; import 'package:analyzer/src/dart/ast/utilities.dart'; @@ -42,73 +40,36 @@ * The computer for Dart assists. */ class AssistProcessor { - /** - * The analysis driver being used to perform analysis. - */ - AnalysisDriver driver; + final DartAssistContext context; + final int selectionOffset; + final int selectionLength; + final int selectionEnd; - /** - * The analysis session to be used to create the change builder. - */ - AnalysisSession session; - - /** - * The helper wrapper around the [session]. - */ - AnalysisSessionHelper sessionHelper; - - Source source; - String file; - - CompilationUnit unit; - CompilationUnitElement unitElement; - - LibraryElement unitLibraryElement; - - int selectionOffset; - int selectionLength; - int selectionEnd; + final AnalysisSession session; + final AnalysisSessionHelper sessionHelper; + final TypeProvider typeProvider; + final String file; + final CorrectionUtils utils; final List<Assist> assists = <Assist>[]; - CorrectionUtils utils; - AstNode node; - TypeProvider _typeProvider; - - AssistProcessor(DartAssistContext dartContext) { - driver = dartContext.analysisDriver; - session = driver.currentSession; - sessionHelper = new AnalysisSessionHelper(session); - // source - source = dartContext.source; - file = dartContext.source.fullName; - // unit - unit = dartContext.unit; - unitElement = dartContext.unit.declaredElement; - // library - unitLibraryElement = resolutionMap - .elementDeclaredByCompilationUnit(dartContext.unit) - .library; - // selection - selectionOffset = dartContext.selectionOffset; - selectionLength = dartContext.selectionLength; - selectionEnd = selectionOffset + selectionLength; - } + AssistProcessor(this.context) + : selectionOffset = context.selectionOffset, + selectionLength = context.selectionLength, + selectionEnd = context.selectionOffset + context.selectionLength, + session = context.resolveResult.session, + sessionHelper = AnalysisSessionHelper(context.resolveResult.session), + typeProvider = context.resolveResult.typeProvider, + file = context.resolveResult.path, + utils = new CorrectionUtils(context.resolveResult); /** * Returns the EOL to use for this [CompilationUnit]. */ String get eol => utils.endOfLine; - TypeProvider get typeProvider { - if (_typeProvider == null) { - _typeProvider = unitElement.context.typeProvider; - } - return _typeProvider; - } - Future<List<Assist>> compute() async { // TODO(brianwilkerson) Determine whether this await is necessary. await null; @@ -149,6 +110,7 @@ await _addProposal_flutterRemoveWidget_multipleChildren(); await _addProposal_flutterSwapWithChild(); await _addProposal_flutterSwapWithParent(); + await _addProposal_flutterWrapStreamBuilder(); await _addProposal_flutterWrapWidget(); await _addProposal_flutterWrapWidgets(); await _addProposal_importAddShow(); @@ -188,28 +150,27 @@ // isn't just "return node.getAncestor((node) => node is FunctionBody);" { FunctionExpression function = - node.getAncestor((node) => node is FunctionExpression); + node.thisOrAncestorOfType<FunctionExpression>(); if (function != null) { return function.body; } } { FunctionDeclaration function = - node.getAncestor((node) => node is FunctionDeclaration); + node.thisOrAncestorOfType<FunctionDeclaration>(); if (function != null) { return function.functionExpression.body; } } { ConstructorDeclaration constructor = - node.getAncestor((node) => node is ConstructorDeclaration); + node.thisOrAncestorOfType<ConstructorDeclaration>(); if (constructor != null) { return constructor.body; } } { - MethodDeclaration method = - node.getAncestor((node) => node is MethodDeclaration); + MethodDeclaration method = node.thisOrAncestorOfType<MethodDeclaration>(); if (method != null) { return method.body; } @@ -233,9 +194,9 @@ // TODO(brianwilkerson) Determine whether this await is necessary. await null; DeclaredIdentifier declaredIdentifier = - node.getAncestor((n) => n is DeclaredIdentifier); + node.thisOrAncestorOfType<DeclaredIdentifier>(); if (declaredIdentifier == null) { - ForEachStatement forEach = node.getAncestor((n) => n is ForEachStatement); + ForEachStatement forEach = node.thisOrAncestorOfType<ForEachStatement>(); int offset = node.offset; if (forEach != null && forEach.iterable != null && @@ -328,7 +289,7 @@ AstNode node = this.node; // prepare VariableDeclarationList VariableDeclarationList declarationList = - node.getAncestor((node) => node is VariableDeclarationList); + node.thisOrAncestorOfType<VariableDeclarationList>(); if (declarationList == null) { _coverageMarker(); return; @@ -385,33 +346,6 @@ } } - Future<void> _addProposal_convertToIntLiteral() async { - if (node is! DoubleLiteral) { - _coverageMarker(); - return; - } - DoubleLiteral literal = node; - int intValue; - try { - intValue = literal.value?.truncate(); - } catch (e) { - // Double cannot be converted to int - } - if (intValue == null || intValue != literal.value) { - _coverageMarker(); - return; - } - - DartChangeBuilder changeBuilder = new DartChangeBuilder(session); - await changeBuilder.addFileEdit(file, (DartFileEditBuilder builder) { - builder.addReplacement(new SourceRange(literal.offset, literal.length), - (DartEditBuilder builder) { - builder.write('$intValue'); - }); - }); - _addAssistFromBuilder(changeBuilder, DartAssistKind.CONVERT_TO_INT_LITERAL); - } - Future<void> _addProposal_assignToLocalVariable() async { // TODO(brianwilkerson) Determine whether this await is necessary. await null; @@ -469,7 +403,7 @@ Future<void> _addProposal_convertClassToMixin() async { ClassDeclaration classDeclaration = - node.getAncestor((n) => n is ClassDeclaration); + node.thisOrAncestorOfType<ClassDeclaration>(); if (classDeclaration == null) { return; } @@ -524,7 +458,7 @@ Future<void> _addProposal_convertDocumentationIntoBlock() async { // TODO(brianwilkerson) Determine whether this await is necessary. await null; - Comment comment = node.getAncestor((n) => n is Comment); + Comment comment = node.thisOrAncestorOfType<Comment>(); if (comment == null || !comment.isDocumentation) { return; } @@ -557,7 +491,7 @@ Future<void> _addProposal_convertDocumentationIntoLine() async { // TODO(brianwilkerson) Determine whether this await is necessary. await null; - Comment comment = node.getAncestor((n) => n is Comment); + Comment comment = node.thisOrAncestorOfType<Comment>(); if (comment == null || !comment.isDocumentation || comment.tokens.length != 1) { @@ -592,13 +526,17 @@ if (line.startsWith(prefix + ' */')) { break; } - String expectedPrefix = prefix + ' * '; + String expectedPrefix = prefix + ' *'; if (!line.startsWith(expectedPrefix)) { _coverageMarker(); return; } line = line.substring(expectedPrefix.length).trim(); - newLines.add('$linePrefix/// $line'); + if (line.isEmpty) { + newLines.add('$linePrefix///'); + } else { + newLines.add('$linePrefix/// $line'); + } linePrefix = eol + prefix; } } @@ -740,13 +678,12 @@ Future<void> _addProposal_convertPartOfToUri() async { // TODO(brianwilkerson) Determine whether this await is necessary. await null; - PartOfDirective directive = - node.getAncestor((node) => node is PartOfDirective); + PartOfDirective directive = node.thisOrAncestorOfType<PartOfDirective>(); if (directive == null || directive.libraryName == null) { return; } - String libraryPath = unitLibraryElement.source.fullName; - String partPath = unit.declaredElement.source.fullName; + String libraryPath = context.resolveResult.libraryElement.source.fullName; + String partPath = context.resolveResult.path; String relativePath = relative(libraryPath, from: dirname(partPath)); String uri = new Uri.file(relativePath).toString(); SourceRange replacementRange = range.node(directive.libraryName); @@ -902,7 +839,7 @@ } // prepare ConstructorDeclaration ConstructorDeclaration constructor = - node.getAncestor((node) => node is ConstructorDeclaration); + node.thisOrAncestorOfType<ConstructorDeclaration>(); if (constructor == null) { return; } @@ -993,7 +930,7 @@ await null; // find enclosing ForEachStatement ForEachStatement forEachStatement = - node.getAncestor((n) => n is ForEachStatement); + node.thisOrAncestorOfType<ForEachStatement>(); if (forEachStatement == null) { _coverageMarker(); return; @@ -1088,6 +1025,33 @@ } } + Future<void> _addProposal_convertToIntLiteral() async { + if (node is! DoubleLiteral) { + _coverageMarker(); + return; + } + DoubleLiteral literal = node; + int intValue; + try { + intValue = literal.value?.truncate(); + } catch (e) { + // Double cannot be converted to int + } + if (intValue == null || intValue != literal.value) { + _coverageMarker(); + return; + } + + DartChangeBuilder changeBuilder = new DartChangeBuilder(session); + await changeBuilder.addFileEdit(file, (DartFileEditBuilder builder) { + builder.addReplacement(new SourceRange(literal.offset, literal.length), + (DartEditBuilder builder) { + builder.write('$intValue'); + }); + }); + _addAssistFromBuilder(changeBuilder, DartAssistKind.CONVERT_TO_INT_LITERAL); + } + Future<void> _addProposal_convertToIsNot_onIs() async { // TODO(brianwilkerson) Determine whether this await is necessary. await null; @@ -1310,7 +1274,7 @@ await null; // find FieldDeclaration FieldDeclaration fieldDeclaration = - node.getAncestor((x) => x is FieldDeclaration); + node.thisOrAncestorOfType<FieldDeclaration>(); if (fieldDeclaration == null) { _coverageMarker(); return; @@ -1496,7 +1460,7 @@ Future<void> _addProposal_flutterConvertToStatefulWidget() async { ClassDeclaration widgetClass = - node.getAncestor((n) => n is ClassDeclaration); + node.thisOrAncestorOfType<ClassDeclaration>(); TypeName superclass = widgetClass?.extendsClause?.superclass; if (widgetClass == null || superclass == null) { _coverageMarker(); @@ -1906,6 +1870,61 @@ parent, child, DartAssistKind.FLUTTER_SWAP_WITH_PARENT); } + Future<void> _addProposal_flutterWrapStreamBuilder() async { + Expression widgetExpr = flutter.identifyWidgetExpression(node); + if (widgetExpr == null) { + return; + } + if (flutter.isExactWidgetTypeStreamBuilder(widgetExpr.staticType)) { + return; + } + String widgetSrc = utils.getNodeText(widgetExpr); + + var streamBuilderElement = await sessionHelper.getClass( + flutter.WIDGETS_LIBRARY_URI, + 'StreamBuilder', + ); + if (streamBuilderElement == null) { + return; + } + + var changeBuilder = new DartChangeBuilder(session); + await changeBuilder.addFileEdit(file, (builder) { + builder.addReplacement(range.node(widgetExpr), (builder) { + builder.writeType(streamBuilderElement.type); + builder.writeln('<Object>('); + + String indentOld = utils.getLinePrefix(widgetExpr.offset); + String indentNew1 = indentOld + utils.getIndent(1); + String indentNew2 = indentOld + utils.getIndent(2); + + builder.write(indentNew1); + builder.writeln('stream: null,'); + + builder.write(indentNew1); + builder.writeln('builder: (context, snapshot) {'); + + widgetSrc = widgetSrc.replaceAll( + new RegExp("^$indentOld", multiLine: true), + indentNew2, + ); + builder.write(indentNew2); + builder.write('return $widgetSrc'); + builder.writeln(';'); + + builder.write(indentNew1); + builder.writeln('}'); + + builder.write(indentOld); + builder.write(')'); + }); + }); + _addAssistFromBuilder( + changeBuilder, + DartAssistKind.FLUTTER_WRAP_STREAM_BUILDER, + ); + } + Future<void> _addProposal_flutterWrapWidget() async { // TODO(brianwilkerson) Determine whether this await is necessary. await null; @@ -2006,7 +2025,7 @@ await null; var selectionRange = new SourceRange(selectionOffset, selectionLength); var analyzer = new SelectionAnalyzer(selectionRange); - unit.accept(analyzer); + context.resolveResult.unit.accept(analyzer); List<Expression> widgetExpressions = []; if (analyzer.hasSelectedNodes) { @@ -2095,7 +2114,7 @@ await null; // prepare ImportDirective ImportDirective importDirective = - node.getAncestor((node) => node is ImportDirective); + node.thisOrAncestorOfType<ImportDirective>(); if (importDirective == null) { _coverageMarker(); return; @@ -2121,7 +2140,7 @@ referencedNames.add(element.displayName); } }); - unit.accept(visitor); + context.resolveResult.unit.accept(visitor); // ignore if unused if (referencedNames.isEmpty) { _coverageMarker(); @@ -2157,7 +2176,7 @@ String prefix; Block targetBlock; { - Statement statement = node.getAncestor((n) => n is Statement); + Statement statement = node.thisOrAncestorOfType<Statement>(); if (statement is IfStatement && statement.thenStatement is Block) { targetBlock = statement.thenStatement; } else if (statement is WhileStatement && statement.body is Block) { @@ -2389,6 +2408,7 @@ return; } int declOffset = element.nameOffset; + var unit = context.resolveResult.unit; AstNode declNode = new NodeLocator(declOffset).searchWithin(unit); if (declNode != null && declNode.parent is VariableDeclaration && @@ -2446,7 +2466,7 @@ await null; // prepare enclosing VariableDeclarationList VariableDeclarationList declList = - node.getAncestor((node) => node is VariableDeclarationList); + node.thisOrAncestorOfType<VariableDeclarationList>(); if (declList != null && declList.variables.length == 1) { } else { _coverageMarker(); @@ -2515,7 +2535,7 @@ // TODO(brianwilkerson) Determine whether this await is necessary. await null; VariableDeclarationList declarationList = - node.getAncestor((n) => n is VariableDeclarationList); + node.thisOrAncestorOfType<VariableDeclarationList>(); if (declarationList == null) { _coverageMarker(); return; @@ -2611,7 +2631,7 @@ await null; ConditionalExpression conditional = null; // may be on Statement with Conditional - Statement statement = node.getAncestor((node) => node is Statement); + Statement statement = node.thisOrAncestorOfType<Statement>(); if (statement == null) { _coverageMarker(); return; @@ -2801,7 +2821,7 @@ return; } // prepare "if" - Statement statement = node.getAncestor((node) => node is Statement); + Statement statement = node.thisOrAncestorOfType<Statement>(); if (statement is! IfStatement) { _coverageMarker(); return; @@ -2878,7 +2898,7 @@ await null; // prepare DartVariableStatement, should be part of Block VariableDeclarationStatement statement = - node.getAncestor((node) => node is VariableDeclarationStatement); + node.thisOrAncestorOfType<VariableDeclarationStatement>(); if (statement != null && statement.parent is Block) { } else { _coverageMarker(); @@ -2920,8 +2940,9 @@ List<Statement> selectedStatements; { StatementAnalyzer selectionAnalyzer = new StatementAnalyzer( - unit, new SourceRange(selectionOffset, selectionLength)); - unit.accept(selectionAnalyzer); + context.resolveResult, + new SourceRange(selectionOffset, selectionLength)); + selectionAnalyzer.analyze(); List<AstNode> selectedNodes = selectionAnalyzer.selectedNodes; // convert nodes to statements selectedStatements = []; @@ -3149,7 +3170,7 @@ utils.targetClassElement = null; if (target is AstNode) { ClassDeclaration targetClassDeclaration = - target.getAncestor((node) => node is ClassDeclaration); + target.thisOrAncestorOfType<ClassDeclaration>(); if (targetClassDeclaration != null) { utils.targetClassElement = targetClassDeclaration.declaredElement; } @@ -3330,13 +3351,8 @@ } bool _setupCompute() { - try { - utils = new CorrectionUtils(unit); - } catch (e) { - throw new CancelCorrectionException(exception: e); - } - - node = new NodeLocator(selectionOffset, selectionEnd).searchWithin(unit); + var locator = new NodeLocator(selectionOffset, selectionEnd); + node = locator.searchWithin(context.resolveResult.unit); return node != null; }
diff --git a/pkg/analysis_server/lib/src/services/correction/fix.dart b/pkg/analysis_server/lib/src/services/correction/fix.dart index 21765cf..796ae49 100644 --- a/pkg/analysis_server/lib/src/services/correction/fix.dart +++ b/pkg/analysis_server/lib/src/services/correction/fix.dart
@@ -2,11 +2,10 @@ // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. -import 'package:analysis_server/plugin/edit/fix/fix_core.dart'; +import 'package:analysis_server/plugin/edit/fix/fix_dart.dart'; import 'package:analysis_server/src/services/correction/fix_internal.dart'; +import 'package:analyzer/dart/analysis/results.dart'; import 'package:analyzer/error/error.dart'; -import 'package:analyzer/file_system/file_system.dart'; -import 'package:analyzer/src/dart/analysis/driver.dart'; import 'package:analyzer/src/error/codes.dart'; import 'package:analyzer/src/generated/parser.dart'; import 'package:analyzer_plugin/utilities/fixes/fixes.dart'; @@ -62,7 +61,6 @@ errorCode == HintCode.UNUSED_CATCH_CLAUSE || errorCode == HintCode.UNUSED_CATCH_STACK || errorCode == HintCode.UNUSED_IMPORT || - errorCode == HintCode.UNDEFINED_METHOD || errorCode == ParserErrorCode.EXPECTED_TOKEN || errorCode == ParserErrorCode.GETTER_WITH_PARAMETERS || errorCode == ParserErrorCode.VAR_AS_TYPE_NAME || @@ -86,6 +84,23 @@ errorCode.name == LintNames.unnecessary_this)); /** + * The implementation of [DartFixContext]. + */ +class DartFixContextImpl implements DartFixContext { + @override + final ResolvedUnitResult resolveResult; + + @override + final AnalysisError error; + + DartFixContextImpl(this.resolveResult, this.error); + + DartFixContextImpl.from(DartFixContext other) + : resolveResult = other.resolveResult, + error = other.error; +} + +/** * An enumeration of possible quick fix kinds. */ class DartFixKind { @@ -96,20 +111,22 @@ appliedTogetherMessage: "Add all casts in file"); static const ADD_FIELD_FORMAL_PARAMETERS = const FixKind( 'ADD_FIELD_FORMAL_PARAMETERS', 70, "Add final field formal parameters"); + static const ADD_MISSING_PARAMETER_NAMED = const FixKind( + 'ADD_MISSING_PARAMETER_NAMED', 70, "Add named parameter '{0}'"); static const ADD_MISSING_PARAMETER_POSITIONAL = const FixKind( 'ADD_MISSING_PARAMETER_POSITIONAL', 69, "Add optional positional parameter"); - static const ADD_MISSING_PARAMETER_NAMED = const FixKind( - 'ADD_MISSING_PARAMETER_NAMED', 70, "Add named parameter '{0}'"); static const ADD_MISSING_PARAMETER_REQUIRED = const FixKind( 'ADD_MISSING_PARAMETER_REQUIRED', 70, "Add required parameter"); static const ADD_MISSING_REQUIRED_ARGUMENT = const FixKind( 'ADD_MISSING_REQUIRED_ARGUMENT', 70, "Add required argument '{0}'"); static const ADD_NE_NULL = const FixKind('ADD_NE_NULL', 50, "Add != null", appliedTogetherMessage: "Add != null everywhere in file"); - static const ADD_PACKAGE_DEPENDENCY = const FixKind( - 'ADD_PACKAGE_DEPENDENCY', 50, "Add dependency on package '{0}'"); + static const ADD_OVERRIDE = + const FixKind('ADD_OVERRIDE', 50, "Add '@override' annotation"); + static const ADD_REQUIRED = + const FixKind('ADD_REQUIRED', 50, "Add '@required' annotation"); static const ADD_STATIC = const FixKind('ADD_STATIC', 50, "Add 'static' modifier"); static const ADD_SUPER_CONSTRUCTOR_INVOCATION = const FixKind( @@ -129,6 +146,8 @@ const FixKind('CONVERT_FLUTTER_CHILD', 50, "Convert to children:"); static const CONVERT_FLUTTER_CHILDREN = const FixKind('CONVERT_FLUTTER_CHILDREN', 50, "Convert to child:"); + static const CONVERT_TO_NAMED_ARGUMENTS = const FixKind( + 'CONVERT_TO_NAMED_ARGUMENTS', 50, "Convert to named arguments"); static const CREATE_CLASS = const FixKind('CREATE_CLASS', 50, "Create class '{0}'"); static const CREATE_CONSTRUCTOR = @@ -157,8 +176,10 @@ const FixKind('CREATE_MIXIN', 50, "Create mixin '{0}'"); static const CREATE_NO_SUCH_METHOD = const FixKind( 'CREATE_NO_SUCH_METHOD', 49, "Create 'noSuchMethod' method"); - static const CONVERT_TO_NAMED_ARGUMENTS = const FixKind( - 'CONVERT_TO_NAMED_ARGUMENTS', 50, "Convert to named arguments"); + static const EXTEND_CLASS_FOR_MIXIN = + const FixKind('EXTEND_CLASS_FOR_MIXIN', 50, "Extend the class '{0}'"); + static const IMPORT_ASYNC = + const FixKind('IMPORT_ASYNC', 49, "Import 'dart:async'"); static const IMPORT_LIBRARY_PREFIX = const FixKind('IMPORT_LIBRARY_PREFIX', 49, "Use imported library '{0}' with prefix '{1}'"); static const IMPORT_LIBRARY_PROJECT1 = @@ -173,28 +194,18 @@ const FixKind('IMPORT_LIBRARY_SHOW', 55, "Update library '{0}' import"); static const INSERT_SEMICOLON = const FixKind('INSERT_SEMICOLON', 50, "Insert ';'"); - static const INVOKE_CONSTRUCTOR_USING_NEW = const FixKind( - 'INVOKE_CONSTRUCTOR_USING_NEW', 50, "Invoke constructor using 'new'"); - static const LINT_ADD_OVERRIDE = - const FixKind('LINT_ADD_OVERRIDE', 50, "Add '@override' annotation"); - static const LINT_ADD_REQUIRED = - const FixKind('LINT_ADD_REQUIRED', 50, "Add '@required' annotation"); - static const LINT_REMOVE_INTERPOLATION_BRACES = const FixKind( - 'LINT_REMOVE_INTERPOLATION_BRACES', - 50, - "Remove unnecessary interpolation braces"); static const MAKE_CLASS_ABSTRACT = const FixKind('MAKE_CLASS_ABSTRACT', 50, "Make class '{0}' abstract"); + static const MAKE_FIELD_NOT_FINAL = + const FixKind('MAKE_FIELD_NOT_FINAL', 50, "Make field '{0}' not final"); + static const MAKE_FINAL = const FixKind('MAKE_FINAL', 50, "Make final"); static const MOVE_TYPE_ARGUMENTS_TO_CLASS = const FixKind( 'MOVE_TYPE_ARGUMENTS_TO_CLASS', 50, "Move type arguments to after class name"); + static const REMOVE_AWAIT = const FixKind('REMOVE_AWAIT', 50, "Remove await"); static const REMOVE_DEAD_CODE = const FixKind('REMOVE_DEAD_CODE', 50, "Remove dead code"); - static const MAKE_FIELD_NOT_FINAL = - const FixKind('MAKE_FIELD_NOT_FINAL', 50, "Make field '{0}' not final"); - static const MAKE_FINAL = const FixKind('MAKE_FINAL', 50, "Make final"); - static const REMOVE_AWAIT = const FixKind('REMOVE_AWAIT', 50, "Remove await"); static const REMOVE_EMPTY_CATCH = const FixKind('REMOVE_EMPTY_CATCH', 50, "Remove empty catch clause"); static const REMOVE_EMPTY_CONSTRUCTOR_BODY = const FixKind( @@ -205,6 +216,10 @@ const FixKind('REMOVE_EMPTY_STATEMENT', 50, "Remove empty statement"); static const REMOVE_INITIALIZER = const FixKind('REMOVE_INITIALIZER', 50, "Remove initializer"); + static const REMOVE_INTERPOLATION_BRACES = const FixKind( + 'REMOVE_INTERPOLATION_BRACES', + 50, + "Remove unnecessary interpolation braces"); static const REMOVE_METHOD_DECLARATION = const FixKind( 'REMOVE_METHOD_DECLARATION', 50, "Remove method declaration"); static const REMOVE_PARAMETERS_IN_GETTER_DECLARATION = const FixKind( @@ -217,10 +232,10 @@ "Remove parentheses in getter invocation"); static const REMOVE_THIS_EXPRESSION = const FixKind('REMOVE_THIS_EXPRESSION', 50, "Remove this expression"); + static const REMOVE_TYPE_ANNOTATION = + const FixKind('REMOVE_TYPE_ANNOTATION', 50, "Remove type annotation"); static const REMOVE_TYPE_ARGUMENTS = const FixKind('REMOVE_TYPE_ARGUMENTS', 49, "Remove type arguments"); - static const REMOVE_TYPE_NAME = - const FixKind('REMOVE_TYPE_NAME', 50, "Remove type name"); static const REMOVE_UNNECESSARY_CAST = const FixKind( 'REMOVE_UNNECESSARY_CAST', 50, "Remove unnecessary cast", appliedTogetherMessage: "Remove all unnecessary casts in file"); @@ -238,12 +253,12 @@ appliedTogetherMessage: "Replace all 'boolean' with 'bool' in file"); static const REPLACE_FINAL_WITH_CONST = const FixKind( 'REPLACE_FINAL_WITH_CONST', 50, "Replace 'final' with 'const'"); - static const REPLACE_VAR_WITH_DYNAMIC = const FixKind( - 'REPLACE_VAR_WITH_DYNAMIC', 50, "Replace 'var' with 'dynamic'"); static const REPLACE_RETURN_TYPE_FUTURE = const FixKind( 'REPLACE_RETURN_TYPE_FUTURE', 50, "Return 'Future' from 'async' function"); + static const REPLACE_VAR_WITH_DYNAMIC = const FixKind( + 'REPLACE_VAR_WITH_DYNAMIC', 50, "Replace 'var' with 'dynamic'"); static const REPLACE_WITH_BRACKETS = const FixKind('REPLACE_WITH_BRACKETS', 50, "Replace with { }"); static const REPLACE_WITH_CONDITIONAL_ASSIGNMENT = const FixKind( @@ -258,6 +273,8 @@ "Replace the '.' with a '?.' in the invocation"); static const REPLACE_WITH_TEAR_OFF = const FixKind( 'REPLACE_WITH_TEAR_OFF', 50, "Replace function literal with tear-off"); + static const UPDATE_SDK_CONSTRAINTS = + const FixKind('UPDATE_SDK_CONSTRAINTS', 50, "Update the SDK constraints"); static const USE_CONST = const FixKind('USE_CONST', 50, "Change to constant"); static const USE_EFFECTIVE_INTEGER_DIVISION = const FixKind( 'USE_EFFECTIVE_INTEGER_DIVISION', @@ -274,29 +291,3 @@ appliedTogetherMessage: "Use != null instead of 'is! Null' everywhere in file"); } - -/** - * The implementation of [FixContext]. - */ -class FixContextImpl implements FixContext { - @override - final ResourceProvider resourceProvider; - - @override - final AnalysisDriver analysisDriver; - - @override - final AnalysisError error; - - @override - final List<AnalysisError> errors; - - FixContextImpl( - this.resourceProvider, this.analysisDriver, this.error, this.errors); - - FixContextImpl.from(FixContext other) - : resourceProvider = other.resourceProvider, - analysisDriver = other.analysisDriver, - error = other.error, - errors = other.errors; -}
diff --git a/pkg/analysis_server/lib/src/services/correction/fix_internal.dart b/pkg/analysis_server/lib/src/services/correction/fix_internal.dart index db40113..ff63464 100644 --- a/pkg/analysis_server/lib/src/services/correction/fix_internal.dart +++ b/pkg/analysis_server/lib/src/services/correction/fix_internal.dart
@@ -1,4 +1,4 @@ -// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file +// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. @@ -23,16 +23,12 @@ import 'package:analyzer/dart/element/element.dart'; import 'package:analyzer/dart/element/type.dart'; import 'package:analyzer/error/error.dart'; -import 'package:analyzer/exception/exception.dart'; import 'package:analyzer/file_system/file_system.dart'; -import 'package:analyzer/src/context/context_root.dart'; -import 'package:analyzer/src/dart/analysis/driver.dart'; import 'package:analyzer/src/dart/analysis/session_helper.dart'; import 'package:analyzer/src/dart/analysis/top_level_declaration.dart'; import 'package:analyzer/src/dart/ast/ast.dart'; import 'package:analyzer/src/dart/ast/token.dart'; import 'package:analyzer/src/dart/ast/utilities.dart'; -import 'package:analyzer/src/dart/element/ast_provider.dart'; import 'package:analyzer/src/dart/element/element.dart'; import 'package:analyzer/src/dart/element/member.dart'; import 'package:analyzer/src/dart/element/type.dart'; @@ -44,6 +40,7 @@ import 'package:analyzer/src/generated/parser.dart'; import 'package:analyzer/src/generated/resolver.dart'; import 'package:analyzer/src/generated/source.dart'; +import 'package:analyzer/src/hint/sdk_constraint_extractor.dart'; import 'package:analyzer_plugin/protocol/protocol_common.dart' hide AnalysisError, Element, ElementKind; import 'package:analyzer_plugin/src/utilities/string_utilities.dart'; @@ -58,30 +55,11 @@ typedef bool ElementPredicate(Element argument); /** - * The implementation of [DartFixContext]. - * - * Clients may not extend, implement or mix-in this class. + * A fix contributor that provides the default set of fixes for Dart files. */ -class DartFixContextImpl extends FixContextImpl implements DartFixContext { +class DartFixContributor implements FixContributor { @override - final AstProvider astProvider; - - @override - final CompilationUnit unit; - - DartFixContextImpl(FixContext fixContext, this.astProvider, this.unit) - : super.from(fixContext); - - GetTopLevelDeclarations get getTopLevelDeclarations => - analysisDriver.getTopLevelNameDeclarations; -} - -/** - * A [FixContributor] that provides the default set of fixes. - */ -class DefaultFixContributor extends DartFixContributor { - @override - Future<List<Fix>> internalComputeFixes(DartFixContext context) async { + Future<List<Fix>> computeFixes(DartFixContext context) async { // TODO(brianwilkerson) Determine whether this await is necessary. await null; try { @@ -98,8 +76,8 @@ DartFixContext context, List<Fix> fixes) async { // TODO(brianwilkerson) Determine whether this await is necessary. await null; - final AnalysisError analysisError = context.error; - final List<AnalysisError> allAnalysisErrors = context.errors; + final analysisError = context.error; + final allAnalysisErrors = context.resolveResult.errors.toList(); // Validate inputs: // - return if no fixes @@ -123,14 +101,9 @@ // one. // For each fix, put the fix into the HashMap. for (int i = 0; i < allAnalysisErrors.length; i++) { - final FixContext fixContextI = new FixContextImpl( - context.resourceProvider, - context.analysisDriver, - allAnalysisErrors[i], - allAnalysisErrors); - final DartFixContextImpl dartFixContextI = new DartFixContextImpl( - fixContextI, context.astProvider, context.unit); - final FixProcessor processorI = new FixProcessor(dartFixContextI); + final FixContext fixContextI = + new DartFixContextImpl(context.resolveResult, allAnalysisErrors[i]); + final FixProcessor processorI = new FixProcessor(fixContextI); final List<Fix> fixesListI = await processorI.compute(); for (Fix f in fixesListI) { if (!map.containsKey(f.kind)) { @@ -188,70 +161,40 @@ class FixProcessor { static const int MAX_LEVENSHTEIN_DISTANCE = 3; - ResourceProvider resourceProvider; - AstProvider astProvider; - GetTopLevelDeclarations getTopLevelDeclarations; - CompilationUnit unit; - AnalysisError error; + final DartFixContext context; + final ResourceProvider resourceProvider; + final AnalysisSession session; + final AnalysisSessionHelper sessionHelper; + final TypeProvider typeProvider; + final TypeSystem typeSystem; - /** - * The analysis driver being used to perform analysis. - */ - AnalysisDriver driver; + final String file; + final LibraryElement unitLibraryElement; + final CompilationUnit unit; + final CorrectionUtils utils; - /** - * The analysis session to be used to create the change builder. - */ - AnalysisSession session; - - /** - * The helper wrapper around the [session]. - */ - AnalysisSessionHelper sessionHelper; - - String file; - CompilationUnitElement unitElement; - Source unitSource; - LibraryElement unitLibraryElement; - File unitLibraryFile; - Folder unitLibraryFolder; + final AnalysisError error; + final int errorOffset; + final int errorLength; final List<Fix> fixes = <Fix>[]; - CorrectionUtils utils; - int errorOffset; - int errorLength; - int errorEnd; - SourceRange errorRange; AstNode node; AstNode coveredNode; - TypeProvider _typeProvider; - TypeSystem _typeSystem; - - FixProcessor(DartFixContext dartContext) { - resourceProvider = dartContext.resourceProvider; - astProvider = dartContext.astProvider; - getTopLevelDeclarations = dartContext.getTopLevelDeclarations; - - driver = dartContext.analysisDriver; - session = driver.currentSession; - sessionHelper = new AnalysisSessionHelper(session); - - // unit - unit = dartContext.unit; - unitElement = unit.declaredElement; - unitSource = unitElement.source; - // file - file = unitSource.fullName; - // library - unitLibraryElement = unitElement.library; - String unitLibraryPath = unitLibraryElement.source.fullName; - unitLibraryFile = resourceProvider.getFile(unitLibraryPath); - unitLibraryFolder = unitLibraryFile.parent; - // error - error = dartContext.error; - } + FixProcessor(this.context) + : resourceProvider = context.resolveResult.session.resourceProvider, + session = context.resolveResult.session, + sessionHelper = AnalysisSessionHelper(context.resolveResult.session), + typeProvider = context.resolveResult.typeProvider, + typeSystem = StrongTypeSystemImpl(context.resolveResult.typeProvider), + file = context.resolveResult.path, + unitLibraryElement = context.resolveResult.libraryElement, + unit = context.resolveResult.unit, + utils = CorrectionUtils(context.resolveResult), + error = context.error, + errorOffset = context.error.offset, + errorLength = context.error.length; DartType get coreTypeBool => _getCoreType('bool'); @@ -260,36 +203,13 @@ */ String get eol => utils.endOfLine; - TypeProvider get typeProvider { - if (_typeProvider == null) { - _typeProvider = unitElement.context.typeProvider; - } - return _typeProvider; - } - - TypeSystem get typeSystem { - if (_typeSystem == null) { - _typeSystem = new StrongTypeSystemImpl(typeProvider); - } - return _typeSystem; - } - Future<List<Fix>> compute() async { // TODO(brianwilkerson) Determine whether this await is necessary. await null; - try { - utils = new CorrectionUtils(unit); - } catch (e) { - throw new CancelCorrectionException(exception: e); - } - errorOffset = error.offset; - errorLength = error.length; - errorEnd = errorOffset + errorLength; - errorRange = new SourceRange(errorOffset, errorLength); node = new NodeLocator2(errorOffset).searchWithin(unit); - coveredNode = - new NodeLocator2(errorOffset, errorEnd - 1).searchWithin(unit); + coveredNode = new NodeLocator2(errorOffset, errorOffset + errorLength - 1) + .searchWithin(unit); if (coveredNode == null) { // TODO(brianwilkerson) Figure out why the coveredNode is sometimes null. return fixes; @@ -481,9 +401,6 @@ errorCode == StaticWarningCode.UNDEFINED_NAMED_PARAMETER) { await _addFix_addMissingNamedArgument(); } - if (errorCode == StaticTypeWarningCode.UNDEFINED_METHOD_WITH_CONSTRUCTOR) { - await _addFix_undefinedMethodWithContructor(); - } if (errorCode == StaticTypeWarningCode.ILLEGAL_ASYNC_RETURN_TYPE) { await _addFix_illegalAsyncReturnType(); } @@ -526,8 +443,7 @@ await _addFix_importLibrary_withTopLevelVariable(); await _addFix_importLibrary_withType(); } - if (errorCode == HintCode.UNDEFINED_METHOD || - errorCode == StaticTypeWarningCode.UNDEFINED_METHOD) { + if (errorCode == StaticTypeWarningCode.UNDEFINED_METHOD) { await _addFix_createClass(); await _addFix_importLibrary_withFunction(); await _addFix_importLibrary_withType(); @@ -556,6 +472,14 @@ await _addFix_moveTypeArgumentsToClass(); await _addFix_removeTypeArguments(); } + if (errorCode == + CompileTimeErrorCode.MIXIN_APPLICATION_NOT_IMPLEMENTED_INTERFACE) { + await _addFix_extendClassForMixin(); + } + if (errorCode == HintCode.SDK_VERSION_ASYNC_EXPORTED_FROM_CORE) { + await _addFix_importAsync(); + await _addFix_updateSdkConstraints(); + } // lints if (errorCode is LintCode) { String name = errorCode.name; @@ -642,7 +566,7 @@ Future<void> _addFix_addAsync() async { // TODO(brianwilkerson) Determine whether this await is necessary. await null; - FunctionBody body = node.getAncestor((n) => n is FunctionBody); + FunctionBody body = node.thisOrAncestorOfType<FunctionBody>(); if (body != null && body.keyword == null) { TypeProvider typeProvider = this.typeProvider; DartChangeBuilder changeBuilder = new DartChangeBuilder(session); @@ -777,7 +701,7 @@ AstNode argumentList = namedExpression.parent; // Prepare the invoked element. - var context = new _ExecutableParameters(astProvider, argumentList.parent); + var context = new _ExecutableParameters(sessionHelper, argumentList.parent); if (context == null) { return; } @@ -829,7 +753,7 @@ List<Expression> arguments = argumentList.arguments; // Prepare the invoked element. - var context = new _ExecutableParameters(astProvider, node.parent); + var context = new _ExecutableParameters(sessionHelper, node.parent); if (context == null) { return; } @@ -902,7 +826,7 @@ argumentList = invocation.argumentList; } else { creation = - invocation.getAncestor((p) => p is InstanceCreationExpression); + invocation.thisOrAncestorOfType<InstanceCreationExpression>(); if (creation != null) { targetElement = creation.staticElement; argumentList = creation.argumentList; @@ -960,7 +884,7 @@ Future<void> _addFix_addOverrideAnnotation() async { // TODO(brianwilkerson) Determine whether this await is necessary. await null; - ClassMember member = node.getAncestor((n) => n is ClassMember); + ClassMember member = node.thisOrAncestorOfType<ClassMember>(); if (member == null) { return; } @@ -981,7 +905,7 @@ range.startLength(token, 0), '@override$eol$indent'); }); changeBuilder.setSelection(exitPosition); - _addFixFromBuilder(changeBuilder, DartFixKind.LINT_ADD_OVERRIDE); + _addFixFromBuilder(changeBuilder, DartFixKind.ADD_OVERRIDE); } Future<void> _addFix_addRequiredAnnotation() async { @@ -991,14 +915,14 @@ await changeBuilder.addFileEdit(file, (DartFileEditBuilder builder) { builder.addSimpleInsertion(node.parent.offset, '@required '); }); - _addFixFromBuilder(changeBuilder, DartFixKind.LINT_ADD_REQUIRED); + _addFixFromBuilder(changeBuilder, DartFixKind.ADD_REQUIRED); } Future<void> _addFix_addStatic() async { // TODO(brianwilkerson) Determine whether this await is necessary. await null; FieldDeclaration declaration = - node.getAncestor((n) => n is FieldDeclaration); + node.thisOrAncestorOfType<FieldDeclaration>(); DartChangeBuilder changeBuilder = new DartChangeBuilder(session); await changeBuilder.addFileEdit(file, (DartFileEditBuilder builder) { builder.addSimpleInsertion(declaration.offset, 'static '); @@ -1265,9 +1189,10 @@ int offset = -1; String filePath; if (prefixElement == null) { - targetUnit = unitElement; - CompilationUnitMember enclosingMember = node.getAncestor((node) => - node is CompilationUnitMember && node.parent is CompilationUnit); + targetUnit = unit.declaredElement; + CompilationUnitMember enclosingMember = node.thisOrAncestorMatching( + (node) => + node is CompilationUnitMember && node.parent is CompilationUnit); if (enclosingMember == null) { return; } @@ -1324,7 +1249,7 @@ } ClassDeclaration classDeclaration = - node.getAncestor((node) => node is ClassDeclaration); + node.thisOrAncestorOfType<ClassDeclaration>(); if (classDeclaration == null) { return; } @@ -1418,12 +1343,12 @@ } ClassElement targetElement = constructorElement.enclosingElement; // prepare location for a new constructor - AstNode targetTypeNode = getParsedClassElementNode(targetElement); - if (targetTypeNode is! ClassDeclaration) { + var targetNode = await _getClassDeclaration(targetElement); + if (targetNode == null) { return; } ClassMemberLocation targetLocation = - utils.prepareNewConstructorLocation(targetTypeNode); + utils.prepareNewConstructorLocation(targetNode); Source targetSource = targetElement.source; String targetFile = targetSource.fullName; DartChangeBuilder changeBuilder = new DartChangeBuilder(session); @@ -1474,12 +1399,12 @@ } // prepare location for a new constructor ClassElement targetElement = targetType.element as ClassElement; - AstNode targetTypeNode = getParsedClassElementNode(targetElement); - if (targetTypeNode is! ClassDeclaration) { + var targetNode = await _getClassDeclaration(targetElement); + if (targetNode == null) { return; } ClassMemberLocation targetLocation = - utils.prepareNewConstructorLocation(targetTypeNode); + utils.prepareNewConstructorLocation(targetNode); String targetFile = targetElement.source.fullName; DartChangeBuilder changeBuilder = new DartChangeBuilder(session); await changeBuilder.addFileEdit(file, (DartFileEditBuilder builder) { @@ -1574,7 +1499,7 @@ // TODO(brianwilkerson) Determine whether this await is necessary. await null; ClassDeclaration targetClassNode = - node.getAncestor((parent) => parent is ClassDeclaration); + node.thisOrAncestorOfType<ClassDeclaration>(); ClassElement targetClassElement = targetClassNode.declaredElement; InterfaceType superType = targetClassElement.supertype; String targetClassName = targetClassElement.name; @@ -1689,14 +1614,16 @@ } utils.targetClassElement = targetClassElement; // prepare target ClassDeclaration - AstNode targetTypeNode = getParsedClassElementNode(targetClassElement); - if (targetTypeNode is! ClassDeclaration) { + var targetDeclarationResult = + await sessionHelper.getElementDeclaration(targetClassElement); + if (targetDeclarationResult.node is! ClassOrMixinDeclaration) { return; } - ClassDeclaration targetClassNode = targetTypeNode; + ClassOrMixinDeclaration targetNode = targetDeclarationResult.node; // prepare location ClassMemberLocation targetLocation = - _getUtilsFor(targetClassNode).prepareNewFieldLocation(targetClassNode); + CorrectionUtils(targetDeclarationResult.resolvedUnit) + .prepareNewFieldLocation(targetNode); // build field source Source targetSource = targetClassElement.source; String targetFile = targetSource.fullName; @@ -1724,12 +1651,12 @@ // Ensure that we are in an initializing formal parameter. // FieldFormalParameter parameter = - node.getAncestor((node) => node is FieldFormalParameter); + node.thisOrAncestorOfType<FieldFormalParameter>(); if (parameter == null) { return; } ClassDeclaration targetClassNode = - parameter.getAncestor((node) => node is ClassDeclaration); + parameter.thisOrAncestorOfType<ClassDeclaration>(); if (targetClassNode == null) { return; } @@ -1772,8 +1699,8 @@ return; } } else { - ClassDeclaration enclosingClass = - node.getAncestor((node) => node is ClassDeclaration); + ClassOrMixinDeclaration enclosingClass = + node.thisOrAncestorOfType<ClassOrMixinDeclaration>(); targetElement = enclosingClass?.declaredElement; argument = nameNode; } @@ -1851,15 +1778,17 @@ return; } utils.targetClassElement = targetClassElement; - // prepare target ClassDeclaration - AstNode targetTypeNode = getParsedClassElementNode(targetClassElement); - if (targetTypeNode is! ClassDeclaration) { + // prepare target ClassOrMixinDeclaration + var targetDeclarationResult = + await sessionHelper.getElementDeclaration(targetClassElement); + if (targetDeclarationResult.node is! ClassOrMixinDeclaration) { return; } - ClassDeclaration targetClassNode = targetTypeNode; + ClassOrMixinDeclaration targetNode = targetDeclarationResult.node; // prepare location ClassMemberLocation targetLocation = - _getUtilsFor(targetClassNode).prepareNewGetterLocation(targetClassNode); + CorrectionUtils(targetDeclarationResult.resolvedUnit) + .prepareNewGetterLocation(targetNode); // build method source Source targetSource = targetClassElement.source; String targetFile = targetSource.fullName; @@ -1891,18 +1820,15 @@ if (source != null) { String file = source.fullName; if (isAbsolute(file) && AnalysisEngine.isDartFileName(file)) { - String libName = _computeLibraryName(file); - try { - DartChangeBuilder changeBuilder = new DartChangeBuilder(session); - await changeBuilder.addFileEdit(source.fullName, - (DartFileEditBuilder builder) { - builder.addSimpleInsertion(0, 'library $libName;$eol$eol'); - }); - _addFixFromBuilder(changeBuilder, DartFixKind.CREATE_FILE, - args: [source.shortName]); - } on AnalysisException { - // Ignore the exception and just don't create a fix. - } + DartChangeBuilder changeBuilder = new DartChangeBuilder(session); + await changeBuilder.addFileEdit(source.fullName, (builder) { + builder.addSimpleInsertion(0, '// TODO Implement this library.'); + }); + _addFixFromBuilder( + changeBuilder, + DartFixKind.CREATE_FILE, + args: [source.shortName], + ); } } } @@ -1932,7 +1858,7 @@ } } // prepare target Statement - Statement target = node.getAncestor((x) => x is Statement); + Statement target = node.thisOrAncestorOfType<Statement>(); if (target == null) { return; } @@ -2083,9 +2009,10 @@ int offset = -1; String filePath; if (prefixElement == null) { - targetUnit = unitElement; - CompilationUnitMember enclosingMember = node.getAncestor((node) => - node is CompilationUnitMember && node.parent is CompilationUnit); + targetUnit = unit.declaredElement; + CompilationUnitMember enclosingMember = node.thisOrAncestorMatching( + (node) => + node is CompilationUnitMember && node.parent is CompilationUnit); if (enclosingMember == null) { return; } @@ -2179,11 +2106,30 @@ } } + Future<void> _addFix_extendClassForMixin() async { + ClassDeclaration declaration = + node.thisOrAncestorOfType<ClassDeclaration>(); + if (declaration != null && declaration.extendsClause == null) { + String message = error.message; + int startIndex = message.indexOf("'", message.indexOf("'") + 1) + 1; + int endIndex = message.indexOf("'", startIndex); + String typeName = message.substring(startIndex, endIndex); + DartChangeBuilder changeBuilder = new DartChangeBuilder(session); + await changeBuilder.addFileEdit(file, (DartFileEditBuilder builder) { + builder.addSimpleInsertion( + declaration.typeParameters?.end ?? declaration.name.end, + ' extends $typeName'); + }); + _addFixFromBuilder(changeBuilder, DartFixKind.EXTEND_CLASS_FOR_MIXIN, + args: [typeName]); + } + } + Future<void> _addFix_illegalAsyncReturnType() async { // TODO(brianwilkerson) Determine whether this await is necessary. await null; // prepare the existing type - TypeAnnotation typeName = node.getAncestor((n) => n is TypeAnnotation); + TypeAnnotation typeName = node.thisOrAncestorOfType<TypeAnnotation>(); TypeProvider typeProvider = this.typeProvider; DartChangeBuilder changeBuilder = new DartChangeBuilder(session); await changeBuilder.addFileEdit(file, (DartFileEditBuilder builder) { @@ -2192,6 +2138,11 @@ _addFixFromBuilder(changeBuilder, DartFixKind.REPLACE_RETURN_TYPE_FUTURE); } + Future<void> _addFix_importAsync() async { + await _addFix_importLibrary( + DartFixKind.IMPORT_ASYNC, Uri.parse('dart:async')); + } + Future<void> _addFix_importLibrary(FixKind kind, Uri library) async { // TODO(brianwilkerson) Determine whether this await is necessary. await null; @@ -2260,7 +2211,8 @@ String newShowCode = 'show ${showNames.join(', ')}'; int offset = showCombinator.offset; int length = showCombinator.end - offset; - String libraryFile = unitLibraryElement.source.fullName; + String libraryFile = + context.resolveResult.libraryElement.source.fullName; DartChangeBuilder changeBuilder = new DartChangeBuilder(session); await changeBuilder.addFileEdit(libraryFile, (DartFileEditBuilder builder) { @@ -2273,8 +2225,7 @@ } // Find new top-level declarations. { - List<TopLevelDeclarationInSource> declarations = - await getTopLevelDeclarations(name); + var declarations = await session.getTopLevelDeclarations(name); for (TopLevelDeclarationInSource declaration in declarations) { // Check the kind. if (declaration.declaration.kind != kind2) { @@ -2431,7 +2382,7 @@ // TODO(brianwilkerson) Determine whether this await is necessary. await null; ClassDeclaration enclosingClass = - node.getAncestor((node) => node is ClassDeclaration); + node.thisOrAncestorOfType<ClassDeclaration>(); if (enclosingClass == null) { return; } @@ -2457,9 +2408,9 @@ !getter.variable.isSynthetic && getter.variable.setter == null && getter.enclosingElement is ClassElement) { - AstNode name = - await astProvider.getParsedNameForElement(getter.variable); - AstNode variable = name?.parent; + var declarationResult = + await sessionHelper.getElementDeclaration(getter.variable); + AstNode variable = declarationResult.node; if (variable is VariableDeclaration && variable.parent is VariableDeclarationList && variable.parent.parent is FieldDeclaration) { @@ -2580,6 +2531,7 @@ } else if (coveringNode is Block) { Block block = coveringNode; List<Statement> statementsToRemove = <Statement>[]; + var errorRange = SourceRange(errorOffset, errorLength); for (Statement statement in block.statements) { if (range.node(statement).intersects(errorRange)) { statementsToRemove.add(statement); @@ -2667,7 +2619,7 @@ await null; // Retrieve the linted node. VariableDeclaration ancestor = - node.getAncestor((a) => a is VariableDeclaration); + node.thisOrAncestorOfType<VariableDeclaration>(); if (ancestor == null) { return; } @@ -2692,7 +2644,7 @@ builder.addDeletion(range.token(right)); }); _addFixFromBuilder( - changeBuilder, DartFixKind.LINT_REMOVE_INTERPOLATION_BRACES); + changeBuilder, DartFixKind.REMOVE_INTERPOLATION_BRACES); } else {} } } @@ -2701,7 +2653,7 @@ // TODO(brianwilkerson) Determine whether this await is necessary. await null; MethodDeclaration declaration = - node.getAncestor((node) => node is MethodDeclaration); + node.thisOrAncestorOfType<MethodDeclaration>(); if (declaration != null) { DartChangeBuilder changeBuilder = new DartChangeBuilder(session); await changeBuilder.addFileEdit(file, (DartFileEditBuilder builder) { @@ -2759,7 +2711,7 @@ await null; final thisExpression = node is ThisExpression ? node - : node.getAncestor((node) => node is ThisExpression); + : node.thisOrAncestorOfType<ThisExpression>(); final parent = thisExpression?.parent; if (parent is PropertyAccess) { DartChangeBuilder changeBuilder = new DartChangeBuilder(session); @@ -2779,14 +2731,13 @@ Future<void> _addFix_removeTypeAnnotation() async { // TODO(brianwilkerson) Determine whether this await is necessary. await null; - final TypeAnnotation type = - node.getAncestor((node) => node is TypeAnnotation); + final TypeAnnotation type = node.thisOrAncestorOfType<TypeAnnotation>(); if (type != null) { DartChangeBuilder changeBuilder = new DartChangeBuilder(session); await changeBuilder.addFileEdit(file, (DartFileEditBuilder builder) { builder.addDeletion(range.startStart(type, type.endToken.next)); }); - _addFixFromBuilder(changeBuilder, DartFixKind.REMOVE_TYPE_NAME); + _addFixFromBuilder(changeBuilder, DartFixKind.REMOVE_TYPE_ANNOTATION); } } @@ -2861,7 +2812,7 @@ await null; // prepare ImportDirective ImportDirective importDirective = - node.getAncestor((node) => node is ImportDirective); + node.thisOrAncestorOfType<ImportDirective>(); if (importDirective == null) { return; } @@ -2892,11 +2843,11 @@ List<SimpleIdentifier> references; Element element = identifier.staticElement; if (element is LocalVariableElement) { - AstNode root = node.getAncestor((node) => node is Block); + AstNode root = node.thisOrAncestorOfType<Block>(); references = findLocalElementReferences(root, element); } else if (element is ParameterElement) { if (!element.isNamed) { - AstNode root = node.getAncestor((node) => + AstNode root = node.thisOrAncestorMatching((node) => node.parent is ClassOrMixinDeclaration || node.parent is CompilationUnit); references = findLocalElementReferences(root, element); @@ -2943,9 +2894,8 @@ Future<void> _addFix_replaceWithConditionalAssignment() async { // TODO(brianwilkerson) Determine whether this await is necessary. await null; - IfStatement ifStatement = node is IfStatement - ? node - : node.getAncestor((node) => node is IfStatement); + IfStatement ifStatement = + node is IfStatement ? node : node.thisOrAncestorOfType<IfStatement>(); if (ifStatement == null) { return; } @@ -3000,7 +2950,7 @@ // TODO(brianwilkerson) Determine whether this await is necessary. await null; final FunctionTypedFormalParameter functionTyped = - node.getAncestor((node) => node is FunctionTypedFormalParameter); + node.thisOrAncestorOfType<FunctionTypedFormalParameter>(); if (functionTyped != null) { DartChangeBuilder changeBuilder = new DartChangeBuilder(session); await changeBuilder.addFileEdit(file, (DartFileEditBuilder builder) { @@ -3017,7 +2967,7 @@ // TODO(brianwilkerson) Determine whether this await is necessary. await null; final InstanceCreationExpression instanceCreation = - node.getAncestor((node) => node is InstanceCreationExpression); + node.thisOrAncestorOfType<InstanceCreationExpression>(); final InterfaceType type = instanceCreation.staticType; final generics = instanceCreation.constructorName.type.typeArguments; DartChangeBuilder changeBuilder = new DartChangeBuilder(session); @@ -3041,7 +2991,7 @@ // TODO(brianwilkerson) Determine whether this await is necessary. await null; FunctionExpression ancestor = - node.getAncestor((a) => a is FunctionExpression); + node.thisOrAncestorOfType<FunctionExpression>(); if (ancestor == null) { return; } @@ -3168,8 +3118,7 @@ new _ClosestElementFinder(name, predicate, MAX_LEVENSHTEIN_DISTANCE); // unqualified invocation if (target == null) { - ClassDeclaration clazz = - node.getAncestor((node) => node is ClassDeclaration); + ClassDeclaration clazz = node.thisOrAncestorOfType<ClassDeclaration>(); if (clazz != null) { ClassElement classElement = clazz.declaredElement; _updateFinderWithClassMembers(finder, classElement); @@ -3213,7 +3162,7 @@ int insertOffset; String sourcePrefix; AstNode enclosingMember = - node.getAncestor((node) => node is CompilationUnitMember); + node.thisOrAncestorOfType<CompilationUnitMember>(); insertOffset = enclosingMember.end; sourcePrefix = '$eol$eol'; utils.targetClassElement = null; @@ -3301,12 +3250,12 @@ Element targetElement; bool staticModifier = false; - ClassDeclaration targetClassNode; + ClassOrMixinDeclaration targetClassNode; Expression target = invocation.realTarget; + CorrectionUtils utils = this.utils; if (target == null) { - targetElement = unitElement; - ClassMember enclosingMember = - node.getAncestor((node) => node is ClassMember); + targetElement = unit.declaredElement; + ClassMember enclosingMember = node.thisOrAncestorOfType<ClassMember>(); if (enclosingMember == null) { // If the undefined identifier isn't inside a class member, then it // doesn't make sense to create a method. @@ -3327,11 +3276,10 @@ } targetElement = targetClassElement; // prepare target ClassDeclaration - AstNode targetTypeNode = getParsedClassElementNode(targetClassElement); - if (targetTypeNode is! ClassDeclaration) { + targetClassNode = await _getClassDeclaration(targetClassElement); + if (targetClassNode == null) { return; } - targetClassNode = targetTypeNode; // maybe static if (target is Identifier) { staticModifier = @@ -3339,10 +3287,9 @@ ElementKind.CLASS; } // use different utils - CompilationUnitElement targetUnitElement = - getCompilationUnitElement(targetClassElement); - CompilationUnit targetUnit = getParsedUnit(targetUnitElement); - utils = new CorrectionUtils(targetUnit); + var targetPath = targetClassElement.source.fullName; + var targetResolveResult = await session.getResolvedUnit(targetPath); + utils = CorrectionUtils(targetResolveResult); } ClassMemberLocation targetLocation = utils.prepareNewMethodLocation(targetClassNode); @@ -3392,22 +3339,6 @@ } } - Future<void> _addFix_undefinedMethodWithContructor() async { - // TODO(brianwilkerson) Determine whether this await is necessary. - await null; - if (node is SimpleIdentifier && node.parent is MethodInvocation) { - DartChangeBuilder changeBuilder = new DartChangeBuilder(session); - await changeBuilder.addFileEdit(file, (DartFileEditBuilder builder) { - builder.addSimpleInsertion(node.parent.offset, 'new '); - }); - _addFixFromBuilder( - changeBuilder, DartFixKind.INVOKE_CONSTRUCTOR_USING_NEW); - // TODO(brianwilkerson) Figure out whether the constructor is a `const` - // constructor and all of the parameters are constant expressions, and - // suggest inserting 'const ' if so. - } - } - /** * Here we handle cases when a constructors does not initialize all of the * final fields. @@ -3474,6 +3405,53 @@ _addFixFromBuilder(changeBuilder, DartFixKind.ADD_FIELD_FORMAL_PARAMETERS); } + Future<void> _addFix_updateSdkConstraints() async { + Context context = resourceProvider.pathContext; + File pubspecFile = null; + Folder folder = resourceProvider.getFolder(context.dirname(file)); + while (folder != null) { + pubspecFile = folder.getChildAssumingFile('pubspec.yaml'); + if (pubspecFile.exists) { + break; + } + pubspecFile = null; + folder = folder.parent; + } + if (pubspecFile == null) { + return; + } + SdkConstraintExtractor extractor = new SdkConstraintExtractor(pubspecFile); + String text = extractor.constraintText(); + int offset = extractor.constraintOffset(); + int length = text.length; + if (text == null || offset < 0) { + return; + } + String newText; + int spaceOffset = text.indexOf(' '); + if (spaceOffset >= 0) { + length = spaceOffset; + } + if (text == 'any') { + newText = '^2.1.0'; + } else if (text.startsWith('^')) { + newText = '^2.1.0'; + } else if (text.startsWith('>=')) { + newText = '>=2.1.0'; + } else if (text.startsWith('>')) { + newText = '>=2.1.0'; + } + if (newText == null) { + return; + } + DartChangeBuilder changeBuilder = new DartChangeBuilder(session); + await changeBuilder.addFileEdit(pubspecFile.path, + (DartFileEditBuilder builder) { + builder.addSimpleReplacement(new SourceRange(offset, length), newText); + }); + _addFixFromBuilder(changeBuilder, DartFixKind.UPDATE_SDK_CONSTRAINTS); + } + Future<void> _addFix_useEffectiveIntegerDivision() async { // TODO(brianwilkerson) Determine whether this await is necessary. await null; @@ -3564,7 +3542,7 @@ Future<DartChangeBuilder> _addProposal_createFunction( FunctionType functionType, String name, - Source targetSource, + String targetFile, int insertOffset, bool isStatic, String prefix, @@ -3574,7 +3552,6 @@ // TODO(brianwilkerson) Determine whether this await is necessary. await null; // build method source - String targetFile = targetSource.fullName; DartChangeBuilder changeBuilder = new DartChangeBuilder(session); await changeBuilder.addFileEdit(targetFile, (DartFileEditBuilder builder) { builder.addInsertion(insertOffset, (DartEditBuilder builder) { @@ -3622,7 +3599,7 @@ builder.write(' {$eol$prefix}'); builder.write(sourceSuffix); }); - if (targetSource == unitSource) { + if (targetFile == file) { builder.addLinkedPosition(range.node(node), 'NAME'); } }); @@ -3647,13 +3624,13 @@ DartChangeBuilder changeBuilder = await _addProposal_createFunction( functionType, name, - unitSource, + file, insertOffset, false, prefix, sourcePrefix, sourceSuffix, - unitElement); + unit.declaredElement); _addFixFromBuilder(changeBuilder, DartFixKind.CREATE_FUNCTION, args: [name]); } @@ -3670,13 +3647,15 @@ // prepare environment Source targetSource = targetClassElement.source; // prepare insert offset - ClassDeclaration targetClassNode = - getParsedClassElementNode(targetClassElement); - int insertOffset = targetClassNode.end - 1; + var targetNode = await _getClassDeclaration(targetClassElement); + if (targetNode == null) { + return; + } + int insertOffset = targetNode.end - 1; // prepare prefix String prefix = ' '; String sourcePrefix; - if (targetClassNode.members.isEmpty) { + if (targetNode.members.isEmpty) { sourcePrefix = ''; } else { sourcePrefix = eol; @@ -3685,7 +3664,7 @@ DartChangeBuilder changeBuilder = await _addProposal_createFunction( functionType, name, - targetSource, + targetSource.fullName, insertOffset, _inStaticContext(), prefix, @@ -3696,48 +3675,15 @@ } /** - * Computes the name of the library at the given [path]. - * See https://www.dartlang.org/articles/style-guide/#names for conventions. + * Returns the [ClassOrMixinDeclaration] for the given [element]. */ - String _computeLibraryName(String path) { - Context pathContext = resourceProvider.pathContext; - String packageFolder = _computePackageFolder(path); - if (packageFolder == null) { - return pathContext.basenameWithoutExtension(path); + Future<ClassOrMixinDeclaration> _getClassDeclaration( + ClassElement element) async { + var result = await sessionHelper.getElementDeclaration(element); + if (result.node is ClassOrMixinDeclaration) { + return result.node; } - String packageName = pathContext.basename(packageFolder); - String relPath = pathContext.relative(path, from: packageFolder); - List<String> relPathParts = pathContext.split(relPath); - if (relPathParts.isNotEmpty) { - if (relPathParts[0].toLowerCase() == 'lib') { - relPathParts.removeAt(0); - } - if (relPathParts.isNotEmpty) { - String nameWithoutExt = pathContext.withoutExtension(relPathParts.last); - relPathParts[relPathParts.length - 1] = nameWithoutExt; - } - } - return packageName + '.' + relPathParts.join('.'); - } - - /** - * Returns the path of the folder which contains the given [path]. - */ - String _computePackageFolder(String path) { - Context pathContext = resourceProvider.pathContext; - String pubspecFolder = dirname(path); - while (true) { - if (resourceProvider - .getResource(pathContext.join(pubspecFolder, 'pubspec.yaml')) - .exists) { - return pubspecFolder; - } - String pubspecFolderNew = pathContext.dirname(pubspecFolder); - if (pubspecFolderNew == pubspecFolder) { - return null; - } - pubspecFolder = pubspecFolderNew; - } + return null; } /** @@ -3774,26 +3720,6 @@ } /** - * Return the correction utilities that should be used when creating an edit - * in the compilation unit containing the given [node]. - */ - CorrectionUtils _getUtilsFor(AstNode node) { - CompilationUnit targetUnit = - node.getAncestor((node) => node is CompilationUnit); - CompilationUnitElement targetUnitElement = targetUnit?.declaredElement; - CorrectionUtils realUtils = utils; - if (targetUnitElement != utils.unit.declaredElement) { - realUtils = new CorrectionUtils(targetUnit); - ClassDeclaration targetClass = - node.getAncestor((node) => node is ClassDeclaration); - if (targetClass != null) { - realUtils.targetClassElement = targetClass.declaredElement; - } - } - return realUtils; - } - - /** * Returns an expected [DartType] of [expression], may be `null` if cannot be * inferred. */ @@ -3924,17 +3850,15 @@ */ bool _inStaticContext() { // constructor initializer cannot reference "this" - if (node.getAncestor((node) => node is ConstructorInitializer) != null) { + if (node.thisOrAncestorOfType<ConstructorInitializer>() != null) { return true; } // field initializer cannot reference "this" - if (node.getAncestor((node) => node is FieldDeclaration) != null) { + if (node.thisOrAncestorOfType<FieldDeclaration>() != null) { return true; } // static method - MethodDeclaration method = node.getAncestor((node) { - return node is MethodDeclaration; - }); + MethodDeclaration method = node.thisOrAncestorOfType<MethodDeclaration>(); return method != null && method.isStatic; } @@ -3999,24 +3923,24 @@ } /** - * Return `true` if the [source] can be imported into [unitLibraryFile]. + * Return `true` if the [source] can be imported into current library. */ bool _isSourceVisibleToLibrary(Source source) { String path = source.fullName; - ContextRoot contextRoot = driver.contextRoot; + var contextRoot = context.resolveResult.session.analysisContext.contextRoot; if (contextRoot == null) { return true; } // We don't want to use private libraries of other packages. if (source.uri.isScheme('package') && _isLibSrcPath(path)) { - return resourceProvider.pathContext.isWithin(contextRoot.root, path); + return contextRoot.root.contains(path); } // We cannot use relative URIs to reference files outside of our package. if (source.uri.isScheme('file')) { - return resourceProvider.pathContext.isWithin(contextRoot.root, path); + return contextRoot.root.contains(path); } return true; @@ -4181,14 +4105,15 @@ * [ExecutableElement], its parameters, and operations on them. */ class _ExecutableParameters { - final AstProvider astProvider; + final AnalysisSessionHelper sessionHelper; final ExecutableElement executable; final List<ParameterElement> required = []; final List<ParameterElement> optionalPositional = []; final List<ParameterElement> named = []; - factory _ExecutableParameters(AstProvider astProvider, AstNode invocation) { + factory _ExecutableParameters( + AnalysisSessionHelper sessionHelper, AstNode invocation) { Element element; if (invocation is InstanceCreationExpression) { element = invocation.staticElement; @@ -4196,14 +4121,14 @@ if (invocation is MethodInvocation) { element = invocation.methodName.staticElement; } - if (element is ExecutableElement) { - return new _ExecutableParameters._(astProvider, element); + if (element is ExecutableElement && !element.isSynthetic) { + return new _ExecutableParameters._(sessionHelper, element); } else { return null; } } - _ExecutableParameters._(this.astProvider, this.executable) { + _ExecutableParameters._(this.sessionHelper, this.executable) { for (var parameter in executable.parameters) { if (parameter.isNotOptional) { required.add(parameter); @@ -4222,10 +4147,8 @@ * be found. */ Future<FormalParameterList> getParameterList() async { - // TODO(brianwilkerson) Determine whether this await is necessary. - await null; - var name = await astProvider.getParsedNameForElement(executable); - AstNode targetDeclaration = name?.parent; + var result = await sessionHelper.getElementDeclaration(executable); + var targetDeclaration = result.node; if (targetDeclaration is ConstructorDeclaration) { return targetDeclaration.parameters; } else if (targetDeclaration is FunctionDeclaration) { @@ -4242,10 +4165,9 @@ * or `null` is cannot be found. */ Future<FormalParameter> getParameterNode(ParameterElement element) async { - // TODO(brianwilkerson) Determine whether this await is necessary. - await null; - var name = await astProvider.getParsedNameForElement(element); - for (AstNode node = name; node != null; node = node.parent) { + var result = await sessionHelper.getElementDeclaration(element); + var declaration = result.node; + for (AstNode node = declaration; node != null; node = node.parent) { if (node is FormalParameter && node.parent is FormalParameterList) { return node; }
diff --git a/pkg/analysis_server/lib/src/services/correction/name_suggestion.dart b/pkg/analysis_server/lib/src/services/correction/name_suggestion.dart index 46fa120..e8da43f 100644 --- a/pkg/analysis_server/lib/src/services/correction/name_suggestion.dart +++ b/pkg/analysis_server/lib/src/services/correction/name_suggestion.dart
@@ -1,4 +1,4 @@ -// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file +// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. @@ -8,7 +8,7 @@ import 'package:analyzer/dart/element/type.dart'; import 'package:analyzer_plugin/src/utilities/string_utilities.dart'; -List<String> _KNOWN_METHOD_NAME_PREFIXES = ['get', 'is', 'to']; +final List<String> _KNOWN_METHOD_NAME_PREFIXES = ['get', 'is', 'to']; /** * Returns all variants of names by removing leading words one by one. @@ -37,7 +37,7 @@ if (isMethod) { // If we're in a build() method, use 'build' as the name prefix. MethodDeclaration method = - assignedExpression.getAncestor((n) => n is MethodDeclaration); + assignedExpression.thisOrAncestorOfType<MethodDeclaration>(); if (method != null) { String enclosingName = method.name?.name; if (enclosingName != null && enclosingName.startsWith('build')) {
diff --git a/pkg/analysis_server/lib/src/services/correction/namespace.dart b/pkg/analysis_server/lib/src/services/correction/namespace.dart index 1419922..a3bdd84 100644 --- a/pkg/analysis_server/lib/src/services/correction/namespace.dart +++ b/pkg/analysis_server/lib/src/services/correction/namespace.dart
@@ -1,4 +1,4 @@ -// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file +// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. @@ -18,15 +18,6 @@ } /** - * Returns the namespace of the given [ExportElement]. - */ -Map<String, Element> getExportNamespaceForDirective(ExportElement exp) { - Namespace namespace = - new NamespaceBuilder().createExportNamespaceForDirective(exp); - return namespace.definedNames; -} - -/** * Returns the export namespace of the given [LibraryElement]. */ Map<String, Element> getExportNamespaceForLibrary(LibraryElement library) { @@ -45,8 +36,7 @@ if (parent is ImportDirective) { return parent.element; } - ImportElementInfo info = internal_getImportElementInfo(prefixNode); - return info?.element; + return internal_getImportElementInfo(prefixNode); } /** @@ -130,15 +120,13 @@ } /** - * Returns the [ImportElementInfo] with the [ImportElement] that is referenced - * by [prefixNode] with a [PrefixElement], maybe `null`. + * Returns the [ImportElement] that is referenced by [prefixNode] with a + * [PrefixElement], maybe `null`. */ -ImportElementInfo internal_getImportElementInfo(SimpleIdentifier prefixNode) { - ImportElementInfo info = new ImportElementInfo(); +ImportElement internal_getImportElementInfo(SimpleIdentifier prefixNode) { // prepare environment AstNode parent = prefixNode.parent; - CompilationUnit unit = - prefixNode.getAncestor((node) => node is CompilationUnit); + CompilationUnit unit = prefixNode.thisOrAncestorOfType<CompilationUnit>(); LibraryElement libraryElement = resolutionMap.elementDeclaredByCompilationUnit(unit).library; // prepare used element @@ -147,14 +135,12 @@ PrefixedIdentifier prefixed = parent; if (prefixed.prefix == prefixNode) { usedElement = prefixed.staticElement; - info.periodEnd = prefixed.period.end; } } if (parent is MethodInvocation) { MethodInvocation invocation = parent; if (invocation.target == prefixNode) { usedElement = invocation.methodName.staticElement; - info.periodEnd = invocation.operator.end; } } // we need used Element @@ -164,12 +150,8 @@ // find ImportElement String prefix = prefixNode.name; Map<ImportElement, Set<Element>> importElementsMap = {}; - info.element = internal_getImportElement( + return internal_getImportElement( libraryElement, prefix, usedElement, importElementsMap); - if (info.element == null) { - return null; - } - return info; } /** @@ -178,5 +160,4 @@ */ class ImportElementInfo { ImportElement element; - int periodEnd; }
diff --git a/pkg/analysis_server/lib/src/services/correction/selection_analyzer.dart b/pkg/analysis_server/lib/src/services/correction/selection_analyzer.dart index 9b026bd..3b9b505 100644 --- a/pkg/analysis_server/lib/src/services/correction/selection_analyzer.dart +++ b/pkg/analysis_server/lib/src/services/correction/selection_analyzer.dart
@@ -1,4 +1,4 @@ -// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file +// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. @@ -10,7 +10,7 @@ /** * A visitor for visiting [AstNode]s covered by a selection [SourceRange]. */ -class SelectionAnalyzer extends GeneralizingAstVisitor<Object> { +class SelectionAnalyzer extends GeneralizingAstVisitor<void> { final SourceRange selection; AstNode _coveringNode; @@ -57,19 +57,6 @@ } /** - * Returns the [SourceRange] which covers selected [AstNode]s, may be `null` - * if there are no [AstNode]s under the selection. - */ - SourceRange get selectedNodeRange { - if (_selectedNodes == null || _selectedNodes.isEmpty) { - return null; - } - AstNode firstNode = _selectedNodes[0]; - AstNode lastNode = _selectedNodes[_selectedNodes.length - 1]; - return range.startEnd(firstNode, lastNode); - } - - /** * Return the [AstNode]s fully covered by the selection [SourceRange]. */ List<AstNode> get selectedNodes { @@ -114,7 +101,7 @@ } @override - Object visitNode(AstNode node) { + void visitNode(AstNode node) { SourceRange nodeRange = range.node(node); if (selection.covers(nodeRange)) { if (isFirstNode) { @@ -122,21 +109,20 @@ } else { handleNextSelectedNode(node); } - return null; + return; } else if (selection.coveredBy(nodeRange)) { _coveringNode = node; node.visitChildren(this); - return null; + return; } else if (selection.startsIn(nodeRange)) { handleSelectionStartsIn(node); node.visitChildren(this); - return null; + return; } else if (selection.endsIn(nodeRange)) { handleSelectionEndsIn(node); node.visitChildren(this); - return null; + return; } // no intersection - return null; } }
diff --git a/pkg/analysis_server/lib/src/services/correction/sort_members.dart b/pkg/analysis_server/lib/src/services/correction/sort_members.dart index 1bd8aef8..04baf5f 100644 --- a/pkg/analysis_server/lib/src/services/correction/sort_members.dart +++ b/pkg/analysis_server/lib/src/services/correction/sort_members.dart
@@ -20,6 +20,8 @@ new _PriorityItem(false, _MemberKind.UNIT_ACCESSOR, true), new _PriorityItem(false, _MemberKind.UNIT_FUNCTION, false), new _PriorityItem(false, _MemberKind.UNIT_FUNCTION, true), + new _PriorityItem(false, _MemberKind.UNIT_GENERIC_TYPE_ALIAS, false), + new _PriorityItem(false, _MemberKind.UNIT_GENERIC_TYPE_ALIAS, true), new _PriorityItem(false, _MemberKind.UNIT_FUNCTION_TYPE, false), new _PriorityItem(false, _MemberKind.UNIT_FUNCTION_TYPE, true), new _PriorityItem(false, _MemberKind.UNIT_CLASS, false), @@ -83,21 +85,20 @@ } /** - * Sorts all members of all [ClassDeclaration]s. + * Sorts all members of all [ClassOrMixinDeclaration]s. */ void _sortClassesMembers() { for (CompilationUnitMember unitMember in unit.declarations) { - if (unitMember is ClassDeclaration) { - ClassDeclaration classDeclaration = unitMember; - _sortClassMembers(classDeclaration); + if (unitMember is ClassOrMixinDeclaration) { + _sortClassMembers(unitMember); } } } /** - * Sorts all members of the given [ClassDeclaration]. + * Sorts all members of the given [classDeclaration]. */ - void _sortClassMembers(ClassDeclaration classDeclaration) { + void _sortClassMembers(ClassOrMixinDeclaration classDeclaration) { List<_MemberInfo> members = <_MemberInfo>[]; for (ClassMember member in classDeclaration.members) { _MemberKind kind = null; @@ -272,7 +273,7 @@ for (CompilationUnitMember member in unit.declarations) { _MemberKind kind = null; String name = null; - if (member is ClassDeclaration) { + if (member is ClassOrMixinDeclaration) { kind = _MemberKind.UNIT_CLASS; name = member.name.name; } @@ -305,6 +306,10 @@ kind = _MemberKind.UNIT_FUNCTION_TYPE; name = member.name.name; } + if (member is GenericTypeAlias) { + kind = _MemberKind.UNIT_GENERIC_TYPE_ALIAS; + name = member.name.name; + } if (member is TopLevelVariableDeclaration) { TopLevelVariableDeclaration variableDeclaration = member; List<VariableDeclaration> variables = @@ -458,14 +463,16 @@ static const UNIT_FUNCTION_MAIN = const _MemberKind('UNIT_FUNCTION_MAIN', 0); static const UNIT_ACCESSOR = const _MemberKind('UNIT_ACCESSOR', 1); static const UNIT_FUNCTION = const _MemberKind('UNIT_FUNCTION', 2); - static const UNIT_FUNCTION_TYPE = const _MemberKind('UNIT_FUNCTION_TYPE', 3); - static const UNIT_CLASS = const _MemberKind('UNIT_CLASS', 4); - static const UNIT_VARIABLE_CONST = const _MemberKind('UNIT_VARIABLE', 5); - static const UNIT_VARIABLE = const _MemberKind('UNIT_VARIABLE', 6); - static const CLASS_ACCESSOR = const _MemberKind('CLASS_ACCESSOR', 7); - static const CLASS_CONSTRUCTOR = const _MemberKind('CLASS_CONSTRUCTOR', 8); - static const CLASS_FIELD = const _MemberKind('CLASS_FIELD', 9); - static const CLASS_METHOD = const _MemberKind('CLASS_METHOD', 10); + static const UNIT_GENERIC_TYPE_ALIAS = + const _MemberKind('UNIT_GENERIC_TYPE_ALIAS', 3); + static const UNIT_FUNCTION_TYPE = const _MemberKind('UNIT_FUNCTION_TYPE', 4); + static const UNIT_CLASS = const _MemberKind('UNIT_CLASS', 5); + static const UNIT_VARIABLE_CONST = const _MemberKind('UNIT_VARIABLE', 6); + static const UNIT_VARIABLE = const _MemberKind('UNIT_VARIABLE', 7); + static const CLASS_ACCESSOR = const _MemberKind('CLASS_ACCESSOR', 8); + static const CLASS_CONSTRUCTOR = const _MemberKind('CLASS_CONSTRUCTOR', 9); + static const CLASS_FIELD = const _MemberKind('CLASS_FIELD', 10); + static const CLASS_METHOD = const _MemberKind('CLASS_METHOD', 11); final String name; final int ordinal;
diff --git a/pkg/analysis_server/lib/src/services/correction/source_buffer.dart b/pkg/analysis_server/lib/src/services/correction/source_buffer.dart index 24d6848..a414cd5 100644 --- a/pkg/analysis_server/lib/src/services/correction/source_buffer.dart +++ b/pkg/analysis_server/lib/src/services/correction/source_buffer.dart
@@ -2,9 +2,6 @@ // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. -import 'package:analyzer/src/generated/source.dart'; -import 'package:analyzer_plugin/protocol/protocol_common.dart'; - /** * Helper for building Dart source with linked positions. */ @@ -13,18 +10,10 @@ final int offset; final StringBuffer _buffer = new StringBuffer(); - final Map<String, LinkedEditGroup> linkedPositionGroups = - <String, LinkedEditGroup>{}; - LinkedEditGroup _currentLinkedPositionGroup; - int _currentPositionStart; int _exitOffset; SourceBuilder(this.file, this.offset); - SourceBuilder.buffer() - : file = null, - offset = 0; - /** * Returns the exit offset, maybe `null` if not set. */ @@ -37,15 +26,6 @@ int get length => _buffer.length; - void addSuggestion(LinkedEditSuggestionKind kind, String value) { - var suggestion = new LinkedEditSuggestion(value, kind); - _currentLinkedPositionGroup.addSuggestion(suggestion); - } - - void addSuggestions(LinkedEditSuggestionKind kind, List<String> values) { - values.forEach((value) => addSuggestion(kind, value)); - } - /** * Appends [s] to the buffer. */ @@ -55,45 +35,12 @@ } /** - * Ends position started using [startPosition]. - */ - void endPosition() { - assert(_currentLinkedPositionGroup != null); - _addPosition(); - _currentLinkedPositionGroup = null; - } - - /** * Marks the current offset as an "exit" one. */ void setExitOffset() { _exitOffset = _buffer.length; } - /** - * Marks start of a new linked position for the group with the given ID. - */ - void startPosition(String id) { - assert(_currentLinkedPositionGroup == null); - _currentLinkedPositionGroup = linkedPositionGroups[id]; - if (_currentLinkedPositionGroup == null) { - _currentLinkedPositionGroup = new LinkedEditGroup.empty(); - linkedPositionGroups[id] = _currentLinkedPositionGroup; - } - _currentPositionStart = _buffer.length; - } - @override String toString() => _buffer.toString(); - - /** - * Adds position location [SourceRange] using current fields. - */ - void _addPosition() { - int start = offset + _currentPositionStart; - int end = offset + _buffer.length; - int length = end - start; - Position position = new Position(file, start); - _currentLinkedPositionGroup.addPosition(position, length); - } }
diff --git a/pkg/analysis_server/lib/src/services/correction/statement_analyzer.dart b/pkg/analysis_server/lib/src/services/correction/statement_analyzer.dart index 3a5b1af..db39ca8 100644 --- a/pkg/analysis_server/lib/src/services/correction/statement_analyzer.dart +++ b/pkg/analysis_server/lib/src/services/correction/statement_analyzer.dart
@@ -6,9 +6,9 @@ import 'package:analysis_server/src/services/correction/selection_analyzer.dart'; import 'package:analysis_server/src/services/correction/status.dart'; import 'package:analysis_server/src/services/correction/util.dart'; +import 'package:analyzer/dart/analysis/results.dart'; import 'package:analyzer/dart/ast/ast.dart'; import 'package:analyzer/dart/ast/token.dart'; -import 'package:analyzer/dart/element/element.dart'; import 'package:analyzer/src/dart/scanner/reader.dart'; import 'package:analyzer/src/dart/scanner/scanner.dart'; import 'package:analyzer/src/generated/source.dart'; @@ -37,11 +37,12 @@ * Analyzer to check if a selection covers a valid set of statements of AST. */ class StatementAnalyzer extends SelectionAnalyzer { - final CompilationUnit unit; + final ResolvedUnitResult resolveResult; final RefactoringStatus _status = new RefactoringStatus(); - StatementAnalyzer(this.unit, SourceRange selection) : super(selection); + StatementAnalyzer(this.resolveResult, SourceRange selection) + : super(selection); /** * Returns the [RefactoringStatus] result of selection checking. @@ -49,6 +50,13 @@ RefactoringStatus get status => _status; /** + * Analyze the selection, compute [status] and nodes. + */ + void analyze() { + resolveResult.unit.accept(this); + } + + /** * Records fatal error with given message and [Location]. */ void invalidSelection(String message, [Location context]) { @@ -68,7 +76,7 @@ { int selectionStart = selection.offset; int selectionEnd = selection.end; - List<SourceRange> commentRanges = getCommentRanges(unit); + List<SourceRange> commentRanges = getCommentRanges(resolveResult.unit); for (SourceRange commentRange in commentRanges) { if (commentRange.contains(selectionStart)) { invalidSelection("Selection begins inside a comment."); @@ -204,8 +212,7 @@ * Returns `true` if there are [Token]s in the given [SourceRange]. */ bool _hasTokens(SourceRange range) { - CompilationUnitElement unitElement = unit.declaredElement; - String fullText = unitElement.context.getContents(unitElement.source).data; + String fullText = resolveResult.content; String rangeText = fullText.substring(range.offset, range.end); return _getTokens(rangeText).isNotEmpty; }
diff --git a/pkg/analysis_server/lib/src/services/correction/strings.dart b/pkg/analysis_server/lib/src/services/correction/strings.dart index 33a4c6a..125fc14 100644 --- a/pkg/analysis_server/lib/src/services/correction/strings.dart +++ b/pkg/analysis_server/lib/src/services/correction/strings.dart
@@ -12,11 +12,6 @@ const int CHAR_DOLLAR = 0x24; /** - * "." - */ -const int CHAR_DOT = 0x2E; - -/** * "_" */ const int CHAR_UNDERSCORE = 0x5F; @@ -98,39 +93,6 @@ } /** - * Returns the number of characters common to the end of [a] and the start - * of [b]. - */ -int findCommonOverlap(String a, String b) { - int a_length = a.length; - int b_length = b.length; - // all empty - if (a_length == 0 || b_length == 0) { - return 0; - } - // truncate - if (a_length > b_length) { - a = a.substring(a_length - b_length); - } else if (a_length < b_length) { - b = b.substring(0, a_length); - } - int text_length = min(a_length, b_length); - // the worst case - if (a == b) { - return text_length; - } - // increase common length one by one - int length = 0; - while (length < text_length) { - if (a.codeUnitAt(text_length - 1 - length) != b.codeUnitAt(length)) { - break; - } - length++; - } - return length; -} - -/** * Return the number of characters common to the start of [a] and [b]. */ int findCommonPrefix(String a, String b) { @@ -193,13 +155,6 @@ return isSpace(c) || isEOL(c); } -String remove(String str, String remove) { - if (isEmpty(str) || isEmpty(remove)) { - return str; - } - return str.replaceAll(remove, ''); -} - String removeEnd(String str, String remove) { if (isEmpty(str) || isEmpty(remove)) { return str; @@ -233,24 +188,6 @@ } /** - * Gets the substring after the last occurrence of a separator. - * The separator is not returned. - */ -String substringAfterLast(String str, String separator) { - if (isEmpty(str)) { - return str; - } - if (isEmpty(separator)) { - return ''; - } - int pos = str.lastIndexOf(separator); - if (pos == -1) { - return str; - } - return str.substring(pos + separator.length); -} - -/** * Information about a single replacement that should be made to convert the * "old" string to the "new" one. */
diff --git a/pkg/analysis_server/lib/src/services/correction/util.dart b/pkg/analysis_server/lib/src/services/correction/util.dart index f517e04..9ea11e0 100644 --- a/pkg/analysis_server/lib/src/services/correction/util.dart +++ b/pkg/analysis_server/lib/src/services/correction/util.dart
@@ -1,4 +1,4 @@ -// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file +// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. @@ -7,6 +7,8 @@ import 'package:analysis_server/src/protocol_server.dart' show doSourceChange_addElementEdit; import 'package:analysis_server/src/services/correction/strings.dart'; +import 'package:analyzer/dart/analysis/results.dart'; +import 'package:analyzer/dart/analysis/session.dart'; import 'package:analyzer/dart/ast/ast.dart'; import 'package:analyzer/dart/ast/token.dart'; import 'package:analyzer/dart/ast/visitor.dart'; @@ -15,7 +17,6 @@ import 'package:analyzer/src/dart/ast/utilities.dart'; import 'package:analyzer/src/dart/scanner/reader.dart'; import 'package:analyzer/src/dart/scanner/scanner.dart'; -import 'package:analyzer/src/generated/engine.dart'; import 'package:analyzer/src/generated/source.dart'; import 'package:analyzer_plugin/protocol/protocol_common.dart' show SourceChange, SourceEdit; @@ -27,16 +28,11 @@ * Adds edits to the given [change] that ensure that all the [libraries] are * imported into the given [targetLibrary]. */ -void addLibraryImports(pathos.Context pathContext, SourceChange change, - LibraryElement targetLibrary, Set<Source> libraries) { - CorrectionUtils libUtils; - try { - CompilationUnitElement unitElement = targetLibrary.definingCompilationUnit; - CompilationUnit unitAst = getParsedUnit(unitElement); - libUtils = new CorrectionUtils(unitAst); - } catch (e) { - throw new CancelCorrectionException(exception: e); - } +Future<void> addLibraryImports(AnalysisSession session, SourceChange change, + LibraryElement targetLibrary, Set<Source> libraries) async { + var libraryPath = targetLibrary.source.fullName; + var resolveResult = await session.getResolvedUnit(libraryPath); + var libUtils = new CorrectionUtils(resolveResult); String eol = libUtils.endOfLine; // Prepare information about existing imports. LibraryDirective libraryDirective; @@ -46,14 +42,14 @@ libraryDirective = directive; } else if (directive is ImportDirective) { importDirectives.add(new _ImportDirectiveInfo( - directive.uriContent, directive.offset, directive.end)); + directive.uri.stringValue, directive.offset, directive.end)); } } // Prepare all URIs to import. List<String> uriList = libraries - .map((library) => - getLibrarySourceUri(pathContext, targetLibrary, library.uri)) + .map((library) => getLibrarySourceUri( + session.resourceProvider.pathContext, targetLibrary, library.uri)) .toList(); uriList.sort((a, b) => a.compareTo(b)); @@ -235,12 +231,12 @@ } /** - * If the given [AstNode] is in a [ClassDeclaration], returns the + * If the given [AstNode] is in a [ClassOrMixinDeclaration], returns the * [ClassElement]. Otherwise returns `null`. */ ClassElement getEnclosingClassElement(AstNode node) { - ClassDeclaration enclosingClassNode = - node.getAncestor((node) => node is ClassDeclaration); + ClassOrMixinDeclaration enclosingClassNode = + node.thisOrAncestorOfType<ClassOrMixinDeclaration>(); if (enclosingClassNode != null) { return enclosingClassNode.declaredElement; } @@ -470,40 +466,6 @@ } /** - * Returns a parsed [AstNode] for the given [classElement]. - * - * The resulting AST structure may or may not be resolved. - */ -AstNode getParsedClassElementNode(ClassElement classElement) { - CompilationUnitElement unitElement = getCompilationUnitElement(classElement); - CompilationUnit unit = getParsedUnit(unitElement); - int offset = classElement.nameOffset; - AstNode classNameNode = new NodeLocator(offset).searchWithin(unit); - if (classElement.isEnum) { - return classNameNode.getAncestor((node) => node is EnumDeclaration); - } else { - return classNameNode.getAncestor( - (node) => node is ClassDeclaration || node is ClassTypeAlias); - } -} - -/** - * Returns a parsed [CompilationUnit] for the given [unitElement]. - * - * The resulting AST structure may or may not be resolved. - * If it is not resolved, then at least the given [unitElement] will be set. - */ -CompilationUnit getParsedUnit(CompilationUnitElement unitElement) { - AnalysisContext context = unitElement.context; - Source source = unitElement.source; - CompilationUnit unit = context.parseCompilationUnit(source); - if (unit.declaredElement == null) { - unit.element = unitElement; - } - return unit; -} - -/** * If given [node] is name of qualified property extraction, returns target from * which this property is extracted, otherwise `null`. */ @@ -641,6 +603,8 @@ class CorrectionUtils { final CompilationUnit unit; + final LibraryElement _library; + final String _buffer; /** * The [ClassElement] the generated code is inserted to, so we can decide if @@ -650,19 +614,12 @@ ExecutableElement targetExecutableElement; - LibraryElement _library; - String _buffer; String _endOfLine; - CorrectionUtils(this.unit, {String buffer}) { - CompilationUnitElement unitElement = unit.declaredElement; - AnalysisContext context = unitElement.context; - if (context == null) { - throw new CancelCorrectionException(); - } - this._library = unitElement.library; - this._buffer = buffer ?? context.getContents(unitElement.source).data; - } + CorrectionUtils(ResolvedUnitResult result) + : unit = result.unit, + _library = result.libraryElement, + _buffer = result.content; /** * Returns the EOL to use for this [CompilationUnit]. @@ -690,7 +647,7 @@ Set<String> findPossibleLocalVariableConflicts(int offset) { Set<String> conflicts = new Set<String>(); AstNode enclosingNode = findNode(offset); - Block enclosingBlock = enclosingNode.getAncestor((node) => node is Block); + Block enclosingBlock = enclosingNode.thisOrAncestorOfType<Block>(); if (enclosingBlock != null) { _CollectReferencedUnprefixedNames visitor = new _CollectReferencedUnprefixedNames(); @@ -1091,7 +1048,7 @@ * Return `true` if the given [classDeclaration] has open '{' and close '}' * at the same line, e.g. `class X {}`. */ - bool isClassWithEmptyBody(ClassDeclaration classDeclaration) { + bool isClassWithEmptyBody(ClassOrMixinDeclaration classDeclaration) { return getLineThis(classDeclaration.leftBracket.offset) == getLineThis(classDeclaration.rightBracket.offset); } @@ -1110,7 +1067,7 @@ } ClassMemberLocation prepareNewClassMemberLocation( - ClassDeclaration classDeclaration, + ClassOrMixinDeclaration classDeclaration, bool shouldSkip(ClassMember existingMember)) { String indent = getIndent(1); // Find the last target member. @@ -1145,13 +1102,13 @@ } ClassMemberLocation prepareNewFieldLocation( - ClassDeclaration classDeclaration) { + ClassOrMixinDeclaration classDeclaration) { return prepareNewClassMemberLocation( classDeclaration, (member) => member is FieldDeclaration); } ClassMemberLocation prepareNewGetterLocation( - ClassDeclaration classDeclaration) { + ClassOrMixinDeclaration classDeclaration) { return prepareNewClassMemberLocation( classDeclaration, (member) => @@ -1161,7 +1118,7 @@ } ClassMemberLocation prepareNewMethodLocation( - ClassDeclaration classDeclaration) { + ClassOrMixinDeclaration classDeclaration) { return prepareNewClassMemberLocation( classDeclaration, (member) =>
diff --git a/pkg/analysis_server/lib/src/services/kythe/kythe_visitors.dart b/pkg/analysis_server/lib/src/services/kythe/kythe_visitors.dart index 23c804b..24d7722 100644 --- a/pkg/analysis_server/lib/src/services/kythe/kythe_visitors.dart +++ b/pkg/analysis_server/lib/src/services/kythe/kythe_visitors.dart
@@ -1,4 +1,4 @@ -// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file +// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. @@ -14,8 +14,8 @@ import 'package:analyzer/dart/element/visitor.dart'; import 'package:analyzer/file_system/file_system.dart'; import 'package:analyzer/src/dart/element/inheritance_manager2.dart'; -import 'package:analyzer/src/generated/bazel.dart'; -import 'package:analyzer/src/generated/gn.dart'; +import 'package:analyzer/src/workspace/bazel.dart'; +import 'package:analyzer/src/workspace/gn.dart'; import 'package:analyzer_plugin/protocol/protocol_common.dart' show KytheEntry, KytheVName; @@ -803,7 +803,7 @@ // Most simple identifiers are "ref" edges. In cases some cases, there may // be other ref/* edges. - if (node.getAncestor((node) => node is CommentReference) != null) { + if (node.thisOrAncestorOfType<CommentReference>() != null) { // The identifier is in a comment, add just the "ref" edge. _handleRefEdge( node.staticElement, @@ -1106,7 +1106,7 @@ /// This class is meant to be a mixin to concrete visitor methods to walk the /// [Element] or [AstNode]s produced by the Dart Analyzer to output Kythe /// [KytheEntry] protos. -abstract class OutputUtils { +mixin OutputUtils { /// A set of [String]s which have already had a name [KytheVName] created. final Set<String> nameNodes = new Set<String>();
diff --git a/pkg/analysis_server/lib/src/services/refactoring/convert_getter_to_method.dart b/pkg/analysis_server/lib/src/services/refactoring/convert_getter_to_method.dart index 61dd338..94010f7 100644 --- a/pkg/analysis_server/lib/src/services/refactoring/convert_getter_to_method.dart +++ b/pkg/analysis_server/lib/src/services/refactoring/convert_getter_to_method.dart
@@ -10,10 +10,11 @@ import 'package:analysis_server/src/services/refactoring/refactoring_internal.dart'; import 'package:analysis_server/src/services/search/hierarchy.dart'; import 'package:analysis_server/src/services/search/search_engine.dart'; +import 'package:analyzer/dart/analysis/session.dart'; import 'package:analyzer/dart/ast/ast.dart'; import 'package:analyzer/dart/ast/token.dart'; import 'package:analyzer/dart/element/element.dart'; -import 'package:analyzer/src/dart/element/ast_provider.dart'; +import 'package:analyzer/src/dart/analysis/session_helper.dart'; import 'package:analyzer/src/generated/source.dart'; import 'package:analyzer_plugin/utilities/range_factory.dart'; @@ -23,13 +24,13 @@ class ConvertGetterToMethodRefactoringImpl extends RefactoringImpl implements ConvertGetterToMethodRefactoring { final SearchEngine searchEngine; - final AstProvider astProvider; + final AnalysisSession session; final PropertyAccessorElement element; SourceChange change; ConvertGetterToMethodRefactoringImpl( - this.searchEngine, this.astProvider, this.element); + this.searchEngine, this.session, this.element); @override String get refactoringName => 'Convert Getter To Method'; @@ -92,8 +93,9 @@ // prepare "get" keyword Token getKeyword = null; { - AstNode name = await astProvider.getParsedNameForElement(element); - AstNode declaration = name?.parent; + var sessionHelper = AnalysisSessionHelper(session); + var result = await sessionHelper.getElementDeclaration(element); + var declaration = result.node; if (declaration is MethodDeclaration) { getKeyword = declaration.propertyKeyword; } else if (declaration is FunctionDeclaration) {
diff --git a/pkg/analysis_server/lib/src/services/refactoring/convert_method_to_getter.dart b/pkg/analysis_server/lib/src/services/refactoring/convert_method_to_getter.dart index 4f38b26..e7bc247 100644 --- a/pkg/analysis_server/lib/src/services/refactoring/convert_method_to_getter.dart +++ b/pkg/analysis_server/lib/src/services/refactoring/convert_method_to_getter.dart
@@ -1,4 +1,4 @@ -// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file +// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. @@ -12,8 +12,8 @@ import 'package:analysis_server/src/services/search/search_engine.dart'; import 'package:analyzer/dart/ast/ast.dart'; import 'package:analyzer/dart/element/element.dart'; +import 'package:analyzer/src/dart/analysis/session_helper.dart'; import 'package:analyzer/src/dart/ast/utilities.dart'; -import 'package:analyzer/src/dart/element/ast_provider.dart'; import 'package:analyzer/src/generated/source.dart'; import 'package:analyzer_plugin/utilities/range_factory.dart'; @@ -23,13 +23,13 @@ class ConvertMethodToGetterRefactoringImpl extends RefactoringImpl implements ConvertMethodToGetterRefactoring { final SearchEngine searchEngine; - final AstProvider astProvider; + final AnalysisSessionHelper sessionHelper; final ExecutableElement element; SourceChange change; - ConvertMethodToGetterRefactoringImpl( - this.searchEngine, this.astProvider, this.element); + ConvertMethodToGetterRefactoringImpl(this.searchEngine, this.element) + : sessionHelper = AnalysisSessionHelper(element.session); @override String get refactoringName => 'Convert Method To Getter'; @@ -100,8 +100,8 @@ // prepare parameters FormalParameterList parameters; { - AstNode name = await astProvider.getParsedNameForElement(element); - AstNode declaration = name?.parent; + var result = await sessionHelper.getElementDeclaration(element); + var declaration = result.node; if (declaration is MethodDeclaration) { parameters = declaration.parameters; } else if (declaration is FunctionDeclaration) { @@ -133,11 +133,11 @@ // prepare invocation MethodInvocation invocation; { - CompilationUnit refUnit = - await astProvider.getParsedUnitForElement(refElement); - AstNode refNode = - new NodeLocator(refRange.offset).searchWithin(refUnit); - invocation = refNode.getAncestor((node) => node is MethodInvocation); + var resolvedUnit = + await sessionHelper.getResolvedUnitByElement(refElement); + var refUnit = resolvedUnit.unit; + var refNode = new NodeLocator(refRange.offset).searchWithin(refUnit); + invocation = refNode.thisOrAncestorOfType<MethodInvocation>(); } // we need invocation if (invocation != null) {
diff --git a/pkg/analysis_server/lib/src/services/refactoring/extract_local.dart b/pkg/analysis_server/lib/src/services/refactoring/extract_local.dart index cf9cd10..d8e0c05 100644 --- a/pkg/analysis_server/lib/src/services/refactoring/extract_local.dart +++ b/pkg/analysis_server/lib/src/services/refactoring/extract_local.dart
@@ -1,4 +1,4 @@ -// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file +// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. @@ -31,7 +31,7 @@ */ class ExtractLocalRefactoringImpl extends RefactoringImpl implements ExtractLocalRefactoring { - final ResolveResult resolveResult; + final ResolvedUnitResult resolveResult; final int selectionOffset; final int selectionLength; SourceRange selectionRange; @@ -56,7 +56,7 @@ ExtractLocalRefactoringImpl( this.resolveResult, this.selectionOffset, this.selectionLength) { selectionRange = new SourceRange(selectionOffset, selectionLength); - utils = new CorrectionUtils(unit, buffer: resolveResult.content); + utils = new CorrectionUtils(resolveResult); } String get file => resolveResult.path; @@ -319,7 +319,7 @@ // into this block. If it has an expression body, we can convert it into // the block body first. if (coveringNode == null || - coveringNode.getAncestor((node) => node is FunctionBody) == null) { + coveringNode.thisOrAncestorOfType<FunctionBody>() == null) { return new RefactoringStatus.fatal( 'An expression inside a function must be selected ' 'to activate this refactoring.'); @@ -414,7 +414,7 @@ return expressionBody; } // single Statement - AstNode target = commonParent.getAncestor((node) => node is Statement); + AstNode target = commonParent.thisOrAncestorOfType<Statement>(); while (target.parent is! Block) { target = target.parent; } @@ -601,7 +601,7 @@ } } -class _OccurrencesVisitor extends GeneralizingAstVisitor<Object> { +class _OccurrencesVisitor extends GeneralizingAstVisitor<void> { final ExtractLocalRefactoringImpl ref; final List<SourceRange> occurrences; final String selectionSource; @@ -609,24 +609,24 @@ _OccurrencesVisitor(this.ref, this.occurrences, this.selectionSource); @override - Object visitBinaryExpression(BinaryExpression node) { + void visitBinaryExpression(BinaryExpression node) { if (!_hasStatements(node)) { _tryToFindOccurrenceFragments(node); - return null; + return; } - return super.visitBinaryExpression(node); + super.visitBinaryExpression(node); } @override - Object visitExpression(Expression node) { + void visitExpression(Expression node) { if (ref._isExtractable(range.node(node))) { _tryToFindOccurrence(node); } - return super.visitExpression(node); + super.visitExpression(node); } @override - Object visitStringLiteral(StringLiteral node) { + void visitStringLiteral(StringLiteral node) { if (ref.stringLiteralPart != null) { int length = ref.stringLiteralPart.length; String value = ref.utils.getNodeText(node); @@ -641,9 +641,9 @@ SourceRange range = new SourceRange(start, length); occurrences.add(range); } - return null; + return; } - return visitExpression(node); + visitExpression(node); } void _addOccurrence(SourceRange range) {
diff --git a/pkg/analysis_server/lib/src/services/refactoring/extract_method.dart b/pkg/analysis_server/lib/src/services/refactoring/extract_method.dart index 6969c41..bce5382 100644 --- a/pkg/analysis_server/lib/src/services/refactoring/extract_method.dart +++ b/pkg/analysis_server/lib/src/services/refactoring/extract_method.dart
@@ -1,4 +1,4 @@ -// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file +// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. @@ -23,8 +23,8 @@ import 'package:analyzer/dart/ast/visitor.dart'; import 'package:analyzer/dart/element/element.dart'; import 'package:analyzer/dart/element/type.dart'; +import 'package:analyzer/src/dart/analysis/session_helper.dart'; import 'package:analyzer/src/dart/ast/utilities.dart'; -import 'package:analyzer/src/dart/element/ast_provider.dart'; import 'package:analyzer/src/generated/java_core.dart'; import 'package:analyzer/src/generated/resolver.dart' show ExitDetector; import 'package:analyzer/src/generated/resolver.dart'; @@ -74,8 +74,7 @@ 'execution flows exit. Semantics may not be preserved.'; final SearchEngine searchEngine; - final AstProvider astProvider; - final ResolveResult resolveResult; + final ResolvedUnitResult resolveResult; final int selectionOffset; final int selectionLength; SourceRange selectionRange; @@ -119,11 +118,10 @@ List<_Occurrence> _occurrences = []; bool _staticContext = false; - ExtractMethodRefactoringImpl(this.searchEngine, this.astProvider, - this.resolveResult, this.selectionOffset, this.selectionLength) { + ExtractMethodRefactoringImpl(this.searchEngine, this.resolveResult, + this.selectionOffset, this.selectionLength) { selectionRange = new SourceRange(selectionOffset, selectionLength); - utils = - new CorrectionUtils(resolveResult.unit, buffer: resolveResult.content); + utils = new CorrectionUtils(resolveResult); } @override @@ -138,8 +136,7 @@ String get refactoringName { AstNode node = new NodeLocator(selectionOffset).searchWithin(resolveResult.unit); - if (node != null && - node.getAncestor((node) => node is ClassDeclaration) != null) { + if (node != null && node.thisOrAncestorOfType<ClassDeclaration>() != null) { return 'Extract Method'; } return 'Extract Function'; @@ -394,8 +391,8 @@ } } // done - addLibraryImports(resolveResult.session.resourceProvider.pathContext, - change, resolveResult.libraryElement, librariesToImport); + await addLibraryImports(resolveResult.session, change, + resolveResult.libraryElement, librariesToImport); return change; } @@ -454,8 +451,8 @@ // method of class if (parent is ClassDeclaration) { ClassElement classElement = parent.declaredElement; - return validateCreateMethod( - searchEngine, astProvider, classElement, name); + return validateCreateMethod(searchEngine, + AnalysisSessionHelper(resolveResult.session), classElement, name); } // OK return new Future<RefactoringStatus>.value(result); @@ -477,23 +474,20 @@ } } - _ExtractMethodAnalyzer selectionAnalyzer = - new _ExtractMethodAnalyzer(resolveResult.unit, selectionRange); - resolveResult.unit.accept(selectionAnalyzer); + var analyzer = new _ExtractMethodAnalyzer(resolveResult, selectionRange); + analyzer.analyze(); // May be a fatal error. { - if (selectionAnalyzer.status.hasFatalError) { - return selectionAnalyzer.status; + if (analyzer.status.hasFatalError) { + return analyzer.status; } } - List<AstNode> selectedNodes = selectionAnalyzer.selectedNodes; + List<AstNode> selectedNodes = analyzer.selectedNodes; // If no selected nodes, extract the smallest covering expression. if (selectedNodes.isEmpty) { - for (var node = selectionAnalyzer.coveringNode; - node != null; - node = node.parent) { + for (var node = analyzer.coveringNode; node != null; node = node.parent) { if (node is Statement) { break; } @@ -586,7 +580,7 @@ // Check for the parameter list of a FunctionExpression. { FunctionExpression function = - node?.getAncestor((n) => n is FunctionExpression); + node?.thisOrAncestorOfType<FunctionExpression>(); if (function != null && function.parameters != null && range.node(function.parameters).contains(offset)) { @@ -655,7 +649,7 @@ // change indentation if (_selectionFunctionExpression != null) { AstNode baseNode = - _selectionFunctionExpression.getAncestor((node) => node is Statement); + _selectionFunctionExpression.thisOrAncestorOfType<Statement>(); if (baseNode != null) { String baseIndent = utils.getNodePrefix(baseNode); String targetIndent = utils.getNodePrefix(_parentMember); @@ -826,9 +820,8 @@ * Checks if it is OK to extract the node with the given [SourceRange]. */ bool _isExtractable(SourceRange range) { - _ExtractMethodAnalyzer analyzer = - new _ExtractMethodAnalyzer(resolveResult.unit, range); - utils.unit.accept(analyzer); + var analyzer = new _ExtractMethodAnalyzer(resolveResult, range); + analyzer.analyze(); return analyzer.status.isOK; } @@ -929,8 +922,9 @@ * [SelectionAnalyzer] for [ExtractMethodRefactoringImpl]. */ class _ExtractMethodAnalyzer extends StatementAnalyzer { - _ExtractMethodAnalyzer(CompilationUnit unit, SourceRange selection) - : super(unit, selection); + _ExtractMethodAnalyzer( + ResolvedUnitResult resolveResult, SourceRange selection) + : super(resolveResult, selection); @override void handleNextSelectedNode(AstNode node) { @@ -1120,7 +1114,7 @@ } } -class _InitializeOccurrencesVisitor extends GeneralizingAstVisitor<Object> { +class _InitializeOccurrencesVisitor extends GeneralizingAstVisitor<void> { final ExtractMethodRefactoringImpl ref; final _SourcePattern selectionPattern; final Map<String, String> patternToSelectionName; @@ -1131,50 +1125,50 @@ this.ref, this.selectionPattern, this.patternToSelectionName); @override - Object visitBlock(Block node) { + void visitBlock(Block node) { if (ref._selectionStatements != null) { _visitStatements(node.statements); } - return super.visitBlock(node); + super.visitBlock(node); } @override - Object visitConstructorInitializer(ConstructorInitializer node) { + void visitConstructorInitializer(ConstructorInitializer node) { forceStatic = true; try { - return super.visitConstructorInitializer(node); + super.visitConstructorInitializer(node); } finally { forceStatic = false; } } @override - Object visitExpression(Expression node) { + void visitExpression(Expression node) { if (ref._selectionFunctionExpression != null || ref._selectionExpression != null && node.runtimeType == ref._selectionExpression.runtimeType) { SourceRange nodeRange = range.node(node); _tryToFindOccurrence(nodeRange); } - return super.visitExpression(node); + super.visitExpression(node); } @override - Object visitMethodDeclaration(MethodDeclaration node) { + void visitMethodDeclaration(MethodDeclaration node) { forceStatic = node.isStatic; try { - return super.visitMethodDeclaration(node); + super.visitMethodDeclaration(node); } finally { forceStatic = false; } } @override - Object visitSwitchMember(SwitchMember node) { + void visitSwitchMember(SwitchMember node) { if (ref._selectionStatements != null) { _visitStatements(node.statements); } - return super.visitSwitchMember(node); + super.visitSwitchMember(node); } /**
diff --git a/pkg/analysis_server/lib/src/services/refactoring/extract_widget.dart b/pkg/analysis_server/lib/src/services/refactoring/extract_widget.dart index 8218754..b182f37 100644 --- a/pkg/analysis_server/lib/src/services/refactoring/extract_widget.dart +++ b/pkg/analysis_server/lib/src/services/refactoring/extract_widget.dart
@@ -1,4 +1,4 @@ -// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. @@ -13,12 +13,13 @@ import 'package:analysis_server/src/services/search/element_visitors.dart'; import 'package:analysis_server/src/services/search/search_engine.dart'; import 'package:analysis_server/src/utilities/flutter.dart'; -import 'package:analyzer/analyzer.dart'; import 'package:analyzer/dart/analysis/results.dart'; import 'package:analyzer/dart/ast/ast.dart'; +import 'package:analyzer/dart/ast/visitor.dart'; import 'package:analyzer/dart/element/element.dart'; import 'package:analyzer/dart/element/type.dart'; import 'package:analyzer/src/dart/analysis/session_helper.dart'; +import 'package:analyzer/src/dart/ast/utilities.dart'; import 'package:analyzer/src/generated/java_core.dart'; import 'package:analyzer/src/generated/source.dart' show SourceRange; import 'package:analyzer_plugin/utilities/change_builder/change_builder_dart.dart'; @@ -28,7 +29,7 @@ class ExtractWidgetRefactoringImpl extends RefactoringImpl implements ExtractWidgetRefactoring { final SearchEngine searchEngine; - final ResolveResult resolveResult; + final ResolvedUnitResult resolveResult; final AnalysisSessionHelper sessionHelper; final int offset; final int length; @@ -73,8 +74,7 @@ ExtractWidgetRefactoringImpl( this.searchEngine, this.resolveResult, this.offset, this.length) : sessionHelper = new AnalysisSessionHelper(resolveResult.session) { - utils = - new CorrectionUtils(resolveResult.unit, buffer: resolveResult.content); + utils = new CorrectionUtils(resolveResult); } @override @@ -103,7 +103,7 @@ } AstNode astNode = _expression ?? _method ?? _statements.first; - _enclosingUnitMember = astNode.getAncestor((n) { + _enclosingUnitMember = astNode.thisOrAncestorMatching((n) { return n is CompilationUnitMember && n.parent is CompilationUnit; }); @@ -178,7 +178,7 @@ } // Find the enclosing class. - _enclosingClassNode = node?.getAncestor((n) => n is ClassDeclaration); + _enclosingClassNode = node?.thisOrAncestorOfType<ClassDeclaration>(); _enclosingClassElement = _enclosingClassNode?.declaredElement; // new MyWidget(...)
diff --git a/pkg/analysis_server/lib/src/services/refactoring/inline_local.dart b/pkg/analysis_server/lib/src/services/refactoring/inline_local.dart index eafbcaf..00b8883 100644 --- a/pkg/analysis_server/lib/src/services/refactoring/inline_local.dart +++ b/pkg/analysis_server/lib/src/services/refactoring/inline_local.dart
@@ -1,4 +1,4 @@ -// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file +// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. @@ -14,8 +14,8 @@ import 'package:analyzer/dart/ast/ast.dart'; import 'package:analyzer/dart/ast/token.dart'; import 'package:analyzer/dart/element/element.dart'; +import 'package:analyzer/src/dart/analysis/session_helper.dart'; import 'package:analyzer/src/dart/ast/utilities.dart'; -import 'package:analyzer/src/dart/element/ast_provider.dart'; import 'package:analyzer/src/generated/java_core.dart'; import 'package:analyzer/src/generated/source.dart'; import 'package:analyzer_plugin/utilities/range_factory.dart'; @@ -26,8 +26,7 @@ class InlineLocalRefactoringImpl extends RefactoringImpl implements InlineLocalRefactoring { final SearchEngine searchEngine; - final AstProvider astProvider; - final ResolveResult resolveResult; + final ResolvedUnitResult resolveResult; final int offset; CorrectionUtils utils; @@ -36,9 +35,8 @@ List<SearchMatch> _references; InlineLocalRefactoringImpl( - this.searchEngine, this.astProvider, this.resolveResult, this.offset) { - utils = - new CorrectionUtils(resolveResult.unit, buffer: resolveResult.content); + this.searchEngine, this.resolveResult, this.offset) { + utils = new CorrectionUtils(resolveResult); } @override @@ -79,8 +77,10 @@ Element element = offsetNode.staticElement; if (element is LocalVariableElement) { _variableElement = element; - AstNode name = await astProvider.getResolvedNameForElement(element); - _variableNode = name.parent as VariableDeclaration; + var declarationResult = + await AnalysisSessionHelper(resolveResult.session) + .getElementDeclaration(element); + _variableNode = declarationResult.node; } } } @@ -121,8 +121,8 @@ SourceChange change = new SourceChange(refactoringName); // remove declaration { - Statement declarationStatement = _variableNode - .getAncestor((node) => node is VariableDeclarationStatement); + Statement declarationStatement = + _variableNode.thisOrAncestorOfType<VariableDeclarationStatement>(); SourceRange range = utils.getLinesRangeStatements([declarationStatement]); doSourceChange_addElementEdit(change, resolveResult.unit.declaredElement, newSourceEdit_range(range, ''));
diff --git a/pkg/analysis_server/lib/src/services/refactoring/inline_method.dart b/pkg/analysis_server/lib/src/services/refactoring/inline_method.dart index 05e5c1b..4d7b4e2 100644 --- a/pkg/analysis_server/lib/src/services/refactoring/inline_method.dart +++ b/pkg/analysis_server/lib/src/services/refactoring/inline_method.dart
@@ -1,4 +1,4 @@ -// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file +// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. @@ -16,8 +16,8 @@ import 'package:analyzer/dart/ast/ast.dart'; import 'package:analyzer/dart/ast/visitor.dart'; import 'package:analyzer/dart/element/element.dart'; +import 'package:analyzer/src/dart/analysis/session_helper.dart'; import 'package:analyzer/src/dart/ast/utilities.dart'; -import 'package:analyzer/src/dart/element/ast_provider.dart'; import 'package:analyzer/src/generated/source.dart'; import 'package:analyzer_plugin/utilities/range_factory.dart'; @@ -26,7 +26,7 @@ */ SourceRange _getLocalsConflictingRange(AstNode node) { // maybe Block - Block block = node.getAncestor((node) => node is Block); + Block block = node.thisOrAncestorOfType<Block>(); if (block != null) { return range.startEnd(node, block); } @@ -188,10 +188,9 @@ class InlineMethodRefactoringImpl extends RefactoringImpl implements InlineMethodRefactoring { final SearchEngine searchEngine; - final AstProvider astProvider; - final ResolveResult resolveResult; + final ResolvedUnitResult resolveResult; final int offset; - ResolvedUnitCache _unitCache; + final AnalysisSessionHelper sessionHelper; CorrectionUtils utils; SourceChange change; @@ -200,7 +199,6 @@ bool inlineAll = true; ExecutableElement _methodElement; - bool _isAccessor; CompilationUnit _methodUnit; CorrectionUtils _methodUtils; AstNode _methodNode; @@ -210,13 +208,12 @@ _SourcePart _methodExpressionPart; _SourcePart _methodStatementsPart; final List<_ReferenceProcessor> _referenceProcessors = []; - final Set<FunctionBody> _alreadyMadeAsync = new Set<FunctionBody>(); + final Set<Element> _alreadyMadeAsync = new Set<Element>(); InlineMethodRefactoringImpl( - this.searchEngine, this.astProvider, this.resolveResult, this.offset) { - _unitCache = new ResolvedUnitCache(astProvider, resolveResult.unit); - utils = - new CorrectionUtils(resolveResult.unit, buffer: resolveResult.content); + this.searchEngine, this.resolveResult, this.offset) + : sessionHelper = AnalysisSessionHelper(resolveResult.session) { + utils = new CorrectionUtils(resolveResult); } @override @@ -311,24 +308,6 @@ return new Future.value(change); } - Future<FunctionDeclaration> _computeFunctionDeclaration() async { - // TODO(brianwilkerson) Determine whether this await is necessary. - await null; - CompilationUnit unit = await _unitCache.getUnit(_methodElement); - return new NodeLocator(_methodElement.nameOffset) - .searchWithin(unit) - .getAncestor((n) => n is FunctionDeclaration) as FunctionDeclaration; - } - - Future<MethodDeclaration> _computeMethodDeclaration() async { - // TODO(brianwilkerson) Determine whether this await is necessary. - await null; - CompilationUnit unit = await _unitCache.getUnit(_methodElement); - return new NodeLocator(_methodElement.nameOffset) - .searchWithin(unit) - .getAncestor((n) => n is MethodDeclaration) as MethodDeclaration; - } - _SourcePart _createSourcePart(SourceRange range) { String source = _methodUtils.getRangeText(range); String prefix = getLinePrefix(source); @@ -368,38 +347,30 @@ return fatalStatus; } _methodElement = element as ExecutableElement; - _isAccessor = element is PropertyAccessorElement; - _methodUnit = await _unitCache.getUnit(element); - _methodUtils = new CorrectionUtils(_methodUnit); - // class member - bool isClassMember = element.enclosingElement is ClassElement; - if (element is MethodElement || _isAccessor && isClassMember) { - MethodDeclaration methodDeclaration = await _computeMethodDeclaration(); - _methodNode = methodDeclaration; - _methodParameters = methodDeclaration.parameters; - _methodBody = methodDeclaration.body; - // prepare mode - isDeclaration = node == methodDeclaration.name; - deleteSource = isDeclaration; - inlineAll = deleteSource; - return new RefactoringStatus(); + + var declaration = await sessionHelper.getElementDeclaration(_methodElement); + var methodNode = declaration.node; + _methodNode = methodNode; + + var resolvedUnit = declaration.resolvedUnit; + _methodUnit = resolvedUnit.unit; + _methodUtils = new CorrectionUtils(resolvedUnit); + + if (methodNode is MethodDeclaration) { + _methodParameters = methodNode.parameters; + _methodBody = methodNode.body; + } else if (methodNode is FunctionDeclaration) { + _methodParameters = methodNode.functionExpression.parameters; + _methodBody = methodNode.functionExpression.body; + } else { + return fatalStatus; } - // unit member - bool isUnitMember = element.enclosingElement is CompilationUnitElement; - if (element is FunctionElement || _isAccessor && isUnitMember) { - FunctionDeclaration functionDeclaration = - await _computeFunctionDeclaration(); - _methodNode = functionDeclaration; - _methodParameters = functionDeclaration.functionExpression.parameters; - _methodBody = functionDeclaration.functionExpression.body; - // prepare mode - isDeclaration = node == functionDeclaration.name; - deleteSource = isDeclaration; - inlineAll = deleteSource; - return new RefactoringStatus(); - } - // OK - return fatalStatus; + + isDeclaration = resolveResult.uri == element.source.uri && + node.offset == element.nameOffset; + deleteSource = isDeclaration; + inlineAll = deleteSource; + return new RefactoringStatus(); } /** @@ -467,12 +438,14 @@ // TODO(brianwilkerson) Determine whether this await is necessary. await null; refElement = reference.element; + // prepare CorrectionUtils - CompilationUnit refUnit = await ref._unitCache.getUnit(refElement); - _refUtils = new CorrectionUtils(refUnit); + var result = await ref.sessionHelper.getResolvedUnitByElement(refElement); + _refUtils = new CorrectionUtils(result); + // prepare node and environment _node = _refUtils.findNode(reference.sourceRange.offset); - Statement refStatement = _node.getAncestor((node) => node is Statement); + Statement refStatement = _node.thisOrAncestorOfType<Statement>(); if (refStatement != null) { _refLineRange = _refUtils.getLinesRangeStatements([refStatement]); _refPrefix = _refUtils.getNodePrefix(refStatement); @@ -591,7 +564,7 @@ // If the element being inlined is async, ensure that the function // body that encloses the method is also async. if (ref._methodElement.isAsynchronous) { - FunctionBody body = _node.getAncestor((n) => n is FunctionBody); + FunctionBody body = _node.thisOrAncestorOfType<FunctionBody>(); if (body != null) { if (body.isSynchronous) { if (body.isGenerator) { @@ -608,7 +581,7 @@ return; } } - if (ref._alreadyMadeAsync.add(body)) { + if (ref._alreadyMadeAsync.add(refElement)) { SourceRange bodyStart = range.startLength(body, 0); _addRefEdit(newSourceEdit_range(bodyStart, 'async ')); } @@ -650,7 +623,7 @@ List<Expression> arguments = []; if (_node.inSetterContext()) { AssignmentExpression assignment = - _node.getAncestor((node) => node is AssignmentExpression); + _node.thisOrAncestorOfType<AssignmentExpression>(); arguments.add(assignment.rightHandSide); } // inline body
diff --git a/pkg/analysis_server/lib/src/services/refactoring/move_file.dart b/pkg/analysis_server/lib/src/services/refactoring/move_file.dart index d2e3c69..a068451 100644 --- a/pkg/analysis_server/lib/src/services/refactoring/move_file.dart +++ b/pkg/analysis_server/lib/src/services/refactoring/move_file.dart
@@ -32,6 +32,8 @@ String oldFile; String newFile; + final packagePrefixedStringPattern = new RegExp(r'''^r?['"]+package:'''); + MoveFileRefactoringImpl(ResourceProvider resourceProvider, this.workspace, this.source, this.oldFile) : resourceProvider = resourceProvider, @@ -90,7 +92,8 @@ }); } else { // Otherwise, we need to update any relative part-of references. - Iterable<PartOfDirective> partOfs = element.unit.directives + final result = await driver.currentSession.getResolvedUnit(oldFile); + Iterable<PartOfDirective> partOfs = result.unit.directives .whereType<PartOfDirective>() .where((po) => po.uri != null && _isRelativeUri(po.uri.stringValue)); @@ -139,7 +142,12 @@ return _getRelativeUri(newFile, refDir); } - final packagePrefixedStringPattern = new RegExp(r'''^r?['"]+package:'''); + String _getRelativeUri(String path, String from) { + String uri = pathContext.relative(path, from: from); + List<String> parts = pathContext.split(uri); + return pathos.posix.joinAll(parts); + } + bool _isPackageReference(SourceReference reference) { final Source source = reference.element.source; final String quotedImportUri = source.contents.data.substring( @@ -148,12 +156,6 @@ return packagePrefixedStringPattern.hasMatch(quotedImportUri); } - String _getRelativeUri(String path, String from) { - String uri = pathContext.relative(path, from: from); - List<String> parts = pathContext.split(uri); - return pathos.posix.joinAll(parts); - } - /** * Checks if the given [path] represents a relative URI. *
diff --git a/pkg/analysis_server/lib/src/services/refactoring/refactoring.dart b/pkg/analysis_server/lib/src/services/refactoring/refactoring.dart index 50e2344..223d699 100644 --- a/pkg/analysis_server/lib/src/services/refactoring/refactoring.dart +++ b/pkg/analysis_server/lib/src/services/refactoring/refactoring.dart
@@ -22,11 +22,11 @@ import 'package:analysis_server/src/services/refactoring/rename_unit_member.dart'; import 'package:analysis_server/src/services/search/search_engine.dart'; import 'package:analyzer/dart/analysis/results.dart'; +import 'package:analyzer/dart/analysis/session.dart'; import 'package:analyzer/dart/ast/ast.dart'; import 'package:analyzer/dart/element/element.dart'; import 'package:analyzer/file_system/file_system.dart'; import 'package:analyzer/src/dart/analysis/driver.dart'; -import 'package:analyzer/src/dart/element/ast_provider.dart'; import 'package:analyzer/src/generated/source.dart'; import 'package:analyzer_plugin/protocol/protocol_common.dart' show RefactoringMethodParameter, SourceChange; @@ -40,9 +40,9 @@ * [element] and all the corresponding hierarchy elements. */ factory ConvertGetterToMethodRefactoring(SearchEngine searchEngine, - AstProvider astProvider, PropertyAccessorElement element) { + AnalysisSession session, PropertyAccessorElement element) { return new ConvertGetterToMethodRefactoringImpl( - searchEngine, astProvider, element); + searchEngine, session, element); } } @@ -55,9 +55,8 @@ * [element] and all the corresponding hierarchy elements. */ factory ConvertMethodToGetterRefactoring(SearchEngine searchEngine, - AstProvider astProvider, ExecutableElement element) { - return new ConvertMethodToGetterRefactoringImpl( - searchEngine, astProvider, element); + AnalysisSession session, ExecutableElement element) { + return new ConvertMethodToGetterRefactoringImpl(searchEngine, element); } } @@ -68,7 +67,7 @@ /** * Returns a new [ExtractLocalRefactoring] instance. */ - factory ExtractLocalRefactoring(ResolveResult resolveResult, + factory ExtractLocalRefactoring(ResolvedUnitResult resolveResult, int selectionOffset, int selectionLength) = ExtractLocalRefactoringImpl; /** @@ -144,12 +143,11 @@ */ factory ExtractMethodRefactoring( SearchEngine searchEngine, - AstProvider astProvider, - ResolveResult resolveResult, + ResolvedUnitResult resolveResult, int selectionOffset, int selectionLength) { - return new ExtractMethodRefactoringImpl(searchEngine, astProvider, - resolveResult, selectionOffset, selectionLength); + return new ExtractMethodRefactoringImpl( + searchEngine, resolveResult, selectionOffset, selectionLength); } /** @@ -243,7 +241,7 @@ * Returns a new [ExtractWidgetRefactoring] instance. */ factory ExtractWidgetRefactoring(SearchEngine searchEngine, - ResolveResult resolveResult, int offset, int length) { + ResolvedUnitResult resolveResult, int offset, int length) { return new ExtractWidgetRefactoringImpl( searchEngine, resolveResult, offset, length); } @@ -278,10 +276,9 @@ /** * Returns a new [InlineLocalRefactoring] instance. */ - factory InlineLocalRefactoring(SearchEngine searchEngine, - AstProvider astProvider, ResolveResult resolveResult, int offset) { - return new InlineLocalRefactoringImpl( - searchEngine, astProvider, resolveResult, offset); + factory InlineLocalRefactoring( + SearchEngine searchEngine, ResolvedUnitResult resolveResult, int offset) { + return new InlineLocalRefactoringImpl(searchEngine, resolveResult, offset); } /** @@ -302,10 +299,9 @@ /** * Returns a new [InlineMethodRefactoring] instance. */ - factory InlineMethodRefactoring(SearchEngine searchEngine, - AstProvider astProvider, ResolveResult resolveResult, int offset) { - return new InlineMethodRefactoringImpl( - searchEngine, astProvider, resolveResult, offset); + factory InlineMethodRefactoring( + SearchEngine searchEngine, ResolvedUnitResult resolveResult, int offset) { + return new InlineMethodRefactoringImpl(searchEngine, resolveResult, offset); } /** @@ -413,6 +409,13 @@ RefactoringWorkspace(this.drivers, this.searchEngine); /** + * Whether the [element] is defined in a file that is in a context root. + */ + bool containsElement(Element element) { + return containsFile(element.source.fullName); + } + + /** * Whether the file with the given [path] is in a context root. */ bool containsFile(String path) { @@ -441,7 +444,7 @@ * type. */ factory RenameRefactoring(RefactoringWorkspace workspace, - AstProvider astProvider, Element element) { + AnalysisSession session, Element element) { if (element == null) { return null; } @@ -452,11 +455,10 @@ return new RenameUnitMemberRefactoringImpl(workspace, element); } if (element is ConstructorElement) { - return new RenameConstructorRefactoringImpl( - workspace, astProvider, element); + return new RenameConstructorRefactoringImpl(workspace, session, element); } if (element is ImportElement) { - return new RenameImportRefactoringImpl(workspace, astProvider, element); + return new RenameImportRefactoringImpl(workspace, session, element); } if (element is LabelElement) { return new RenameLabelRefactoringImpl(workspace, element); @@ -465,11 +467,10 @@ return new RenameLibraryRefactoringImpl(workspace, element); } if (element is LocalElement) { - return new RenameLocalRefactoringImpl(workspace, astProvider, element); + return new RenameLocalRefactoringImpl(workspace, element); } if (element.enclosingElement is ClassElement) { - return new RenameClassMemberRefactoringImpl( - workspace, astProvider, element); + return new RenameClassMemberRefactoringImpl(workspace, session, element); } return null; } @@ -501,38 +502,3 @@ */ RefactoringStatus checkNewName(); } - -/** - * Cache for accessing resolved [CompilationUnit]s by [Element]s. - * - * Must by short-lived. - * - * TODO(scheglov) consider moving to request-bound object. - */ -class ResolvedUnitCache { - final AstProvider _astProvider; - final Map<CompilationUnitElement, CompilationUnit> _map = {}; - - ResolvedUnitCache(this._astProvider, [CompilationUnit unit]) { - if (unit != null) { - _map[unit.declaredElement] = unit; - } - } - - Future<CompilationUnit> getUnit(Element element) async { - // TODO(brianwilkerson) Determine whether this await is necessary. - await null; - CompilationUnitElement unitElement = getUnitElement(element); - CompilationUnit unit = _map[unitElement]; - if (unit == null) { - unit = await _astProvider.getResolvedUnitForElement(element); - _map[unitElement] = unit; - } - return unit; - } - - CompilationUnitElement getUnitElement(Element element) { - return element.getAncestor((e) => e is CompilationUnitElement) - as CompilationUnitElement; - } -}
diff --git a/pkg/analysis_server/lib/src/services/refactoring/rename.dart b/pkg/analysis_server/lib/src/services/refactoring/rename.dart index d7f193c..b7663c0 100644 --- a/pkg/analysis_server/lib/src/services/refactoring/rename.dart +++ b/pkg/analysis_server/lib/src/services/refactoring/rename.dart
@@ -18,17 +18,17 @@ * Helper for renaming one or more [Element]s. */ class RenameProcessor { - final SearchEngine searchEngine; + final RefactoringWorkspace workspace; final SourceChange change; final String newName; - RenameProcessor(this.searchEngine, this.change, this.newName); + RenameProcessor(this.workspace, this.change, this.newName); /** * Add the edit that updates the [element] declaration. */ void addDeclarationEdit(Element element) { - if (element != null) { + if (element != null && workspace.containsElement(element)) { SourceEdit edit = newSourceEdit_range(range.elementName(element), newName); doSourceChange_addElementEdit(change, element, edit); @@ -41,6 +41,9 @@ void addReferenceEdits(List<SearchMatch> matches) { List<SourceReference> references = getSourceReferences(matches); for (SourceReference reference in references) { + if (!workspace.containsElement(reference.element)) { + continue; + } reference.addEdit(change, newName); } } @@ -50,7 +53,9 @@ */ Future<void> renameElement(Element element) { addDeclarationEdit(element); - return searchEngine.searchReferences(element).then(addReferenceEdits); + return workspace.searchEngine + .searchReferences(element) + .then(addReferenceEdits); } } @@ -86,7 +91,7 @@ getElementQualifiedName(element)); result.addFatalError(message); } - if (!workspace.containsFile(element.source.fullName)) { + if (!workspace.containsElement(element)) { String message = format( "The {0} '{1}' is defined outside of the project, so cannot be renamed.", getElementKindName(element),
diff --git a/pkg/analysis_server/lib/src/services/refactoring/rename_class_member.dart b/pkg/analysis_server/lib/src/services/refactoring/rename_class_member.dart index d085e78..df98b9e 100644 --- a/pkg/analysis_server/lib/src/services/refactoring/rename_class_member.dart +++ b/pkg/analysis_server/lib/src/services/refactoring/rename_class_member.dart
@@ -14,10 +14,11 @@ import 'package:analysis_server/src/services/refactoring/rename.dart'; import 'package:analysis_server/src/services/search/hierarchy.dart'; import 'package:analysis_server/src/services/search/search_engine.dart'; +import 'package:analyzer/dart/analysis/session.dart'; import 'package:analyzer/dart/ast/ast.dart'; import 'package:analyzer/dart/ast/visitor.dart'; import 'package:analyzer/dart/element/element.dart'; -import 'package:analyzer/src/dart/element/ast_provider.dart'; +import 'package:analyzer/src/dart/analysis/session_helper.dart'; import 'package:analyzer/src/generated/java_core.dart'; import 'package:analyzer/src/generated/source.dart'; @@ -25,10 +26,13 @@ * Checks if creating a method with the given [name] in [classElement] will * cause any conflicts. */ -Future<RefactoringStatus> validateCreateMethod(SearchEngine searchEngine, - AstProvider astProvider, ClassElement classElement, String name) { +Future<RefactoringStatus> validateCreateMethod( + SearchEngine searchEngine, + AnalysisSessionHelper sessionHelper, + ClassElement classElement, + String name) { return new _ClassMemberValidator.forCreate( - searchEngine, astProvider, classElement, name) + searchEngine, sessionHelper, classElement, name) .validate(); } @@ -36,13 +40,14 @@ * A [Refactoring] for renaming class member [Element]s. */ class RenameClassMemberRefactoringImpl extends RenameRefactoringImpl { - final AstProvider astProvider; + final AnalysisSessionHelper sessionHelper; _ClassMemberValidator _validator; RenameClassMemberRefactoringImpl( - RefactoringWorkspace workspace, this.astProvider, Element element) - : super(workspace, element); + RefactoringWorkspace workspace, AnalysisSession session, Element element) + : sessionHelper = AnalysisSessionHelper(session), + super(workspace, element); @override String get refactoringName { @@ -58,7 +63,7 @@ @override Future<RefactoringStatus> checkFinalConditions() { _validator = new _ClassMemberValidator.forRename( - searchEngine, astProvider, element, newName); + searchEngine, sessionHelper, element, newName); return _validator.validate(); } @@ -87,7 +92,7 @@ @override Future<void> fillChange() async { - var processor = new RenameProcessor(searchEngine, change, newName); + var processor = new RenameProcessor(workspace, change, newName); // update declarations for (Element renameElement in _validator.elements) { if (renameElement.isSynthetic && renameElement is FieldElement) { @@ -105,7 +110,7 @@ List<SourceReference> nameRefs = getSourceReferences(nameMatches); for (SourceReference reference in nameRefs) { // ignore references from SDK and pub cache - if (!workspace.containsFile(reference.element.source.fullName)) { + if (!workspace.containsElement(reference.element)) { continue; } // check the element being renamed is accessible @@ -132,7 +137,7 @@ */ class _ClassMemberValidator { final SearchEngine searchEngine; - final ResolvedUnitCache unitCache; + final AnalysisSessionHelper sessionHelper; final LibraryElement library; final Element element; final ClassElement elementClass; @@ -145,17 +150,15 @@ List<SearchMatch> references = <SearchMatch>[]; _ClassMemberValidator.forCreate( - this.searchEngine, AstProvider astProvider, this.elementClass, this.name) - : unitCache = new ResolvedUnitCache(astProvider), - isRename = false, + this.searchEngine, this.sessionHelper, this.elementClass, this.name) + : isRename = false, library = null, element = null, elementKind = ElementKind.METHOD; _ClassMemberValidator.forRename( - this.searchEngine, AstProvider astProvider, Element element, this.name) - : unitCache = new ResolvedUnitCache(astProvider), - isRename = true, + this.searchEngine, this.sessionHelper, Element element, this.name) + : isRename = true, library = element.library, element = element, elementClass = element.enclosingElement, @@ -260,12 +263,13 @@ Future<List<LocalElement>> getLocalElements(Element element) async { // TODO(brianwilkerson) Determine whether this await is necessary. await null; - var unitElement = unitCache.getUnitElement(element); + + var resolvedUnit = await sessionHelper.getResolvedUnitByElement(element); + var unitElement = resolvedUnit.unit.declaredElement; var localElements = localElementMap[unitElement]; if (localElements == null) { - var unit = await unitCache.getUnit(unitElement); var collector = new _LocalElementsCollector(name); - unit.accept(collector); + resolvedUnit.unit.accept(collector); localElements = collector.elements; localElementMap[unitElement] = localElements; }
diff --git a/pkg/analysis_server/lib/src/services/refactoring/rename_constructor.dart b/pkg/analysis_server/lib/src/services/refactoring/rename_constructor.dart index 755ebff..6baadf4 100644 --- a/pkg/analysis_server/lib/src/services/refactoring/rename_constructor.dart +++ b/pkg/analysis_server/lib/src/services/refactoring/rename_constructor.dart
@@ -14,9 +14,10 @@ import 'package:analysis_server/src/services/search/hierarchy.dart'; import 'package:analysis_server/src/services/search/search_engine.dart'; import 'package:analysis_server/src/services/search/search_engine_internal.dart'; +import 'package:analyzer/dart/analysis/session.dart'; import 'package:analyzer/dart/ast/ast.dart'; import 'package:analyzer/dart/element/element.dart'; -import 'package:analyzer/src/dart/element/ast_provider.dart'; +import 'package:analyzer/src/dart/analysis/session_helper.dart'; import 'package:analyzer/src/generated/java_core.dart'; import 'package:analyzer/src/generated/source.dart'; import 'package:analyzer_plugin/utilities/range_factory.dart'; @@ -25,10 +26,10 @@ * A [Refactoring] for renaming [ConstructorElement]s. */ class RenameConstructorRefactoringImpl extends RenameRefactoringImpl { - final AstProvider astProvider; + final AnalysisSession session; - RenameConstructorRefactoringImpl(RefactoringWorkspace workspace, - this.astProvider, ConstructorElement element) + RenameConstructorRefactoringImpl( + RefactoringWorkspace workspace, this.session, ConstructorElement element) : super(workspace, element); @override @@ -117,11 +118,12 @@ // TODO(brianwilkerson) Determine whether this await is necessary. await null; ClassElement classElement = element.enclosingElement; - AstNode name = await astProvider.getResolvedNameForElement(classElement); - ClassDeclaration classNode = name.parent as ClassDeclaration; - CorrectionUtils utils = new CorrectionUtils(classNode.parent); - ClassMemberLocation location = - utils.prepareNewConstructorLocation(classNode); + + var result = await AnalysisSessionHelper(session) + .getElementDeclaration(classElement); + ClassDeclaration classNode = result.node; + var utils = new CorrectionUtils(result.resolvedUnit); + var location = utils.prepareNewConstructorLocation(classNode); doSourceChange_addElementEdit( change, classElement,
diff --git a/pkg/analysis_server/lib/src/services/refactoring/rename_import.dart b/pkg/analysis_server/lib/src/services/refactoring/rename_import.dart index 53e382b..2bc3c99 100644 --- a/pkg/analysis_server/lib/src/services/refactoring/rename_import.dart +++ b/pkg/analysis_server/lib/src/services/refactoring/rename_import.dart
@@ -11,12 +11,10 @@ import 'package:analysis_server/src/services/refactoring/refactoring_internal.dart'; import 'package:analysis_server/src/services/refactoring/rename.dart'; import 'package:analysis_server/src/services/search/search_engine.dart'; -import 'package:analyzer/dart/analysis/results.dart'; import 'package:analyzer/dart/analysis/session.dart'; import 'package:analyzer/dart/ast/ast.dart'; import 'package:analyzer/dart/element/element.dart'; import 'package:analyzer/src/dart/ast/utilities.dart'; -import 'package:analyzer/src/dart/element/ast_provider.dart'; import 'package:analyzer/src/generated/source.dart'; import 'package:analyzer_plugin/utilities/range_factory.dart'; @@ -24,10 +22,10 @@ * A [Refactoring] for renaming [ImportElement]s. */ class RenameImportRefactoringImpl extends RenameRefactoringImpl { - final AstProvider astProvider; + final AnalysisSession session; RenameImportRefactoringImpl( - RefactoringWorkspace workspace, this.astProvider, ImportElement element) + RefactoringWorkspace workspace, this.session, ImportElement element) : super(workspace, element); @override @@ -60,14 +58,14 @@ PrefixElement prefix = element.prefix; SourceEdit edit = null; if (newName.isEmpty) { - ImportDirective node = await _findNode(); + ImportDirective node = _findNode(); int uriEnd = node.uri.end; int prefixEnd = element.prefixOffset + prefix.nameLength; edit = newSourceEdit_range( range.startOffsetEndOffset(uriEnd, prefixEnd), ""); } else { if (prefix == null) { - ImportDirective node = await _findNode(); + ImportDirective node = _findNode(); int uriEnd = node.uri.end; edit = newSourceEdit_range(new SourceRange(uriEnd, 0), " as $newName"); @@ -89,7 +87,7 @@ reference.addEdit(change, ''); } else { SimpleIdentifier interpolationIdentifier = - await _getInterpolationIdentifier(reference); + _getInterpolationIdentifier(reference); if (interpolationIdentifier != null) { doSourceChange_addElementEdit( change, @@ -108,11 +106,10 @@ /** * Return the [ImportDirective] node that corresponds to the [element]. */ - Future<ImportDirective> _findNode() async { - // TODO(brianwilkerson) Determine whether this await is necessary. - await null; + ImportDirective _findNode() { LibraryElement library = element.library; - CompilationUnit unit = await astProvider.getParsedUnitForElement(library); + String path = library.source.fullName; + CompilationUnit unit = session.getParsedUnit(path).unit; int index = library.imports.indexOf(element); return unit.directives.where((d) => d is ImportDirective).toList()[index]; } @@ -122,14 +119,9 @@ * an [InterpolationExpression] without surrounding curly brackets, return it. * Otherwise return `null`. */ - Future<SimpleIdentifier> _getInterpolationIdentifier( - SourceReference reference) async { - // TODO(brianwilkerson) Determine whether this await is necessary. - await null; + SimpleIdentifier _getInterpolationIdentifier(SourceReference reference) { Source source = reference.element.source; - AnalysisSession currentSession = astProvider.driver.currentSession; - ParseResult result = await currentSession.getParsedAst(source.fullName); - CompilationUnit unit = result.unit; + CompilationUnit unit = session.getParsedUnit(source.fullName).unit; NodeLocator nodeLocator = new NodeLocator(reference.range.offset); AstNode node = nodeLocator.searchWithin(unit); if (node is SimpleIdentifier) {
diff --git a/pkg/analysis_server/lib/src/services/refactoring/rename_label.dart b/pkg/analysis_server/lib/src/services/refactoring/rename_label.dart index 643be1f..012f500 100644 --- a/pkg/analysis_server/lib/src/services/refactoring/rename_label.dart +++ b/pkg/analysis_server/lib/src/services/refactoring/rename_label.dart
@@ -39,7 +39,7 @@ @override Future<void> fillChange() { - var processor = new RenameProcessor(searchEngine, change, newName); + var processor = new RenameProcessor(workspace, change, newName); return processor.renameElement(element); } }
diff --git a/pkg/analysis_server/lib/src/services/refactoring/rename_library.dart b/pkg/analysis_server/lib/src/services/refactoring/rename_library.dart index e270f82..8ad6912 100644 --- a/pkg/analysis_server/lib/src/services/refactoring/rename_library.dart +++ b/pkg/analysis_server/lib/src/services/refactoring/rename_library.dart
@@ -41,7 +41,7 @@ @override Future<void> fillChange() async { - var processor = new RenameProcessor(searchEngine, change, newName); + var processor = new RenameProcessor(workspace, change, newName); await processor.renameElement(element); } }
diff --git a/pkg/analysis_server/lib/src/services/refactoring/rename_local.dart b/pkg/analysis_server/lib/src/services/refactoring/rename_local.dart index 369b832..7fac53a 100644 --- a/pkg/analysis_server/lib/src/services/refactoring/rename_local.dart +++ b/pkg/analysis_server/lib/src/services/refactoring/rename_local.dart
@@ -1,4 +1,4 @@ -// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file +// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. @@ -15,21 +15,20 @@ import 'package:analyzer/dart/ast/ast.dart'; import 'package:analyzer/dart/ast/visitor.dart'; import 'package:analyzer/dart/element/element.dart'; -import 'package:analyzer/src/dart/element/ast_provider.dart'; +import 'package:analyzer/src/dart/analysis/session_helper.dart'; import 'package:analyzer/src/generated/source.dart'; /** * A [Refactoring] for renaming [LocalElement]s. */ class RenameLocalRefactoringImpl extends RenameRefactoringImpl { - final AstProvider astProvider; - final ResolvedUnitCache unitCache; + final AnalysisSessionHelper sessionHelper; List<LocalElement> elements = []; RenameLocalRefactoringImpl( - RefactoringWorkspace workspace, this.astProvider, LocalElement element) - : unitCache = new ResolvedUnitCache(astProvider), + RefactoringWorkspace workspace, LocalElement element) + : sessionHelper = AnalysisSessionHelper(element.session), super(workspace, element); @override @@ -53,10 +52,9 @@ RefactoringStatus result = new RefactoringStatus(); await _prepareElements(); for (LocalElement element in elements) { - CompilationUnit unit = await unitCache.getUnit(element); - if (unit != null) { - unit.accept(new _ConflictValidatorVisitor(result, newName, element)); - } + var resolvedUnit = await sessionHelper.getResolvedUnitByElement(element); + var unit = resolvedUnit.unit; + unit.accept(new _ConflictValidatorVisitor(result, newName, element)); } return result; } @@ -76,7 +74,7 @@ @override Future<void> fillChange() async { - var processor = new RenameProcessor(searchEngine, change, newName); + var processor = new RenameProcessor(workspace, change, newName); for (Element element in elements) { processor.addDeclarationEdit(element); var references = await searchEngine.searchReferences(element);
diff --git a/pkg/analysis_server/lib/src/services/refactoring/rename_unit_member.dart b/pkg/analysis_server/lib/src/services/refactoring/rename_unit_member.dart index 88cac3a..5d20312 100644 --- a/pkg/analysis_server/lib/src/services/refactoring/rename_unit_member.dart +++ b/pkg/analysis_server/lib/src/services/refactoring/rename_unit_member.dart
@@ -127,7 +127,7 @@ } // Rename each element and references to it. - var processor = new RenameProcessor(searchEngine, change, newName); + var processor = new RenameProcessor(workspace, change, newName); for (var element in elements) { await processor.renameElement(element); } @@ -136,7 +136,7 @@ if (_flutterWidgetState != null) { _updateFlutterWidgetStateName(); await new RenameProcessor( - searchEngine, + workspace, change, _flutterWidgetStateNewName, ).renameElement(_flutterWidgetState);
diff --git a/pkg/analysis_server/lib/src/services/search/search_engine.dart b/pkg/analysis_server/lib/src/services/search/search_engine.dart index df6e31c..74445c4 100644 --- a/pkg/analysis_server/lib/src/services/search/search_engine.dart +++ b/pkg/analysis_server/lib/src/services/search/search_engine.dart
@@ -140,7 +140,7 @@ MatchKind get kind; /** - * Return the [LibraryElement] for the [libraryUri] in the [context]. + * Return the [LibraryElement] for the [file]. */ LibraryElement get libraryElement;
diff --git a/pkg/analysis_server/lib/src/status/diagnostics.dart b/pkg/analysis_server/lib/src/status/diagnostics.dart index dc21222..a8b5a1a 100644 --- a/pkg/analysis_server/lib/src/status/diagnostics.dart +++ b/pkg/analysis_server/lib/src/status/diagnostics.dart
@@ -12,7 +12,6 @@ import 'package:analysis_server/protocol/protocol_generated.dart'; import 'package:analysis_server/src/analysis_server.dart'; import 'package:analysis_server/src/domain_completion.dart'; -import 'package:analysis_server/src/domain_diagnostic.dart'; import 'package:analysis_server/src/plugin/plugin_manager.dart'; import 'package:analysis_server/src/server/http_server.dart'; import 'package:analysis_server/src/services/completion/completion_performance.dart'; @@ -21,6 +20,7 @@ import 'package:analysis_server/src/status/element_writer.dart'; import 'package:analysis_server/src/status/pages.dart'; import 'package:analysis_server/src/utilities/profiling.dart'; +import 'package:analyzer/dart/analysis/results.dart'; import 'package:analyzer/file_system/file_system.dart'; import 'package:analyzer/instrumentation/instrumentation.dart'; import 'package:analyzer/src/context/context_root.dart'; @@ -187,7 +187,7 @@ raw: true); return; } - AnalysisResult result = await driver.getResult(path); + ResolvedUnitResult result = await driver.getResult(path); if (result == null) { p( 'An AST could not be produced for the file ' @@ -387,7 +387,6 @@ b.write(writeOption('Strong mode', options.strongMode)); b.write(writeOption('Implicit dynamic', options.implicitDynamic)); b.write(writeOption('Implicit casts', options.implicitCasts)); - b.write(writeOption('Declaration casts', options.declarationCasts)); b.write( writeOption('Analyze function bodies', options.analyzeFunctionBodies)); @@ -400,6 +399,8 @@ b.write(writeOption('Preserve comments', options.preserveComments)); b.write(writeOption('Strong mode hints', options.strongModeHints)); + b.write(writeOption('Enabled experiments', options.enabledExperiments)); + return b.toString(); } @@ -714,7 +715,7 @@ SocketServer socketServer; /// The last few lines printed. - List<String> lastPrintedLines = <String>[]; + final List<String> lastPrintedLines; DiagnosticsSite(this.socketServer, this.lastPrintedLines) : super('Analysis Server') { @@ -783,7 +784,7 @@ raw: true); return; } - AnalysisResult result = await driver.getResult(path); + ResolvedUnitResult result = await driver.getResult(path); if (result == null) { p( 'An element model could not be produced for the file ' @@ -956,11 +957,6 @@ : super(site, 'memory', 'Memory and CPU Usage', description: 'Memory and CPU usage for the analysis server.'); - DiagnosticDomainHandler get diagnosticDomain { - return server.handlers - .firstWhere((handler) => handler is DiagnosticDomainHandler); - } - @override Future generateContent(Map<String, String> params) async { // TODO(brianwilkerson) Determine whether this await is necessary. @@ -1246,7 +1242,7 @@ final WebSocket socket; int _id = 0; - Map<String, Completer<Map>> _completers = {}; + final Map<String, Completer<Map>> _completers = {}; ServiceProtocol._(this.socket) { socket.listen(_handleMessage);
diff --git a/pkg/analysis_server/lib/src/status/pages.dart b/pkg/analysis_server/lib/src/status/pages.dart index b270a3c..41b9b80 100644 --- a/pkg/analysis_server/lib/src/status/pages.dart +++ b/pkg/analysis_server/lib/src/status/pages.dart
@@ -136,7 +136,7 @@ /// Contains a collection of Pages. abstract class Site { final String title; - List<Page> pages = []; + final List<Page> pages = []; Site(this.title);
diff --git a/pkg/analysis_server/lib/src/status/tree_writer.dart b/pkg/analysis_server/lib/src/status/tree_writer.dart index 9feb8af..62b07f1 100644 --- a/pkg/analysis_server/lib/src/status/tree_writer.dart +++ b/pkg/analysis_server/lib/src/status/tree_writer.dart
@@ -13,7 +13,7 @@ * Utility methods that can be mixed in to classes that produce an HTML * representation of a tree structure. */ -abstract class TreeWriter { +mixin TreeWriter { /** * The buffer on which the HTML is to be written. */
diff --git a/pkg/analysis_server/lib/src/utilities/flutter.dart b/pkg/analysis_server/lib/src/utilities/flutter.dart index f116530..6e754c3 100644 --- a/pkg/analysis_server/lib/src/utilities/flutter.dart +++ b/pkg/analysis_server/lib/src/utilities/flutter.dart
@@ -19,6 +19,8 @@ const _STATE_NAME = "State"; const _STATEFUL_WIDGET_NAME = "StatefulWidget"; const _STATELESS_WIDGET_NAME = "StatelessWidget"; +const _STREAM_BUILDER_NAME = "StreamBuilder"; +const _STREAM_BUILDER_URI = "package:flutter/src/widgets/async.dart"; const _WIDGET_NAME = "Widget"; const _WIDGET_URI = "package:flutter/src/widgets/framework.dart"; final _frameworkUri = Uri.parse('package:flutter/src/widgets/framework.dart'); @@ -307,6 +309,14 @@ } /** + * Return `true` if the given [type] is the Flutter class `StreamBuilder`. + */ +bool isExactWidgetTypeStreamBuilder(DartType type) { + return type is InterfaceType && + _isExactWidget(type.element, _STREAM_BUILDER_NAME, _STREAM_BUILDER_URI); +} + +/** * Return `true` if the given [type] is the Flutter class `Widget`, or its * subtype. */
diff --git a/pkg/analysis_server/lib/src/utilities/profiling.dart b/pkg/analysis_server/lib/src/utilities/profiling.dart index 7e2e49b..9dbd260 100644 --- a/pkg/analysis_server/lib/src/utilities/profiling.dart +++ b/pkg/analysis_server/lib/src/utilities/profiling.dart
@@ -12,8 +12,6 @@ Future<UsageInfo> getProcessUsage(int processId); - UsageInfo getProcessUsageSync(int processId); - /// Return a [ProcessProfiler] instance suitable for the current host /// platform. This can return `null` if we're not able to gather memory and /// cpu information for the current platform. @@ -65,17 +63,6 @@ } } - UsageInfo getProcessUsageSync(int processId) { - try { - // Execution time is typically 2-4ms. - ProcessResult result = - Process.runSync('ps', ['-o', '%cpu=,rss=', processId.toString()]); - return result.exitCode == 0 ? _parse(result.stdout) : null; - } catch (e) { - return null; - } - } - UsageInfo _parse(String psResults) { try { // " 0.0 378940"
diff --git a/pkg/analysis_server/lib/starter.dart b/pkg/analysis_server/lib/starter.dart index aa4a30e..949e761 100644 --- a/pkg/analysis_server/lib/starter.dart +++ b/pkg/analysis_server/lib/starter.dart
@@ -2,7 +2,6 @@ // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. -import 'package:analysis_server/src/analysis_server.dart'; import 'package:analysis_server/src/server/detachable_filesystem_manager.dart'; import 'package:analysis_server/src/server/driver.dart'; import 'package:analyzer/instrumentation/instrumentation.dart'; @@ -47,10 +46,6 @@ /** * Use the given command-line [arguments] to start this server. - * - * At least temporarily returns AnalysisServer so that consumers of the - * starter API can then use the server, this is done as a stopgap for the - * angular plugin until the official plugin API is finished. */ - AnalysisServer start(List<String> arguments); + void start(List<String> arguments); }
diff --git a/pkg/analysis_server/test/abstract_context.dart b/pkg/analysis_server/test/abstract_context.dart index ecbbbb32..6f4f753 100644 --- a/pkg/analysis_server/test/abstract_context.dart +++ b/pkg/analysis_server/test/abstract_context.dart
@@ -1,29 +1,23 @@ -// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file +// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. import 'dart:async'; +import 'package:analyzer/dart/analysis/session.dart'; import 'package:analyzer/dart/ast/ast.dart'; import 'package:analyzer/dart/element/element.dart'; import 'package:analyzer/dart/element/visitor.dart'; -import 'package:analyzer/exception/exception.dart'; import 'package:analyzer/file_system/file_system.dart'; -import 'package:analyzer/src/context/context_root.dart'; +import 'package:analyzer/src/dart/analysis/analysis_context_collection.dart'; import 'package:analyzer/src/dart/analysis/driver.dart'; +import 'package:analyzer/src/dart/analysis/driver_based_analysis_context.dart'; import 'package:analyzer/src/dart/analysis/file_state.dart'; -import 'package:analyzer/src/file_system/file_system.dart'; import 'package:analyzer/src/generated/engine.dart'; -import 'package:analyzer/src/generated/engine.dart' as engine; -import 'package:analyzer/src/generated/parser.dart' as analyzer; -import 'package:analyzer/src/generated/sdk.dart'; import 'package:analyzer/src/generated/source_io.dart'; -import 'package:analyzer/src/source/package_map_resolver.dart'; +import 'package:analyzer/src/test_utilities/mock_sdk.dart'; import 'package:analyzer/src/test_utilities/resource_provider_mixin.dart'; -import 'package:analyzer/src/dart/analysis/byte_store.dart'; -import 'package:analyzer/src/dart/analysis/performance_logger.dart'; -import 'mock_sdk.dart'; import 'src/utilities/flutter_util.dart'; /** @@ -48,25 +42,25 @@ */ typedef void _ElementVisitorFunction(Element element); -class AbstractContextTest extends Object with ResourceProviderMixin { - DartSdk sdk; - Map<String, List<Folder>> packageMap; - UriResolver resourceResolver; - - StringBuffer _logBuffer = new StringBuffer(); +class AbstractContextTest with ResourceProviderMixin { FileContentOverlay fileContentOverlay = new FileContentOverlay(); AnalysisDriver _driver; AnalysisDriver get driver => _driver; + AnalysisSession get session => driver.currentSession; + + /// The file system specific `/home/test/pubspec.yaml` path. + String get testPubspecPath => convertPath('/home/test/pubspec.yaml'); + void addFlutterPackage() { - addMetaPackageSource(); + addMetaPackage(); Folder libFolder = configureFlutterPackage(resourceProvider); - packageMap['flutter'] = [libFolder]; - configureDriver(); + _addTestPackageDependency('flutter', libFolder.parent.path); } - Source addMetaPackageSource() => addPackageSource('meta', 'meta.dart', r''' + void addMetaPackage() { + addPackageFile('meta', 'meta.dart', r''' library meta; const _IsTest isTest = const _IsTest(); @@ -88,13 +82,15 @@ const _IsTestGroup(); } '''); + } - Source addPackageSource(String packageName, String filePath, String content) { - packageMap[packageName] = [newFolder('/pubcache/$packageName/lib')]; - File file = - newFile('/pubcache/$packageName/lib/$filePath', content: content); - configureDriver(); - return file.createSource(); + /// Add a new file with the given [pathInLib] to the package with the + /// given [packageName]. Then ensure that the test package depends on the + /// [packageName]. + File addPackageFile(String packageName, String pathInLib, String content) { + var packagePath = '/.pub-cache/$packageName'; + _addTestPackageDependency(packageName, packagePath); + return newFile('$packagePath/lib/$pathInLib', content: content); } Source addSource(String path, String content, [Uri uri]) { @@ -106,52 +102,22 @@ return source; } - /** - * Re-configure the driver. This is necessary, for example, after defining a - * new package that test code will reference. - */ - void configureDriver() { - driver.configure(); - } - - void configurePreviewDart2() { - driver.configure( - analysisOptions: new AnalysisOptionsImpl.from(driver.analysisOptions) - ..previewDart2 = true); - } - - void processRequiredPlugins() { - AnalysisEngine.instance.processRequiredPlugins(); - } - Future<CompilationUnit> resolveLibraryUnit(Source source) async { - return (await driver.getResult(source.fullName))?.unit; + var resolveResult = await session.getResolvedUnit(source.fullName); + return resolveResult.unit; } void setUp() { - processRequiredPlugins(); setupResourceProvider(); - sdk = new MockSdk(resourceProvider: resourceProvider); - resourceResolver = new ResourceUriResolver(resourceProvider); - packageMap = new Map<String, List<Folder>>(); - PackageMapUriResolver packageResolver = - new PackageMapUriResolver(resourceProvider, packageMap); - SourceFactory sourceFactory = new SourceFactory( - [new DartUriResolver(sdk), packageResolver, resourceResolver]); - PerformanceLog log = new PerformanceLog(_logBuffer); - AnalysisDriverScheduler scheduler = new AnalysisDriverScheduler(log); - _driver = new AnalysisDriver( - scheduler, - log, - resourceProvider, - new MemoryByteStore(), - fileContentOverlay, - new ContextRoot(resourceProvider.convertPath('/project'), [], - pathContext: resourceProvider.pathContext), - sourceFactory, - new AnalysisOptionsImpl()..useFastaParser = analyzer.Parser.useFasta); - scheduler.start(); - AnalysisEngine.instance.logger = PrintLogger.instance; + + new MockSdk(resourceProvider: resourceProvider); + + newFolder('/home/test'); + newFile('/home/test/.packages', content: r''' +test:file:///home/test/lib +'''); + + _createDriver(); } void setupResourceProvider() {} @@ -160,28 +126,42 @@ AnalysisEngine.instance.clearCaches(); AnalysisEngine.instance.logger = null; } -} -/** - * Instances of the class [PrintLogger] print all of the errors. - */ -class PrintLogger implements Logger { - static final Logger instance = new PrintLogger(); - - @override - void logError(String message, [CaughtException exception]) { - print(message); - if (exception != null) { - print(exception); - } + /// Update `/home/test/pubspec.yaml` and create the driver. + void updateTestPubspecFile(String content) { + newFile(testPubspecPath, content: content); + _createDriver(); } - @override - void logInformation(String message, [CaughtException exception]) { - print(message); - if (exception != null) { - print(exception); + void _addTestPackageDependency(String name, String rootPath) { + var packagesFile = getFile('/home/test/.packages'); + var packagesContent = packagesFile.readAsStringSync(); + + // Ignore if there is already the same package dependency. + if (packagesContent.contains('$name:file://')) { + return; } + + packagesContent += '$name:${toUri('$rootPath/lib')}\n'; + + packagesFile.writeAsStringSync(packagesContent); + + _createDriver(); + } + + void _createDriver() { + var collection = AnalysisContextCollectionImpl( + includedPaths: [convertPath('/home')], + enableIndex: true, + fileContentOverlay: fileContentOverlay, + resourceProvider: resourceProvider, + sdkPath: convertPath('/sdk'), + ); + + var testPath = convertPath('/home/test'); + DriverBasedAnalysisContext context = collection.contextFor(testPath); + + _driver = context.driver; } }
diff --git a/pkg/analysis_server/test/abstract_single_unit.dart b/pkg/analysis_server/test/abstract_single_unit.dart index 78e2280..b0901725 100644 --- a/pkg/analysis_server/test/abstract_single_unit.dart +++ b/pkg/analysis_server/test/abstract_single_unit.dart
@@ -1,14 +1,14 @@ -// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file +// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. import 'dart:async'; +import 'package:analyzer/dart/analysis/results.dart'; import 'package:analyzer/dart/ast/ast.dart'; import 'package:analyzer/dart/ast/visitor.dart'; import 'package:analyzer/dart/element/element.dart'; import 'package:analyzer/error/error.dart'; -import 'package:analyzer/src/dart/analysis/driver.dart'; import 'package:analyzer/src/dart/ast/utilities.dart'; import 'package:analyzer/src/dart/error/hint_codes.dart'; import 'package:analyzer/src/generated/java_engine.dart'; @@ -23,7 +23,7 @@ String testCode; String testFile; Source testSource; - AnalysisResult testAnalysisResult; + ResolvedUnitResult testAnalysisResult; CompilationUnit testUnit; CompilationUnitElement testUnitElement; LibraryElement testLibraryElement; @@ -64,7 +64,7 @@ AstNode findNodeAtOffset(int offset, [Predicate<AstNode> predicate]) { AstNode result = new NodeLocator(offset).searchWithin(testUnit); if (result != null && predicate != null) { - result = result.getAncestor(predicate); + result = result.thisOrAncestorMatching(predicate); } return result; } @@ -112,7 +112,7 @@ Future<void> resolveTestUnit(String code) async { addTestSource(code); - testAnalysisResult = await driver.getResult(convertPath(testFile)); + testAnalysisResult = await session.getResolvedUnit(testFile); testUnit = testAnalysisResult.unit; if (verifyNoTestUnitErrors) { expect(testAnalysisResult.errors.where((AnalysisError error) { @@ -132,7 +132,7 @@ @override void setUp() { super.setUp(); - testFile = resourceProvider.convertPath('/project/test.dart'); + testFile = convertPath('/home/test/lib/test.dart'); } }
diff --git a/pkg/analysis_server/test/analysis/get_errors_test.dart b/pkg/analysis_server/test/analysis/get_errors_test.dart index 8649fcc..cb0baa7 100644 --- a/pkg/analysis_server/test/analysis/get_errors_test.dart +++ b/pkg/analysis_server/test/analysis/get_errors_test.dart
@@ -67,13 +67,6 @@ } @failingTest - test_fileDoesNotExist() { - // Broken under the new driver. - String file = convertPath('$projectPath/doesNotExist.dart'); - return _checkInvalid(file); - } - - @failingTest test_fileWithoutContext() { // Broken under the new driver. String file = convertPath('/outside.dart'); @@ -112,25 +105,6 @@ expect(errors, isEmpty); } - @failingTest - test_removeContextAfterRequest() async { - // Broken under the new driver. - addTestFile(''' -main() { - print(42) -} -'''); - // handle the request synchronously - Request request = _createGetErrorsRequest(testFile); - server.handleRequest(request); - // remove context, causes sending an "invalid file" error - deleteFolder(projectPath); - // wait for an error response - Response response = await serverChannel.waitForResponse(request); - expect(response.error, isNotNull); - expect(response.error.code, RequestErrorCode.GET_ERRORS_INVALID_FILE); - } - Future _checkInvalid(String file) async { Request request = _createGetErrorsRequest(file); Response response = await serverChannel.sendRequest(request);
diff --git a/pkg/analysis_server/test/analysis/get_navigation_test.dart b/pkg/analysis_server/test/analysis/get_navigation_test.dart index 20f6b0f..d620a0d 100644 --- a/pkg/analysis_server/test/analysis/get_navigation_test.dart +++ b/pkg/analysis_server/test/analysis/get_navigation_test.dart
@@ -75,7 +75,7 @@ } test_fileOutsideOfRoot() async { - testFile = resourceProvider.convertPath('/outside.dart'); + testFile = convertPath('/outside.dart'); addTestFile(''' main() { var test = 0;
diff --git a/pkg/analysis_server/test/analysis/get_signature_test.dart b/pkg/analysis_server/test/analysis/get_signature_test.dart index fdf651e..10567ce 100644 --- a/pkg/analysis_server/test/analysis/get_signature_test.dart +++ b/pkg/analysis_server/test/analysis/get_signature_test.dart
@@ -116,6 +116,21 @@ equals(new ParameterInfo(ParameterKind.NAMED, "length", "int"))); } + test_does_not_walk_up_over_closure() async { + addTestFile(''' +one(String name, int length) {} +main() { + one("Danny", () { + /*^*/ + }); +} +'''); + var result = await prepareRawSignature('/*^*/'); + expect(result.error, isNotNull); + expect(result.error.code, + equals(RequestErrorCode.GET_SIGNATURE_UNKNOWN_FUNCTION)); + } + test_error_file_invalid_path() async { var result = await prepareRawSignatureAt(0, file: ':\\/?*'); expect(result.error, isNotNull); @@ -125,10 +140,10 @@ test_error_file_not_analyzed() async { var result = await prepareRawSignatureAt(0, - file: resourceProvider.convertPath('/not/in/project.dart')); + file: convertPath('/not/in/project.dart')); expect(result.error, isNotNull); - expect(result.error.code, - equals(RequestErrorCode.GET_SIGNATURE_UNKNOWN_FUNCTION)); + expect( + result.error.code, equals(RequestErrorCode.GET_SIGNATURE_INVALID_FILE)); } test_error_function_unknown() async { @@ -438,19 +453,4 @@ expect(result.parameters[1], equals(new ParameterInfo(ParameterKind.NAMED, "length", "int"))); } - - test_does_not_walk_up_over_closure() async { - addTestFile(''' -one(String name, int length) {} -main() { - one("Danny", () { - /*^*/ - }); -} -'''); - var result = await prepareRawSignature('/*^*/'); - expect(result.error, isNotNull); - expect(result.error.code, - equals(RequestErrorCode.GET_SIGNATURE_UNKNOWN_FUNCTION)); - } }
diff --git a/pkg/analysis_server/test/analysis_abstract.dart b/pkg/analysis_server/test/analysis_abstract.dart index 3610b68..8415bc9 100644 --- a/pkg/analysis_server/test/analysis_abstract.dart +++ b/pkg/analysis_server/test/analysis_abstract.dart
@@ -1,4 +1,4 @@ -// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file +// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. @@ -18,6 +18,7 @@ import 'package:analyzer/src/dart/analysis/driver.dart'; import 'package:analyzer/src/generated/engine.dart'; import 'package:analyzer/src/generated/sdk.dart'; +import 'package:analyzer/src/test_utilities/mock_sdk.dart'; import 'package:analyzer/src/test_utilities/resource_provider_mixin.dart'; import 'package:analyzer_plugin/protocol/protocol.dart' as plugin; import 'package:analyzer_plugin/protocol/protocol_generated.dart' as plugin; @@ -26,7 +27,6 @@ import 'package:test/test.dart'; import 'package:watcher/watcher.dart'; -import 'mock_sdk.dart'; import 'mocks.dart'; int findIdentifierLength(String search) { @@ -47,7 +47,7 @@ /** * An abstract base for all 'analysis' domain tests. */ -class AbstractAnalysisTest extends Object with ResourceProviderMixin { +class AbstractAnalysisTest with ResourceProviderMixin { bool generateSummaryFiles = false; MockServerChannel serverChannel; TestPluginManager pluginManager; @@ -120,7 +120,7 @@ serverChannel, resourceProvider, options, - new DartSdkManager(resourceProvider.convertPath('/'), true), + new DartSdkManager(resourceProvider.convertPath('/sdk'), true), InstrumentationService.NULL_SERVICE); } @@ -194,9 +194,9 @@ void setUp() { serverChannel = new MockServerChannel(); - projectPath = resourceProvider.convertPath('/project'); - testFolder = resourceProvider.convertPath('/project/bin'); - testFile = resourceProvider.convertPath('/project/bin/test.dart'); + projectPath = convertPath('/project'); + testFolder = convertPath('/project/bin'); + testFile = convertPath('/project/bin/test.dart'); pluginManager = new TestPluginManager(); server = createAnalysisServer(); server.pluginManager = pluginManager;
diff --git a/pkg/analysis_server/test/analysis_server_test.dart b/pkg/analysis_server/test/analysis_server_test.dart index 789f634..8a9ea74 100644 --- a/pkg/analysis_server/test/analysis_server_test.dart +++ b/pkg/analysis_server/test/analysis_server_test.dart
@@ -1,4 +1,4 @@ -// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file +// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. @@ -11,15 +11,13 @@ import 'package:analysis_server/src/domain_server.dart'; import 'package:analyzer/file_system/file_system.dart'; import 'package:analyzer/instrumentation/instrumentation.dart'; -import 'package:analyzer/src/generated/engine.dart'; import 'package:analyzer/src/generated/sdk.dart'; +import 'package:analyzer/src/test_utilities/mock_sdk.dart'; import 'package:analyzer/src/test_utilities/resource_provider_mixin.dart'; import 'package:analyzer_plugin/protocol/protocol_common.dart'; -import 'package:plugin/manager.dart'; import 'package:test/test.dart'; import 'package:test_reflective_loader/test_reflective_loader.dart'; -import 'mock_sdk.dart'; import 'mocks.dart'; main() { @@ -29,7 +27,7 @@ } @reflectiveTest -class AnalysisServerTest extends Object with ResourceProviderMixin { +class AnalysisServerTest with ResourceProviderMixin { MockServerChannel channel; AnalysisServer server; @@ -82,13 +80,7 @@ } } - void processRequiredPlugins() { - ExtensionManager manager = new ExtensionManager(); - manager.processPlugins(AnalysisEngine.instance.requiredPlugins); - } - void setUp() { - processRequiredPlugins(); channel = new MockServerChannel(); // Create an SDK in the mock file system. new MockSdk(resourceProvider: resourceProvider); @@ -96,7 +88,7 @@ channel, resourceProvider, new AnalysisServerOptions(), - new DartSdkManager(convertPath('/'), false), + new DartSdkManager(convertPath('/sdk'), false), InstrumentationService.NULL_SERVICE); } @@ -114,8 +106,7 @@ var pkgFolder = convertPath('/pkg'); newFolder(pkgFolder); newFolder(join(pkgFolder, 'lib')); - newFile(join(pkgFolder, 'lib', 'test.dart'), - content: 'class C {}'); + newFile(join(pkgFolder, 'lib', 'test.dart'), content: 'class C {}'); server.setAnalysisRoots('0', [pkgFolder], [], {}); // Pump the event queue to make sure the server has finished any // analysis.
diff --git a/pkg/analysis_server/test/completion_test.dart b/pkg/analysis_server/test/completion_test.dart index 5bed630..50b8449 100644 --- a/pkg/analysis_server/test/completion_test.dart +++ b/pkg/analysis_server/test/completion_test.dart
@@ -1709,8 +1709,7 @@ buildTests( 'testLibrary002', '''t2() {var q=[0],z=q.!1length;q.!2clear();}''', - <String>["1+length", "1+isEmpty", "2+clear"], - failingTests: '1'); + <String>["1+length", "1+isEmpty", "2+clear"]); // TODO Include corelib analysis buildTests('testLibrary003', '''class X{var q; f() {q.!1a!2}}''',
diff --git a/pkg/analysis_server/test/context_manager_test.dart b/pkg/analysis_server/test/context_manager_test.dart index e04d0de..0bfbe6b 100644 --- a/pkg/analysis_server/test/context_manager_test.dart +++ b/pkg/analysis_server/test/context_manager_test.dart
@@ -1,4 +1,4 @@ -// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file +// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. @@ -24,6 +24,7 @@ import 'package:analyzer/src/generated/source_io.dart'; import 'package:analyzer/src/services/lint.dart'; import 'package:analyzer/src/summary/summary_file_builder.dart'; +import 'package:analyzer/src/test_utilities/mock_sdk.dart'; import 'package:analyzer/src/test_utilities/resource_provider_mixin.dart'; import 'package:analyzer/src/util/glob.dart'; import 'package:linter/src/rules.dart'; @@ -34,7 +35,6 @@ import 'package:test_reflective_loader/test_reflective_loader.dart'; import 'package:watcher/watcher.dart'; -import 'mock_sdk.dart'; import 'src/plugin/plugin_manager_test.dart'; main() { @@ -500,7 +500,7 @@ var testLibUri = resourceProvider.pathContext.toUri(testLib); resourceProvider.newFile(packagespecPath, 'unittest:$testLibUri'); String libPath = '$projPath/${ContextManagerTest.LIB_NAME}'; - File mainFile = newFile('$libPath/main.dart', content: ''); + File mainFile = newFile('$libPath/main.dart'); Source source = mainFile.createSource(); manager.setRoots(<String>[projPath], <String>[], <String, String>{}); @@ -586,8 +586,8 @@ // create files newFile('$subProjectA/pubspec.yaml', content: 'pubspec'); newFile('$subProjectB/pubspec.yaml', content: 'pubspec'); - newFile('$subProjectA/.packages', content: ''); - newFile('$subProjectB/.packages', content: ''); + newFile('$subProjectA/.packages'); + newFile('$subProjectB/.packages'); newFile(rootFile, content: 'library root;'); newFile(subProjectA_file, content: 'library a;'); @@ -1641,7 +1641,7 @@ } } -abstract class ContextManagerTest extends Object with ResourceProviderMixin { +abstract class ContextManagerTest with ResourceProviderMixin { /** * The name of the 'bin' directory. */ @@ -1741,7 +1741,7 @@ resourceProvider.newFolder(projPath); // Create an SDK in the mock file system. new MockSdk(generateSummaryFiles: true, resourceProvider: resourceProvider); - DartSdkManager sdkManager = new DartSdkManager(convertPath('/'), true); + DartSdkManager sdkManager = new DartSdkManager(convertPath('/sdk'), true); manager = new ContextManagerImpl( resourceProvider, new FileContentOverlay(), @@ -2167,7 +2167,7 @@ manager.setRoots(<String>[projPath], <String>[], <String, String>{}); await pumpEventQueue(); - AnalysisResult result = await callbacks.currentDriver.getResult(file.path); + var result = await callbacks.currentDriver.getResult(file.path); // Not strong mode - both in the context and the SDK context. // AnalysisContext sdkContext = sourceFactory.dartSdk.context; @@ -2569,7 +2569,7 @@ ContextBuilderOptions builderOptions = new ContextBuilderOptions(); builderOptions.defaultOptions = options; ContextBuilder builder = new ContextBuilder( - resourceProvider, sdkManager, new ContentCache(), + resourceProvider, sdkManager, null, options: builderOptions); return builder; }
diff --git a/pkg/analysis_server/test/domain_analysis_test.dart b/pkg/analysis_server/test/domain_analysis_test.dart index 6bb6343..e50b52f 100644 --- a/pkg/analysis_server/test/domain_analysis_test.dart +++ b/pkg/analysis_server/test/domain_analysis_test.dart
@@ -1,4 +1,4 @@ -// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file +// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. @@ -10,17 +10,15 @@ import 'package:analysis_server/src/analysis_server.dart'; import 'package:analysis_server/src/domain_analysis.dart'; import 'package:analyzer/instrumentation/instrumentation.dart'; -import 'package:analyzer/src/generated/engine.dart'; import 'package:analyzer/src/generated/sdk.dart'; +import 'package:analyzer/src/test_utilities/mock_sdk.dart'; import 'package:analyzer/src/test_utilities/resource_provider_mixin.dart'; import 'package:analyzer_plugin/protocol/protocol_common.dart'; import 'package:analyzer_plugin/protocol/protocol_generated.dart' as plugin; -import 'package:plugin/manager.dart'; import 'package:test/test.dart'; import 'package:test_reflective_loader/test_reflective_loader.dart'; import 'analysis_abstract.dart'; -import 'mock_sdk.dart'; import 'mocks.dart'; main() { @@ -64,8 +62,8 @@ expect(response, isResponseSuccess('0')); // verify that unit is resolved eventually await server.onAnalysisComplete; - var unit = await serverRef.getResolvedCompilationUnit(file); - expect(unit, isNotNull); + var resolvedUnit = await serverRef.getResolvedUnit(file); + expect(resolvedUnit, isNotNull); } test_setAnalysisRoots_included_nonexistentFolder() async { @@ -78,8 +76,8 @@ // Non-existence of /project_a should not prevent files in /project_b // from being analyzed. await server.onAnalysisComplete; - var unit = await serverRef.getResolvedCompilationUnit(fileB); - expect(unit, isNotNull); + var resolvedUnit = await serverRef.getResolvedUnit(fileB); + expect(resolvedUnit, isNotNull); } test_setAnalysisRoots_included_notAbsolute() async { @@ -338,7 +336,7 @@ /** * A helper to test 'analysis.*' requests. */ -class AnalysisTestHelper extends Object with ResourceProviderMixin { +class AnalysisTestHelper with ResourceProviderMixin { MockServerChannel serverChannel; AnalysisServer server; AnalysisDomainHandler handler; @@ -356,7 +354,6 @@ AnalysisTestHelper() { projectPath = convertPath('/project'); testFile = convertPath('/project/bin/test.dart'); - processRequiredPlugins(); serverChannel = new MockServerChannel(); // Create an SDK in the mock file system. new MockSdk(resourceProvider: resourceProvider); @@ -364,7 +361,7 @@ serverChannel, resourceProvider, new AnalysisServerOptions(), - new DartSdkManager(convertPath('/'), false), + new DartSdkManager(convertPath('/sdk'), false), InstrumentationService.NULL_SERVICE); handler = new AnalysisDomainHandler(server); // listen for notifications @@ -518,11 +515,6 @@ expect(response, isResponseSuccess('0')); } - void processRequiredPlugins() { - ExtensionManager manager = new ExtensionManager(); - manager.processPlugins(AnalysisEngine.instance.requiredPlugins); - } - /** * Send an `updateContent` request for [testFile]. */ @@ -661,7 +653,7 @@ } test_afterAnalysis_sdkFile() async { - String file = convertPath('/lib/core/core.dart'); + String file = convertPath('/sdk/lib/core/core.dart'); addTestFile('// no matter'); createProject(); // wait for analysis, no results initially
diff --git a/pkg/analysis_server/test/domain_completion_test.dart b/pkg/analysis_server/test/domain_completion_test.dart index 0566e1f..b3c7c46 100644 --- a/pkg/analysis_server/test/domain_completion_test.dart +++ b/pkg/analysis_server/test/domain_completion_test.dart
@@ -238,7 +238,7 @@ // // We no longer support the analysis of non-dart files. // - testFile = resourceProvider.convertPath('/project/web/test.html'); + testFile = convertPath('/project/web/test.html'); addTestFile(''' <html>^</html> ''');
diff --git a/pkg/analysis_server/test/domain_server_test.dart b/pkg/analysis_server/test/domain_server_test.dart index f7f1fda..1d8389f 100644 --- a/pkg/analysis_server/test/domain_server_test.dart +++ b/pkg/analysis_server/test/domain_server_test.dart
@@ -67,14 +67,9 @@ }); test('shutdown', () async { - expect(server.running, isTrue); - // send request var request = new ServerShutdownParams().toRequest('0'); var response = await serverChannel.sendRequest(request); expect(response, isResponseSuccess('0')); - - // server is down - expect(server.running, isFalse); }); }); }
diff --git a/pkg/analysis_server/test/edit/fixes_test.dart b/pkg/analysis_server/test/edit/fixes_test.dart index 4d07618..c9c5eaa 100644 --- a/pkg/analysis_server/test/edit/fixes_test.dart +++ b/pkg/analysis_server/test/edit/fixes_test.dart
@@ -1,4 +1,4 @@ -// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file +// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. @@ -35,11 +35,12 @@ createProject(); addTestFile(''' main() { - Future<String> x = null; + Completer<String> x = null; } '''); await waitForTasksFinished(); - List<AnalysisErrorFixes> errorFixes = await _getFixesAt('Future<String>'); + List<AnalysisErrorFixes> errorFixes = + await _getFixesAt('Completer<String>'); expect(errorFixes, hasLength(1)); AnalysisError error = errorFixes[0].error; expect(error.severity, AnalysisErrorSeverity.WARNING); @@ -130,7 +131,7 @@ handler: analysisHandler); // Configure the test file. - testFile = resourceProvider.convertPath('/aaa/main.dart'); + testFile = convertPath('/aaa/main.dart'); testCode = 'main() { new Foo(); }'; _addOverlay(testFile, testCode);
diff --git a/pkg/analysis_server/test/integration/analysis/get_errors_nonStandard_sdk_test.dart b/pkg/analysis_server/test/integration/analysis/get_errors_nonStandard_sdk_test.dart index be6e77a..4b102a6 100644 --- a/pkg/analysis_server/test/integration/analysis/get_errors_nonStandard_sdk_test.dart +++ b/pkg/analysis_server/test/integration/analysis/get_errors_nonStandard_sdk_test.dart
@@ -5,13 +5,11 @@ import 'dart:async'; import 'dart:io'; -import 'package:analyzer/src/generated/sdk.dart'; import 'package:analyzer_plugin/protocol/protocol_common.dart'; import 'package:path/path.dart' as path; import 'package:test/test.dart'; import 'package:test_reflective_loader/test_reflective_loader.dart'; -import '../../mock_sdk.dart'; import '../support/integration_tests.dart'; main() { @@ -28,42 +26,56 @@ class AnalysisDomainGetErrorsTest extends AbstractAnalysisServerIntegrationTest { String createNonStandardSdk() { - MockSdkLibrary fakeLibrary = - new MockSdkLibrary('dart:fake', '/lib/fake/fake.dart', ''); - String sdkPath = path.join(sourceDirectory.path, 'sdk'); - StringBuffer librariesContent = new StringBuffer(); - librariesContent.writeln( - 'final Map<String, LibraryInfo> LIBRARIES = const <String, LibraryInfo> {'); - MockSdk.LIBRARIES.toList() - ..add(fakeLibrary) - ..forEach((SdkLibrary library) { - List<String> components = path.posix.split(library.path); - components[0] = sdkPath; - String libraryPath = path.joinAll(components); - new Directory(path.dirname(libraryPath)).createSync(recursive: true); - new File(libraryPath) - .writeAsStringSync((library as MockSdkLibrary).content); + var sdkPath = path.join(sourceDirectory.path, 'sdk'); - String relativePath = path.joinAll(components.sublist(2)); - librariesContent.write('"'); - librariesContent - .write(library.shortName.substring(5)); // Remove the 'dart:' prefix - librariesContent.write('": const LibraryInfo("'); - librariesContent.write(relativePath); - librariesContent.writeln('"),'); - }); - librariesContent.writeln('};'); + new Directory(path.join(sdkPath, 'lib', 'core')) + .createSync(recursive: true); + new Directory(path.join(sdkPath, 'lib', 'async')) + .createSync(recursive: true); + new Directory(path.join(sdkPath, 'lib', 'fake')) + .createSync(recursive: true); - String librariesPath = path.joinAll([ + new File(path.join(sdkPath, 'lib', 'core', 'core.dart')) + .writeAsStringSync(r''' +library dart.core; +import 'dart:async'; +class bool {} +class double {} +class int {} +class num {} +class Object {} +class Map<K, V> {} +class Null {} +class String {} +class Type {} +'''); + + new File(path.join(sdkPath, 'lib', 'async', 'async.dart')) + .writeAsStringSync(r''' +library dart.async; +class Future<T> {} +'''); + + new File(path.join(sdkPath, 'lib', 'fake', 'fake.dart')) + .writeAsStringSync(r''' +class Fake {} +'''); + + var libsDir = path.join( sdkPath, 'lib', '_internal', 'sdk_library_metadata', 'lib', - 'libraries.dart' - ]); - new Directory(path.dirname(librariesPath)).createSync(recursive: true); - new File(librariesPath).writeAsStringSync(librariesContent.toString()); + ); + new Directory(libsDir).createSync(recursive: true); + new File(path.join(libsDir, 'libraries.dart')).writeAsStringSync(r''' +final LIBRARIES = const <String, LibraryInfo> { + "core": const LibraryInfo("core/core.dart"), + "async": const LibraryInfo("async/async.dart"), + "fake": const LibraryInfo("fake/fake.dart"), +}; +'''); return sdkPath; }
diff --git a/pkg/analysis_server/test/integration/analysis/hint_sdk_version_async_exported_from_core_test.dart b/pkg/analysis_server/test/integration/analysis/hint_sdk_version_async_exported_from_core_test.dart new file mode 100644 index 0000000..6703374 --- /dev/null +++ b/pkg/analysis_server/test/integration/analysis/hint_sdk_version_async_exported_from_core_test.dart
@@ -0,0 +1,65 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:test/test.dart'; +import 'package:test_reflective_loader/test_reflective_loader.dart'; + +import '../support/integration_tests.dart'; + +main() { + defineReflectiveSuite(() { + defineReflectiveTests(SdkVersionAsyncExportedFromCoreIntegrationTest); + }); +} + +@reflectiveTest +class SdkVersionAsyncExportedFromCoreIntegrationTest + extends AbstractAnalysisServerIntegrationTest { + test_update_pubspec() async { + var pubspecPath = sourcePath('pubspec.yaml'); + writeFile(pubspecPath, r''' +name: test +environment: + sdk: ^2.0.0 +'''); + + var testPath = sourcePath('lib/test.dart'); + writeFile(testPath, ''' +Future<int> zero() async => 0; +'''); + standardAnalysisSetup(); + + // There is a hint with this SDK version constraint. + await analysisFinished; + expect(currentAnalysisErrors[testPath], hasLength(1)); + + // 2.0.0 -> 2.1.0 + { + writeFile(pubspecPath, r''' +name: test +environment: + sdk: ^2.1.0 +'''); + + // The pubspec.yaml file change has been noticed and processed. + // No more hints. + await analysisFinished; + expect(currentAnalysisErrors[testPath], isEmpty); + } + + // 2.1.0 -> 2.0.0 + { + writeFile(pubspecPath, r''' +name: test +environment: + sdk: ^2.0.0 +'''); + + // The pubspec.yaml file change has been noticed and processed. + // There is a hint again. + await analysisFinished; + expect(currentAnalysisErrors[testPath], hasLength(1)); + } + } +}
diff --git a/pkg/analysis_server/test/integration/analysis/test_all.dart b/pkg/analysis_server/test/integration/analysis/test_all.dart index 99021da..d85814a 100644 --- a/pkg/analysis_server/test/integration/analysis/test_all.dart +++ b/pkg/analysis_server/test/integration/analysis/test_all.dart
@@ -15,6 +15,8 @@ import 'get_reachable_sources_test.dart' as get_reachable_sources_test; import 'highlights2_test.dart' as highlights2_test; import 'highlights_test.dart' as highlights_test; +import 'hint_sdk_version_async_exported_from_core_test.dart' + as hint_sdk_version_async_exported_from_core_test; import 'lint_test.dart' as lint_test; import 'navigation_test.dart' as navigation_test; import 'occurrences_test.dart' as occurrences_test; @@ -47,6 +49,7 @@ get_reachable_sources_test.main(); highlights2_test.main(); highlights_test.main(); + hint_sdk_version_async_exported_from_core_test.main(); lint_test.main(); navigation_test.main(); occurrences_test.main();
diff --git a/pkg/analysis_server/test/lsp/completion_test.dart b/pkg/analysis_server/test/lsp/completion_test.dart new file mode 100644 index 0000000..aa7002c --- /dev/null +++ b/pkg/analysis_server/test/lsp/completion_test.dart
@@ -0,0 +1,276 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:analysis_server/lsp_protocol/protocol_generated.dart'; +import 'package:test/test.dart'; +import 'package:test_reflective_loader/test_reflective_loader.dart'; + +import 'server_abstract.dart'; + +main() { + defineReflectiveSuite(() { + defineReflectiveTests(CompletionTest); + }); +} + +@reflectiveTest +class CompletionTest extends AbstractLspAnalysisServerTest { + test_completionKinds_default() async { + newFile(join(projectFolderPath, 'file.dart')); + newFolder(join(projectFolderPath, 'folder')); + + final content = "import '^';"; + + await initialize(); + await openFile(mainFileUri, withoutMarkers(content)); + final res = await getCompletion(mainFileUri, positionFromMarker(content)); + + final file = res.singleWhere((c) => c.label == 'file.dart'); + final folder = res.singleWhere((c) => c.label == 'folder/'); + final builtin = res.singleWhere((c) => c.label == 'dart:core'); + // Default capabilities include File + Module but not Folder. + expect(file.kind, equals(CompletionItemKind.File)); + // We fall back to Module if Folder isn't supported. + expect(folder.kind, equals(CompletionItemKind.Module)); + expect(builtin.kind, equals(CompletionItemKind.Module)); + } + + test_completionKinds_imports() async { + final content = "import '^';"; + + // Tell the server we support some specific CompletionItemKinds. + await initialize(textDocumentCapabilities: { + 'completion': { + 'completionItemKind': { + 'valueSet': [ + CompletionItemKind.File.toJson(), + CompletionItemKind.Folder.toJson(), + CompletionItemKind.Module.toJson(), + ], + } + }, + }); + await openFile(mainFileUri, withoutMarkers(content)); + final res = await getCompletion(mainFileUri, positionFromMarker(content)); + + final file = res.singleWhere((c) => c.label == 'file.dart'); + final folder = res.singleWhere((c) => c.label == 'folder/'); + final builtin = res.singleWhere((c) => c.label == 'dart:core'); + expect(file.kind, equals(CompletionItemKind.File)); + expect(folder.kind, equals(CompletionItemKind.Folder)); + expect(builtin.kind, equals(CompletionItemKind.Module)); + } + + test_completionKinds_supportedSubset() async { + final content = ''' + class MyClass { + String abcdefghij; + } + + main() { + MyClass a; + a.abc^ + } + '''; + + // Tell the server we only support the Field CompletionItemKind. + await initialize(textDocumentCapabilities: { + 'completion': { + 'completionItemKind': { + 'valueSet': [ + CompletionItemKind.Field.toJson(), + ], + } + }, + }); + await openFile(mainFileUri, withoutMarkers(content)); + final res = await getCompletion(mainFileUri, positionFromMarker(content)); + final kinds = res.map((item) => item.kind).toList(); + + // Ensure we only get nulls or Fields (the sample code contains Classes). + expect( + kinds, + everyElement(anyOf(isNull, equals(CompletionItemKind.Field))), + ); + } + + test_gettersAndSetters() async { + final content = ''' + class MyClass { + String get justGetter => ''; + String set justSetter(String value) {} + String get getterAndSetter => ''; + String set getterAndSetter(String value) {} + } + + main() { + MyClass a; + a.^ + } + '''; + + await initialize(); + await openFile(mainFileUri, withoutMarkers(content)); + final res = await getCompletion(mainFileUri, positionFromMarker(content)); + final getter = res.singleWhere((c) => c.label == 'justGetter'); + final setter = res.singleWhere((c) => c.label == 'justSetter'); + final both = res.singleWhere((c) => c.label == 'getterAndSetter'); + expect(getter.detail, equals('String')); + expect(setter.detail, equals('String')); + expect(both.detail, equals('String')); + [getter, setter, both].forEach((item) { + expect(item.kind, equals(CompletionItemKind.Property)); + }); + } + + test_insideString() async { + final content = ''' + var a = "This is ^a test" + '''; + + await initialize(); + await openFile(mainFileUri, withoutMarkers(content)); + final res = await getCompletion(mainFileUri, positionFromMarker(content)); + expect(res, isEmpty); + } + + test_isDeprecated_notSupported() async { + final content = ''' + class MyClass { + @deprecated + String abcdefghij; + } + + main() { + MyClass a; + a.abc^ + } + '''; + + await initialize(); + await openFile(mainFileUri, withoutMarkers(content)); + final res = await getCompletion(mainFileUri, positionFromMarker(content)); + final item = res.singleWhere((c) => c.label == 'abcdefghij'); + expect(item.deprecated, isNull); + // If the does not say it supports the deprecated flag, we should show + // '(deprecated)' in the details. + expect(item.detail.toLowerCase(), contains('deprecated')); + } + + test_isDeprecated_supported() async { + final content = ''' + class MyClass { + @deprecated + String abcdefghij; + } + + main() { + MyClass a; + a.abc^ + } + '''; + + await initialize(textDocumentCapabilities: { + 'completion': { + 'completionItem': { + 'deprecatedSupport': true, + } + }, + }); + await openFile(mainFileUri, withoutMarkers(content)); + final res = await getCompletion(mainFileUri, positionFromMarker(content)); + final item = res.singleWhere((c) => c.label == 'abcdefghij'); + expect(item.deprecated, isTrue); + // If the client says it supports the deprecated flag, we should not show + // deprecated in the details. + expect(item.detail, isNot(contains('deprecated'))); + } + + test_plainText_simple() async { + final content = ''' + class MyClass { + String abcdefghij; + } + + main() { + MyClass a; + a.abc^ + } + '''; + + await initialize(); + await openFile(mainFileUri, withoutMarkers(content)); + final res = await getCompletion(mainFileUri, positionFromMarker(content)); + expect(res.any((c) => c.label == 'abcdefghij'), isTrue); + final item = res.singleWhere((c) => c.label == 'abcdefghij'); + expect(item.insertTextFormat, equals(InsertTextFormat.PlainText)); + // ignore: deprecated_member_use + expect(item.insertText, anyOf(equals('abcdefghij'), isNull)); + final updated = applyEdits(withoutMarkers(content), [item.textEdit]); + expect(updated, contains('a.abcdefghij')); + } + + test_snippet_simple() async { + final content = ''' + class MyClass { + String abcdefghij; + } + + main() { + MyClass a; + a.abc^ + } + '''; + + await initialize(textDocumentCapabilities: { + 'completion': { + 'completionItem': { + 'snippetSupport': true, + } + } + }); + await openFile(mainFileUri, withoutMarkers(content)); + final res = await getCompletion(mainFileUri, positionFromMarker(content)); + expect(res.any((c) => c.label == 'abcdefghij'), isTrue); + final item = res.singleWhere((c) => c.label == 'abcdefghij'); + // ignore: deprecated_member_use + expect(item.insertText, anyOf(equals('abcdefghij'), isNull)); + expect(item.insertTextFormat, equals(InsertTextFormat.Snippet)); + final updated = applyEdits(withoutMarkers(content), [item.textEdit]); + expect(updated, contains('a.abcdefghij')); + expect(item.kind, equals(CompletionItemKind.Field)); + } + + @failingTest + test_snippet_withSelection() async { + // TODO(dantup): Implement snippet functionality + test. + // Like above, but one that actually has a selectionOffset and results in + // a snippet with tabstop. + fail('NYI'); + } + + test_unopenFile() async { + final content = ''' + class MyClass { + String abcdefghij; + } + + main() { + MyClass a; + a.abc^ + } + '''; + + newFile(mainFilePath, content: withoutMarkers(content)); + await initialize(); + final res = await getCompletion(mainFileUri, positionFromMarker(content)); + expect(res.any((c) => c.label == 'abcdefghij'), isTrue); + final item = res.singleWhere((c) => c.label == 'abcdefghij'); + expect(item.insertTextFormat, equals(InsertTextFormat.PlainText)); + // ignore: deprecated_member_use + expect(item.insertText, anyOf(equals('abcdefghij'), isNull)); + final updated = applyEdits(withoutMarkers(content), [item.textEdit]); + expect(updated, contains('a.abcdefghij')); + } +}
diff --git a/pkg/analysis_server/test/lsp/definition_test.dart b/pkg/analysis_server/test/lsp/definition_test.dart new file mode 100644 index 0000000..4e99a7f --- /dev/null +++ b/pkg/analysis_server/test/lsp/definition_test.dart
@@ -0,0 +1,89 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:analysis_server/lsp_protocol/protocol_generated.dart'; +import 'package:test/test.dart'; +import 'package:test_reflective_loader/test_reflective_loader.dart'; + +import 'server_abstract.dart'; + +main() { + defineReflectiveSuite(() { + defineReflectiveTests(DefinitionTest); + }); +} + +@reflectiveTest +class DefinitionTest extends AbstractLspAnalysisServerTest { + test_acrossFiles() async { + final mainContents = ''' + import 'referenced.dart'; + + main() { + fo^o(); + } + '''; + + final referencedContents = ''' + /// Ensure the function is on a line that + /// does not exist in the mainContents file + /// to ensure we're translating offsets to line/col + /// using the correct file's LineInfo + /// ... + /// ... + /// ... + /// ... + /// ... + [[foo]]() {} + '''; + + final referencedFileUri = + Uri.file(join(projectFolderPath, 'lib', 'referenced.dart')); + + await initialize(); + await openFile(mainFileUri, withoutMarkers(mainContents)); + await openFile(referencedFileUri, withoutMarkers(referencedContents)); + final res = + await getDefinition(mainFileUri, positionFromMarker(mainContents)); + + expect(res, hasLength(1)); + Location loc = res.single; + expect(loc.range, equals(rangeFromMarkers(referencedContents))); + expect(loc.uri, equals(referencedFileUri.toString())); + } + + test_singleFile() async { + final contents = ''' + [[foo]]() { + fo^o(); + } + '''; + + await initialize(); + await openFile(mainFileUri, withoutMarkers(contents)); + final res = await getDefinition(mainFileUri, positionFromMarker(contents)); + + expect(res, hasLength(1)); + Location loc = res.single; + expect(loc.range, equals(rangeFromMarkers(contents))); + expect(loc.uri, equals(mainFileUri.toString())); + } + + test_unopenFile() async { + final contents = ''' + [[foo]]() { + fo^o(); + } + '''; + + newFile(mainFilePath, content: withoutMarkers(contents)); + await initialize(); + final res = await getDefinition(mainFileUri, positionFromMarker(contents)); + + expect(res, hasLength(1)); + Location loc = res.single; + expect(loc.range, equals(rangeFromMarkers(contents))); + expect(loc.uri, equals(mainFileUri.toString())); + } +}
diff --git a/pkg/analysis_server/test/lsp/diagnostic_test.dart b/pkg/analysis_server/test/lsp/diagnostic_test.dart new file mode 100644 index 0000000..430b8a1 --- /dev/null +++ b/pkg/analysis_server/test/lsp/diagnostic_test.dart
@@ -0,0 +1,45 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:test/test.dart'; +import 'package:test_reflective_loader/test_reflective_loader.dart'; + +import 'server_abstract.dart'; + +main() { + defineReflectiveSuite(() { + defineReflectiveTests(DiagnosticTest); + }); +} + +@reflectiveTest +class DiagnosticTest extends AbstractLspAnalysisServerTest { + test_afterDocumentEdits() async { + const initialContents = 'int a = 1;'; + newFile(mainFilePath, content: initialContents); + + await initialize(); + final initialDiagnostics = await waitForDiagnostics(mainFileUri); + expect(initialDiagnostics, hasLength(0)); + + await openFile(mainFileUri, initialContents); + await replaceFile(mainFileUri, 'String a = 1;'); + final updatedDiagnostics = await waitForDiagnostics(mainFileUri); + expect(updatedDiagnostics, hasLength(1)); + } + + test_initialAnalysis() async { + newFile(mainFilePath, content: 'String a = 1;'); + + await initialize(); + final diagnostics = await waitForDiagnostics(mainFileUri); + expect(diagnostics, hasLength(1)); + final diagnostic = diagnostics.first; + expect(diagnostic.code, equals('invalid_assignment')); + expect(diagnostic.range.start.line, equals(0)); + expect(diagnostic.range.start.character, equals(11)); + expect(diagnostic.range.end.line, equals(0)); + expect(diagnostic.range.end.character, equals(12)); + } +}
diff --git a/pkg/analysis_server/test/lsp/document_symbols_test.dart b/pkg/analysis_server/test/lsp/document_symbols_test.dart new file mode 100644 index 0000000..752a160 --- /dev/null +++ b/pkg/analysis_server/test/lsp/document_symbols_test.dart
@@ -0,0 +1,109 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:analysis_server/lsp_protocol/protocol_generated.dart'; +import 'package:test/test.dart'; +import 'package:test_reflective_loader/test_reflective_loader.dart'; + +import 'server_abstract.dart'; + +main() { + defineReflectiveSuite(() { + defineReflectiveTests(DocumentSymbolsTest); + }); +} + +@reflectiveTest +class DocumentSymbolsTest extends AbstractLspAnalysisServerTest { + test_hierarchical() async { + const content = ''' + String topLevel = ''; + class MyClass { + int myField; + MyClass(this.myField); + myMethod() {} + } + '''; + newFile(mainFilePath, content: content); + await initialize(textDocumentCapabilities: { + 'documentSymbol': { + 'hierarchicalDocumentSymbolSupport': true, + }, + }); + + final result = await getDocumentSymbols(mainFileUri.toString()); + final symbols = result.map( + (docsymbols) => docsymbols, + (symbolInfos) => throw 'Expected DocumentSymbols, got SymbolInformations', + ); + + expect(symbols, hasLength(2)); + + final topLevel = symbols[0]; + expect(topLevel.name, equals('topLevel')); + expect(topLevel.kind, equals(SymbolKind.Variable)); + + final myClass = symbols[1]; + expect(myClass.name, equals('MyClass')); + expect(myClass.kind, equals(SymbolKind.Class)); + expect(myClass.children, hasLength(3)); + + final field = myClass.children[0]; + expect(field.name, equals('myField')); + expect(field.kind, equals(SymbolKind.Field)); + + final constructor = myClass.children[1]; + expect(constructor.name, equals('MyClass')); + expect(constructor.kind, equals(SymbolKind.Constructor)); + + final method = myClass.children[2]; + expect(method.name, equals('myMethod')); + expect(method.kind, equals(SymbolKind.Method)); + } + + test_flat() async { + const content = ''' + String topLevel = ''; + class MyClass { + int myField; + MyClass(this.myField); + myMethod() {} + } + '''; + newFile(mainFilePath, content: content); + await initialize(); + + final result = await getDocumentSymbols(mainFileUri.toString()); + final symbols = result.map( + (docsymbols) => throw 'Expected SymbolInformations, got DocumentSymbols', + (symbolInfos) => symbolInfos, + ); + expect(symbols, hasLength(5)); + + final topLevel = symbols[0]; + expect(topLevel.name, equals('topLevel')); + expect(topLevel.kind, equals(SymbolKind.Variable)); + expect(topLevel.containerName, isNull); + + final myClass = symbols[1]; + expect(myClass.name, equals('MyClass')); + expect(myClass.kind, equals(SymbolKind.Class)); + expect(myClass.containerName, isNull); + + final field = symbols[2]; + expect(field.name, equals('myField')); + expect(field.kind, equals(SymbolKind.Field)); + expect(field.containerName, equals(myClass.name)); + + final constructor = symbols[3]; + expect(constructor.name, equals('MyClass')); + expect(constructor.kind, equals(SymbolKind.Constructor)); + expect(constructor.containerName, equals(myClass.name)); + + final method = symbols[4]; + expect(method.name, equals('myMethod')); + expect(method.kind, equals(SymbolKind.Method)); + expect(method.containerName, equals(myClass.name)); + } +}
diff --git a/pkg/analysis_server/test/lsp/file_modification_test.dart b/pkg/analysis_server/test/lsp/file_modification_test.dart new file mode 100644 index 0000000..a7ec93c --- /dev/null +++ b/pkg/analysis_server/test/lsp/file_modification_test.dart
@@ -0,0 +1,110 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:analysis_server/lsp_protocol/protocol_generated.dart'; +import 'package:test/test.dart'; +import 'package:test_reflective_loader/test_reflective_loader.dart'; + +import 'server_abstract.dart'; + +main() { + defineReflectiveSuite(() { + defineReflectiveTests(FileModificationTest); + }); +} + +@reflectiveTest +class FileModificationTest extends AbstractLspAnalysisServerTest { + test_change_badPosition() async { + final contents = ''; + await initialize(); + await openFile(mainFileUri, contents); + + // Since this is a notification and not a request, the server cannot + // respond with an error, but instead sends a ShowMessage notification + // to alert the user to something failing. + final error = await expectErrorNotification<ShowMessageParams>(() async { + await changeFile(mainFileUri, [ + new TextDocumentContentChangeEvent( + new Range(new Position(999, 999), new Position(999, 999)), + null, + ' ', + ) + ]); + }); + + expect(error.message, contains('Invalid line')); + } + + test_change_fullContents() async { + final initialContent = 'int a = 1;'; + final updatedContent = 'int a = 2;'; + + await initialize(); + await openFile(mainFileUri, initialContent); + await replaceFile(mainFileUri, updatedContent); + expect(server.fileContentOverlay[mainFilePath], equals(updatedContent)); + } + + test_change_incremental() async { + final initialContent = '0123456789\n0123456789'; + final expectedUpdatedContent = '0123456789\n01234 89'; + + await initialize(); + await openFile(mainFileUri, initialContent); + await changeFile(mainFileUri, [ + // Replace line1:5-1:8 with spaces. + new TextDocumentContentChangeEvent( + new Range(new Position(1, 5), new Position(1, 8)), + null, + ' ', + ) + ]); + expect(server.fileContentOverlay[mainFilePath], + equals(expectedUpdatedContent)); + } + + test_change_unopenedFile() async { + // It's not valid for a client to send a request to modify a file that it + // has not opened, but Visual Studio has done it in the past so we should + // ensure it generates an obvious error that the user can understand. + final simpleEdit = new TextDocumentContentChangeEvent( + new Range(new Position(1, 1), new Position(1, 1)), + null, + 'test', + ); + await initialize(); + final notificationParams = await expectErrorNotification<ShowMessageParams>( + () => changeFile(mainFileUri, [simpleEdit]), + ); + expect(notificationParams, isNotNull); + expect( + notificationParams.message, + allOf( + contains('because the file was not previously opened'), + contains(mainFilePath), + ), + ); + } + + test_close() async { + final initialContent = 'int a = 1;'; + final updatedContent = 'int a = 2;'; + + await initialize(); + await openFile(mainFileUri, initialContent); + await replaceFile(mainFileUri, updatedContent); + await closeFile(mainFileUri); + expect(server.fileContentOverlay[mainFilePath], isNull); + } + + test_open() async { + const testContent = 'CONTENT'; + + await initialize(); + expect(server.fileContentOverlay[mainFilePath], isNull); + await openFile(mainFileUri, testContent); + expect(server.fileContentOverlay[mainFilePath], equals(testContent)); + } +}
diff --git a/pkg/analysis_server/test/lsp/format_test.dart b/pkg/analysis_server/test/lsp/format_test.dart new file mode 100644 index 0000000..4b58805 --- /dev/null +++ b/pkg/analysis_server/test/lsp/format_test.dart
@@ -0,0 +1,136 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:analysis_server/lsp_protocol/protocol_special.dart'; +import 'package:test/test.dart'; +import 'package:test_reflective_loader/test_reflective_loader.dart'; + +import '../tool/lsp_spec/matchers.dart'; +import 'server_abstract.dart'; + +main() { + defineReflectiveSuite(() { + defineReflectiveTests(FormatTest); + }); +} + +@reflectiveTest +class FormatTest extends AbstractLspAnalysisServerTest { + test_alreadyFormatted() async { + const contents = '''main() { + print('test'); +} +'''; + await initialize(); + await openFile(mainFileUri, contents); + + final formatEdits = await formatDocument(mainFileUri.toString()); + expect(formatEdits, isNull); + } + + test_formatOnType_simple() async { + const contents = ''' + main () + { + + print('test'); + ^} + '''; + final expected = '''main() { + print('test'); +} +'''; + await initialize(); + await openFile(mainFileUri, withoutMarkers(contents)); + + final formatEdits = await formatOnType( + mainFileUri.toString(), positionFromMarker(contents), '}'); + expect(formatEdits, isNotNull); + final formattedContents = applyEdits(contents, formatEdits); + expect(formattedContents, equals(expected)); + } + + test_invalidSyntax() async { + const contents = '''main(((( { + print('test'); +} +'''; + await initialize(); + await openFile(mainFileUri, contents); + + final formatEdits = await formatDocument(mainFileUri.toString()); + expect(formatEdits, isNull); + } + + test_path_doesNotExist() async { + await initialize(); + + await expectLater( + formatDocument( + new Uri.file(join(projectFolderPath, 'missing.dart')).toString()), + throwsA(isResponseError(ServerErrorCodes.InvalidFilePath)), + ); + } + + test_path_invalidFormat() async { + await initialize(); + + await expectLater( + // Add some invalid path characters to the end of a valid file:// URI. + formatDocument(mainFileUri.toString() + '***'), + throwsA(isResponseError(ServerErrorCodes.InvalidFilePath)), + ); + } + + test_path_notFileScheme() async { + await initialize(); + + await expectLater( + formatDocument('a:/a.a'), + throwsA(isResponseError(ServerErrorCodes.InvalidFilePath)), + ); + } + + test_simple() async { + const contents = ''' + main () + { + + print('test'); + } + '''; + final expected = '''main() { + print('test'); +} +'''; + await initialize(); + await openFile(mainFileUri, contents); + + final formatEdits = await formatDocument(mainFileUri.toString()); + expect(formatEdits, isNotNull); + final formattedContents = applyEdits(contents, formatEdits); + expect(formattedContents, equals(expected)); + } + + test_unopenFile() async { + const contents = ''' + main () + { + + print('test'); + } + '''; + final expected = '''main() { + print('test'); +} +'''; + newFile(mainFilePath, content: contents); + await initialize(); + + final formatEdits = await formatDocument(mainFileUri.toString()); + expect(formatEdits, isNotNull); + final formattedContents = applyEdits(contents, formatEdits); + expect(formattedContents, equals(expected)); + } +}
diff --git a/pkg/analysis_server/test/lsp/hover_test.dart b/pkg/analysis_server/test/lsp/hover_test.dart new file mode 100644 index 0000000..1905922 --- /dev/null +++ b/pkg/analysis_server/test/lsp/hover_test.dart
@@ -0,0 +1,219 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:analysis_server/lsp_protocol/protocol_generated.dart'; +import 'package:analysis_server/lsp_protocol/protocol_special.dart'; +import 'package:test/test.dart'; +import 'package:test_reflective_loader/test_reflective_loader.dart'; + +import '../tool/lsp_spec/matchers.dart'; +import 'server_abstract.dart'; + +main() { + defineReflectiveSuite(() { + defineReflectiveTests(HoverTest); + }); +} + +@reflectiveTest +class HoverTest extends AbstractLspAnalysisServerTest { + Future<void> initializeSupportingMarkupContent([ + List<MarkupKind> formats = const [MarkupKind.Markdown], + ]) async { + await initialize(textDocumentCapabilities: { + 'hover': {'contentFormat': formats.map((f) => f.toJson())} + }); + } + + test_hover_bad_position() async { + await initialize(); + await openFile(mainFileUri, ''); + await expectLater( + () => getHover(mainFileUri, new Position(999, 999)), + throwsA(isResponseError(ServerErrorCodes.InvalidFileLineCol)), + ); + } + + test_markdown_isFormattedForDisplay() async { + final content = ''' + /// This is a string. + /// + /// {@template foo} + /// With some [refs] and some + /// [links](https://www.dartlang.org/) + /// {@endTemplate foo} + /// + /// ```dart sample + /// print(); + /// ``` + String [[a^bc]]; + '''; + + final expectedHoverContent = ''' +```dart +String abc +``` + +This is a string. + +With some [refs] and some +[links](https://www.dartlang.org/) + +```dart +print(); +``` + ''' + .trim(); + + await initializeSupportingMarkupContent([MarkupKind.Markdown]); + await openFile(mainFileUri, withoutMarkers(content)); + final hover = await getHover(mainFileUri, positionFromMarker(content)); + expect(hover, isNotNull); + expect(hover.range, equals(rangeFromMarkers(content))); + expect(hover.contents, isNotNull); + final markup = _getMarkupContents(hover); + expect(markup.kind, equals(MarkupKind.Markdown)); + expect(markup.value, equals(expectedHoverContent)); + } + + test_markdown_simple() async { + final content = ''' + /// This is a string. + String [[a^bc]]; + '''; + + await initializeSupportingMarkupContent(); + await openFile(mainFileUri, withoutMarkers(content)); + final hover = await getHover(mainFileUri, positionFromMarker(content)); + expect(hover, isNotNull); + expect(hover.range, equals(rangeFromMarkers(content))); + expect(hover.contents, isNotNull); + final markup = _getMarkupContents(hover); + expect(markup.kind, equals(MarkupKind.Markdown)); + expect(markup.value, contains('This is a string.')); + } + + test_noElement() async { + final content = ''' + String abc; + + ^ + + int a; + '''; + + await initializeSupportingMarkupContent(); + await openFile(mainFileUri, withoutMarkers(content)); + var hover = await getHover(mainFileUri, positionFromMarker(content)); + expect(hover, isNull); + } + + test_plainText_simple() async { + final content = ''' + /// This is a string. + String [[a^bc]]; + '''; + + await initializeSupportingMarkupContent([MarkupKind.PlainText]); + await openFile(mainFileUri, withoutMarkers(content)); + final hover = await getHover(mainFileUri, positionFromMarker(content)); + expect(hover, isNotNull); + expect(hover.range, equals(rangeFromMarkers(content))); + expect(hover.contents, isNotNull); + // Ensure we got PlainText back as the type, even though we're sending the + // same markdown content. + final markup = _getMarkupContents(hover); + expect(markup.kind, equals(MarkupKind.PlainText)); + expect(markup.value, contains('This is a string.')); + } + + test_string_noDocComment() async { + final content = ''' + String [[a^bc]]; + '''; + + final expectedHoverContent = ''' +```dart +String abc +``` + ''' + .trim(); + + await initialize(); + await openFile(mainFileUri, withoutMarkers(content)); + final hover = await getHover(mainFileUri, positionFromMarker(content)); + expect(hover, isNotNull); + expect(hover.range, equals(rangeFromMarkers(content))); + expect(hover.contents, isNotNull); + expect(_getStringContents(hover), equals(expectedHoverContent)); + } + + test_string_reflectsLatestEdits() async { + final original = ''' + /// Original string. + String [[a^bc]]; + '''; + final updated = ''' + /// Updated string. + String [[a^bc]]; + '''; + + await initialize(); + await openFile(mainFileUri, withoutMarkers(original)); + var hover = await getHover(mainFileUri, positionFromMarker(original)); + var contents = _getStringContents(hover); + expect(contents, contains('Original')); + + await replaceFile(mainFileUri, withoutMarkers(updated)); + hover = await getHover(mainFileUri, positionFromMarker(updated)); + contents = _getStringContents(hover); + expect(contents, contains('Updated')); + } + + test_string_simple() async { + final content = ''' + /// This is a string. + String [[a^bc]]; + '''; + + await initialize(); + await openFile(mainFileUri, withoutMarkers(content)); + final hover = await getHover(mainFileUri, positionFromMarker(content)); + expect(hover, isNotNull); + expect(hover.range, equals(rangeFromMarkers(content))); + expect(hover.contents, isNotNull); + final contents = _getStringContents(hover); + expect(contents, contains('This is a string.')); + } + + test_unopenFile() async { + final content = ''' + /// This is a string. + String [[a^bc]]; + '''; + + newFile(mainFilePath, content: withoutMarkers(content)); + await initialize(); + final hover = await getHover(mainFileUri, positionFromMarker(content)); + expect(hover, isNotNull); + expect(hover.range, equals(rangeFromMarkers(content))); + expect(hover.contents, isNotNull); + final markup = _getStringContents(hover); + expect(markup, contains('This is a string.')); + } + + MarkupContent _getMarkupContents(Hover hover) { + return hover.contents.map( + (t1) => throw 'Hover contents were String, not MarkupContent', + (t2) => t2, + ); + } + + String _getStringContents(Hover hover) { + return hover.contents.map( + (t1) => t1, + (t2) => throw 'Hover contents were MarkupContent, not String', + ); + } +}
diff --git a/pkg/analysis_server/test/lsp/initialization_test.dart b/pkg/analysis_server/test/lsp/initialization_test.dart new file mode 100644 index 0000000..ed25a40 --- /dev/null +++ b/pkg/analysis_server/test/lsp/initialization_test.dart
@@ -0,0 +1,81 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:analysis_server/lsp_protocol/protocol_generated.dart'; +import 'package:analysis_server/lsp_protocol/protocol_special.dart'; +import 'package:test/test.dart'; +import 'package:test_reflective_loader/test_reflective_loader.dart'; + +import 'server_abstract.dart'; + +main() { + defineReflectiveSuite(() { + defineReflectiveTests(InitializationTest); + }); +} + +@reflectiveTest +class InitializationTest extends AbstractLspAnalysisServerTest { + test_initialize() async { + final response = await initialize(); + expect(response, isNotNull); + expect(response.error, isNull); + expect(response.result, isNotNull); + expect(response.result, TypeMatcher<InitializeResult>()); + InitializeResult result = response.result; + expect(result.capabilities, isNotNull); + // Check some basic capabilities that are unlikely to change. + expect(result.capabilities.textDocumentSync, isNotNull); + result.capabilities.textDocumentSync.map( + (options) { + // We'll always request open/closed notifications and incremental updates. + expect(options.openClose, isTrue); + expect(options.change, equals(TextDocumentSyncKind.Incremental)); + }, + (_) => + throw 'Expected textDocumentSync capabilities to be a $TextDocumentSyncOptions', + ); + } + + test_initialize_onlyAllowedOnce() async { + await initialize(); + final response = await initialize(); + expect(response, isNotNull); + expect(response.result, isNull); + expect(response.error, isNotNull); + expect( + response.error.code, equals(ServerErrorCodes.ServerAlreadyInitialized)); + } + + test_uninitialized_dropsNotifications() async { + final notification = + makeNotification(new Method.fromJson('randomNotification'), null); + final nextNotification = channel.errorNotificationsFromServer.first; + channel.sendNotificationToServer(notification); + + // Wait up to 1sec to ensure no error/log notifications were sent back. + var didTimeout = false; + final notificationFromServer = await nextNotification.timeout( + const Duration(seconds: 1), + onTimeout: () { + didTimeout = true; + }, + ); + + expect(notificationFromServer, isNull); + expect(didTimeout, isTrue); + } + + test_uninitialized_rejectsRequests() async { + final request = makeRequest(new Method.fromJson('randomRequest'), null); + final logParams = await expectErrorNotification<LogMessageParams>(() async { + final response = await channel.sendRequestToServer(request); + expect(response.id, equals(request.id)); + expect(response.result, isNull); + expect(response.error, isNotNull); + expect(response.error.code, ErrorCodes.ServerNotInitialized); + }); + expect(logParams.type, equals(MessageType.Error)); + } +}
diff --git a/pkg/analysis_server/test/lsp/references_test.dart b/pkg/analysis_server/test/lsp/references_test.dart new file mode 100644 index 0000000..bd36c11 --- /dev/null +++ b/pkg/analysis_server/test/lsp/references_test.dart
@@ -0,0 +1,141 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:analysis_server/lsp_protocol/protocol_generated.dart'; +import 'package:test/test.dart'; +import 'package:test_reflective_loader/test_reflective_loader.dart'; + +import 'server_abstract.dart'; + +main() { + defineReflectiveSuite(() { + defineReflectiveTests(ReferencesTest); + }); +} + +@reflectiveTest +class ReferencesTest extends AbstractLspAnalysisServerTest { + test_acrossFiles_includeDeclaration() async { + final mainContents = ''' + import 'referenced.dart'; + + main() { + [[foo]](); + } + '''; + + final referencedContents = ''' + /// Ensure the function is on a line that + /// does not exist in the mainContents file + /// to ensure we're translating offsets to line/col + /// using the correct file's LineInfo + /// ... + /// ... + /// ... + /// ... + /// ... + [[^foo]]() {} + '''; + + final referencedFileUri = + Uri.file(join(projectFolderPath, 'lib', 'referenced.dart')); + + await initialize(); + await openFile(mainFileUri, withoutMarkers(mainContents)); + await openFile(referencedFileUri, withoutMarkers(referencedContents)); + final res = await getReferences( + referencedFileUri, + positionFromMarker(referencedContents), + includeDeclarations: true, + ); + + // Ensure both the reference and the declaration are included. + expect(res, hasLength(2)); + expect( + res, + contains(new Location( + mainFileUri.toString(), rangeFromMarkers(mainContents)))); + expect( + res, + contains(new Location(referencedFileUri.toString(), + rangeFromMarkers(referencedContents)))); + } + + test_acrossFiles_withoutDeclaration() async { + final mainContents = ''' + import 'referenced.dart'; + + main() { + [[foo]](); + } + '''; + + final referencedContents = ''' + /// Ensure the function is on a line that + /// does not exist in the mainContents file + /// to ensure we're translating offsets to line/col + /// using the correct file's LineInfo + /// ... + /// ... + /// ... + /// ... + /// ... + ^foo() {} + '''; + + final referencedFileUri = + Uri.file(join(projectFolderPath, 'lib', 'referenced.dart')); + + await initialize(); + await openFile(mainFileUri, withoutMarkers(mainContents)); + await openFile(referencedFileUri, withoutMarkers(referencedContents)); + final res = await getReferences( + referencedFileUri, positionFromMarker(referencedContents)); + + expect(res, hasLength(1)); + Location loc = res.single; + expect(loc.range, equals(rangeFromMarkers(mainContents))); + expect(loc.uri, equals(mainFileUri.toString())); + } + + test_singleFile_withoutDeclaration() async { + final contents = ''' + f^oo() { + [[foo]](); + } + '''; + + await initialize(); + await openFile(mainFileUri, withoutMarkers(contents)); + final res = await getReferences(mainFileUri, positionFromMarker(contents)); + + expect(res, hasLength(1)); + expect( + res, + contains( + new Location(mainFileUri.toString(), rangeFromMarkers(contents)), + ), + ); + } + + test_unopenFile() async { + final contents = ''' + f^oo() { + [[foo]](); + } + '''; + + newFile(mainFilePath, content: withoutMarkers(contents)); + await initialize(); + final res = await getReferences(mainFileUri, positionFromMarker(contents)); + + expect(res, hasLength(1)); + expect( + res, + contains( + new Location(mainFileUri.toString(), rangeFromMarkers(contents)), + ), + ); + } +}
diff --git a/pkg/analysis_server/test/lsp/server_abstract.dart b/pkg/analysis_server/test/lsp/server_abstract.dart new file mode 100644 index 0000000..368b330 --- /dev/null +++ b/pkg/analysis_server/test/lsp/server_abstract.dart
@@ -0,0 +1,377 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'dart:async'; + +import 'package:analysis_server/lsp_protocol/protocol_generated.dart'; +import 'package:analysis_server/lsp_protocol/protocol_special.dart'; +import 'package:analysis_server/src/analysis_server.dart'; +import 'package:analysis_server/src/lsp/lsp_analysis_server.dart'; +import 'package:analysis_server/src/lsp/mapping.dart'; +import 'package:analyzer/instrumentation/instrumentation.dart'; +import 'package:analyzer/source/line_info.dart'; +import 'package:analyzer/src/generated/sdk.dart'; +import 'package:analyzer/src/test_utilities/mock_sdk.dart'; +import 'package:analyzer/src/test_utilities/resource_provider_mixin.dart'; +import 'package:test/test.dart'; + +import '../mocks.dart'; + +const dartLanguageId = 'dart'; + +/// Useful for debugging locally, setting this to true will cause all JSON +/// communication to be printed to stdout. +const debugPrintCommunication = false; + +abstract class AbstractLspAnalysisServerTest with ResourceProviderMixin { + static const positionMarker = '^'; + static const rangeMarkerStart = '[['; + static const rangeMarkerEnd = ']]'; + static const allMarkers = [positionMarker, rangeMarkerStart, rangeMarkerEnd]; + static final allMarkersPattern = + new RegExp(allMarkers.map(RegExp.escape).join('|')); + MockLspServerChannel channel; + LspAnalysisServer server; + + int _id = 0; + String projectFolderPath, mainFilePath; + Uri mainFileUri; + + final emptyTextDocumentClientCapabilities = + new TextDocumentClientCapabilities( + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null); + + String applyEdits(String oldContent, List<TextEdit> changes) { + String newContent = oldContent; + // Complex text manipulations are described with an array of TextEdit's, + // representing a single change to the document. + // + // All text edits ranges refer to positions in the original document. Text + // edits ranges must never overlap, that means no part of the original + // document must be manipulated by more than one edit. However, it is possible + // that multiple edits have the same start position: multiple inserts, or any + // number of inserts followed by a single remove or replace edit. If multiple + // inserts have the same position, the order in the array defines the order in + // which the inserted strings appear in the resulting text. + if (changes.length > 1) { + // TODO(dantup): Implement multi-edit edits. + throw 'Test helper applyEdits does not support applying multiple edits'; + } else if (changes.length == 1) { + final change = changes.single; + final startPos = change.range.start; + final endPos = change.range.end; + final lineInfo = LineInfo.fromContent(newContent); + final start = + lineInfo.getOffsetOfLine(startPos.line) + startPos.character; + final end = lineInfo.getOffsetOfLine(endPos.line) + endPos.character; + newContent = newContent.replaceRange(start, end, change.newText); + } + + return newContent; + } + + Future changeFile( + Uri uri, List<TextDocumentContentChangeEvent> changes) async { + var notification = makeNotification( + Method.textDocument_didChange, + new DidChangeTextDocumentParams( + new VersionedTextDocumentIdentifier(1, uri.toString()), changes), + ); + channel.sendNotificationToServer(notification); + await pumpEventQueue(); + } + + Future closeFile(Uri uri) async { + var notification = makeNotification( + Method.textDocument_didClose, + new DidCloseTextDocumentParams( + new TextDocumentIdentifier(uri.toString())), + ); + channel.sendNotificationToServer(notification); + await pumpEventQueue(); + } + + Future<T> expectErrorNotification<T>( + FutureOr<void> f(), { + Duration timeout = const Duration(seconds: 5), + }) async { + final firstError = channel.errorNotificationsFromServer.first; + await f(); + + final notificationFromServer = await firstError.timeout(timeout); + + expect(notificationFromServer, isNotNull); + return notificationFromServer.params as T; + } + + /// Sends a request to the server and unwraps the result. Throws if the + /// response was not successful or returned an error. + Future<T> expectSuccessfulResponseTo<T>(RequestMessage request) async { + final resp = await channel.sendRequestToServer(request); + if (resp.error != null) { + throw resp.error; + } else { + return resp.result as T; + } + } + + Future<List<TextEdit>> formatDocument(String fileUri) async { + final request = makeRequest( + Method.textDocument_formatting, + new DocumentFormattingParams( + new TextDocumentIdentifier(fileUri), + new FormattingOptions(2, true), // These currently don't do anything + ), + ); + return expectSuccessfulResponseTo(request); + } + + Future<List<TextEdit>> formatOnType( + String fileUri, Position pos, String character) async { + final request = makeRequest( + Method.textDocument_onTypeFormatting, + new DocumentOnTypeFormattingParams( + new TextDocumentIdentifier(fileUri), + pos, + character, + new FormattingOptions(2, true), // These currently don't do anything + ), + ); + return expectSuccessfulResponseTo(request); + } + + Future<List<CompletionItem>> getCompletion(Uri uri, Position pos, + {CompletionContext context}) async { + final request = makeRequest( + Method.textDocument_completion, + new CompletionParams( + context, + new TextDocumentIdentifier(uri.toString()), + pos, + ), + ); + return expectSuccessfulResponseTo<List<CompletionItem>>(request); + } + + Future<List<Location>> getDefinition(Uri uri, Position pos) async { + final request = makeRequest( + Method.textDocument_definition, + new TextDocumentPositionParams( + new TextDocumentIdentifier(uri.toString()), + pos, + ), + ); + return expectSuccessfulResponseTo<List<Location>>(request); + } + + Future<Either2<List<DocumentSymbol>, List<SymbolInformation>>> + getDocumentSymbols(String fileUri) async { + final request = makeRequest( + Method.textDocument_documentSymbol, + new DocumentSymbolParams( + new TextDocumentIdentifier(fileUri), + ), + ); + return expectSuccessfulResponseTo(request); + } + + Future<Hover> getHover(Uri uri, Position pos) async { + final request = makeRequest( + Method.textDocument_hover, + new TextDocumentPositionParams( + new TextDocumentIdentifier(uri.toString()), pos), + ); + return expectSuccessfulResponseTo<Hover>(request); + } + + Future<List<Location>> getReferences( + Uri uri, + Position pos, { + includeDeclarations = false, + }) async { + final request = makeRequest( + Method.textDocument_references, + new ReferenceParams( + new ReferenceContext(includeDeclarations), + new TextDocumentIdentifier(uri.toString()), + pos, + ), + ); + return expectSuccessfulResponseTo<List<Location>>(request); + } + + Future<SignatureHelp> getSignatureHelp(Uri uri, Position pos) async { + final request = makeRequest( + Method.textDocument_signatureHelp, + new TextDocumentPositionParams( + new TextDocumentIdentifier(uri.toString()), + pos, + ), + ); + return expectSuccessfulResponseTo<SignatureHelp>(request); + } + + /// A helper that initializes the server with common values, since the server + /// will reject any other requests until it is initialized. + /// Capabilities are overridden by providing JSON to avoid having to construct + /// full objects just to change one value (the types are immutable) so must + /// match the spec exactly and are not verified. + Future<ResponseMessage> initialize({ + String rootPath, + Map<String, dynamic> textDocumentCapabilities, + }) async { + final rootUri = Uri.file(rootPath ?? projectFolderPath).toString(); + final newTextDocumentCapabilities = + overrideTextDocumentCapabilities(textDocumentCapabilities); + final request = makeRequest( + Method.initialize, + new InitializeParams( + null, + null, + rootUri, + null, + new ClientCapabilities(null, newTextDocumentCapabilities, null), + null, + null)); + final response = await channel.sendRequestToServer(request); + expect(response.id, equals(request.id)); + + if (response.error == null) { + final notification = makeNotification(Method.initialized, null); + channel.sendNotificationToServer(notification); + } + + return response; + } + + NotificationMessage makeNotification(Method method, ToJsonable params) { + return new NotificationMessage(method, params, jsonRpcVersion); + } + + RequestMessage makeRequest(Method method, ToJsonable params) { + final id = Either2<num, String>.t1(_id++); + return new RequestMessage(id, method, params, jsonRpcVersion); + } + + Future openFile(Uri uri, String content) async { + var notification = makeNotification( + Method.textDocument_didOpen, + new DidOpenTextDocumentParams( + new TextDocumentItem(uri.toString(), dartLanguageId, 1, content)), + ); + channel.sendNotificationToServer(notification); + await pumpEventQueue(); + } + + TextDocumentClientCapabilities overrideTextDocumentCapabilities( + Map<String, dynamic> textDocumentCapabilities) { + final json = emptyTextDocumentClientCapabilities.toJson(); + if (textDocumentCapabilities != null) { + textDocumentCapabilities.keys.forEach((key) { + json[key] = textDocumentCapabilities[key]; + }); + } + final newTextDocumentCapabilities = + TextDocumentClientCapabilities.fromJson(json); + return newTextDocumentCapabilities; + } + + Position positionFromMarker(String contents) => + positionFromOffset(contents.indexOf('^'), contents); + + Position positionFromOffset(int offset, String contents) { + final lineInfo = LineInfo.fromContent(contents); + return toPosition(lineInfo.getLocation(offset)); + } + + /// Returns the range surrounded by `[[markers]]` in the provided string, + /// excluding the markers themselves (as well as position markers `^` from + /// the offsets). + Range rangeFromMarkers(String contents) { + contents = contents.replaceAll(positionMarker, ''); + final start = contents.indexOf(rangeMarkerStart); + if (start == -1) { + throw 'Contents did not contain $rangeMarkerStart'; + } + final end = contents.indexOf(rangeMarkerEnd); + if (end == -1) { + throw 'Contents did not contain $rangeMarkerEnd'; + } + return new Range( + positionFromOffset(start, contents), + positionFromOffset(end - rangeMarkerStart.length, contents), + ); + } + + Future replaceFile(Uri uri, String content) async { + await changeFile( + uri, + [new TextDocumentContentChangeEvent(null, null, content)], + ); + } + + void setUp() { + channel = new MockLspServerChannel(debugPrintCommunication); + // Create an SDK in the mock file system. + new MockSdk(resourceProvider: resourceProvider); + server = new LspAnalysisServer( + channel, + resourceProvider, + new AnalysisServerOptions(), + new DartSdkManager(convertPath('/sdk'), false), + InstrumentationService.NULL_SERVICE); + + projectFolderPath = convertPath('/project'); + newFolder(projectFolderPath); + newFolder(join(projectFolderPath, 'lib')); + // Create a folder and file to aid testing that includes imports/completion. + newFolder(join(projectFolderPath, 'lib', 'folder')); + newFile(join(projectFolderPath, 'lib', 'file.dart')); + mainFilePath = join(projectFolderPath, 'lib', 'main.dart'); + mainFileUri = Uri.file(mainFilePath); + } + + Future tearDown() async { + channel.close(); + await server.shutdown(); + } + + Future<List<Diagnostic>> waitForDiagnostics(Uri uri) async { + PublishDiagnosticsParams diagnosticParams; + await channel.serverToClient.firstWhere((message) { + if (message is NotificationMessage && + message.method == Method.textDocument_publishDiagnostics) { + diagnosticParams = message.params; + + return diagnosticParams.uri == uri.toString(); + } + return false; + }); + return diagnosticParams.diagnostics; + } + + /// Removes markers like `[[` and `]]` and `^` that are used for marking + /// positions/ranges in strings to avoid hard-coding positions in tests. + String withoutMarkers(String contents) => + contents.replaceAll(allMarkersPattern, ''); +}
diff --git a/pkg/analysis_server/test/lsp/server_test.dart b/pkg/analysis_server/test/lsp/server_test.dart new file mode 100644 index 0000000..9054552 --- /dev/null +++ b/pkg/analysis_server/test/lsp/server_test.dart
@@ -0,0 +1,73 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:analysis_server/lsp_protocol/protocol_generated.dart'; +import 'package:test/test.dart'; +import 'package:test_reflective_loader/test_reflective_loader.dart'; + +import 'server_abstract.dart'; + +main() { + defineReflectiveSuite(() { + defineReflectiveTests(ServerTest); + }); +} + +@reflectiveTest +class ServerTest extends AbstractLspAnalysisServerTest { + test_shutdown_initialized() async { + await initialize(); + final request = makeRequest(Method.shutdown, null); + final response = await channel.sendRequestToServer(request); + expect(response.id, equals(request.id)); + expect(response.error, isNull); + expect(response.result, isNull); + } + + test_shutdown_uninitialized() async { + final request = makeRequest(Method.shutdown, null); + final response = await channel.sendRequestToServer(request); + expect(response.id, equals(request.id)); + expect(response.error, isNull); + expect(response.result, isNull); + } + + test_unknownNotifications_silentlyDropped() async { + await initialize(); + final notification = + makeNotification(new Method.fromJson(r'$/randomNotification'), null); + final firstError = channel.errorNotificationsFromServer.first; + channel.sendNotificationToServer(notification); + + // Wait up to 1sec to ensure no error/log notifications were sent back. + var didTimeout = false; + final notificationFromServer = await firstError.timeout( + const Duration(seconds: 1), + onTimeout: () { + didTimeout = true; + }, + ); + + expect(notificationFromServer, isNull); + expect(didTimeout, isTrue); + } + + test_unknownRequest_rejected() async { + await initialize(); + final request = makeRequest(new Method.fromJson('randomRequest'), null); + final response = await channel.sendRequestToServer(request); + expect(response.id, equals(request.id)); + expect(response.error, isNotNull); + expect(response.error.code, equals(ErrorCodes.MethodNotFound)); + expect(response.result, isNull); + } + + @failingTest + test_unknownRequest_silentlyDropped /*??*/ () async { + // TODO(dantup): Fix this test up when we know how we're supposed to handle + // unknown $/ requests. + // https://github.com/Microsoft/language-server-protocol/issues/607 + fail('TODO(dantup)'); + } +}
diff --git a/pkg/analysis_server/test/lsp/signature_help_test.dart b/pkg/analysis_server/test/lsp/signature_help_test.dart new file mode 100644 index 0000000..b72233d --- /dev/null +++ b/pkg/analysis_server/test/lsp/signature_help_test.dart
@@ -0,0 +1,304 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:analysis_server/lsp_protocol/protocol_generated.dart'; +import 'package:test/test.dart'; +import 'package:test_reflective_loader/test_reflective_loader.dart'; + +import 'server_abstract.dart'; + +main() { + defineReflectiveSuite(() { + defineReflectiveTests(SignatureHelpTest); + }); +} + +@reflectiveTest +class SignatureHelpTest extends AbstractLspAnalysisServerTest { + Future<void> initializeSupportingMarkupContent([ + List<MarkupKind> formats = const [MarkupKind.Markdown], + ]) async { + await initialize(textDocumentCapabilities: { + 'signatureHelp': { + 'signatureInformation': { + 'documentationFormat': formats.map((f) => f.toJson()) + } + } + }); + } + + test_formats_markdown() async { + final content = ''' + /// Does foo. + foo(String s, int i) { + foo(^); + } + '''; + final expectedLabel = 'foo(String s, int i)'; + final expectedDoc = 'Does foo.'; + + await initializeSupportingMarkupContent([MarkupKind.Markdown]); + await openFile(mainFileUri, withoutMarkers(content)); + await testSignature( + content, + expectedLabel, + expectedDoc, + [ + new ParameterInformation('String s', null), + new ParameterInformation('int i', null), + ], + expectedFormat: MarkupKind.Markdown, + ); + } + + test_formats_notSupported() async { + final content = ''' + /// Does foo. + foo(String s, int i) { + foo(^); + } + '''; + final expectedLabel = 'foo(String s, int i)'; + final expectedDoc = 'Does foo.'; + + await initialize(); + await openFile(mainFileUri, withoutMarkers(content)); + await testSignature( + content, + expectedLabel, + expectedDoc, + [ + new ParameterInformation('String s', null), + new ParameterInformation('int i', null), + ], + expectedFormat: null, + ); + } + + test_formats_plainTextOnly() async { + final content = ''' + /// Does foo. + foo(String s, int i) { + foo(^); + } + '''; + final expectedLabel = 'foo(String s, int i)'; + final expectedDoc = 'Does foo.'; + + await initializeSupportingMarkupContent([MarkupKind.PlainText]); + await openFile(mainFileUri, withoutMarkers(content)); + await testSignature( + content, + expectedLabel, + expectedDoc, + [ + new ParameterInformation('String s', null), + new ParameterInformation('int i', null), + ], + expectedFormat: MarkupKind.PlainText, + ); + } + + test_formats_plainTextPreferred() async { + final content = ''' + /// Does foo. + foo(String s, int i) { + foo(^); + } + '''; + final expectedLabel = 'foo(String s, int i)'; + final expectedDoc = 'Does foo.'; + + // We say we prefer PlainText as a client, but since we only really + // support Markdown and the client supports it, we expect the server + // to provide Markdown. + await initializeSupportingMarkupContent( + [MarkupKind.PlainText, MarkupKind.Markdown]); + await openFile(mainFileUri, withoutMarkers(content)); + await testSignature( + content, + expectedLabel, + expectedDoc, + [ + new ParameterInformation('String s', null), + new ParameterInformation('int i', null), + ], + expectedFormat: MarkupKind.Markdown, + ); + } + + test_params_multipleNamed() async { + final content = ''' + /// Does foo. + foo(String s, {bool b = true, bool a}) { + foo(^); + } + '''; + + final expectedLabel = 'foo(String s, {bool b = true, bool a})'; + final expectedDoc = 'Does foo.'; + + await initializeSupportingMarkupContent(); + await openFile(mainFileUri, withoutMarkers(content)); + await testSignature( + content, + expectedLabel, + expectedDoc, + [ + new ParameterInformation('String s', null), + new ParameterInformation('bool b = true', null), + new ParameterInformation('bool a', null), + ], + ); + } + + test_params_multipleOptional() async { + final content = ''' + /// Does foo. + foo(String s, [bool b = true, bool a]) { + foo(^); + } + '''; + + final expectedLabel = 'foo(String s, [bool b = true, bool a])'; + final expectedDoc = 'Does foo.'; + + await initializeSupportingMarkupContent(); + await openFile(mainFileUri, withoutMarkers(content)); + await testSignature( + content, + expectedLabel, + expectedDoc, + [ + new ParameterInformation('String s', null), + new ParameterInformation('bool b = true', null), + new ParameterInformation('bool a', null), + ], + ); + } + + test_params_named() async { + final content = ''' + /// Does foo. + foo(String s, {bool b = true}) { + foo(^); + } + '''; + + final expectedLabel = 'foo(String s, {bool b = true})'; + final expectedDoc = 'Does foo.'; + + await initializeSupportingMarkupContent(); + await openFile(mainFileUri, withoutMarkers(content)); + await testSignature( + content, + expectedLabel, + expectedDoc, + [ + new ParameterInformation('String s', null), + new ParameterInformation('bool b = true', null), + ], + ); + } + + test_params_optional() async { + final content = ''' + /// Does foo. + foo(String s, [bool b = true]) { + foo(^); + } + '''; + + final expectedLabel = 'foo(String s, [bool b = true])'; + final expectedDoc = 'Does foo.'; + + await initializeSupportingMarkupContent(); + await openFile(mainFileUri, withoutMarkers(content)); + await testSignature( + content, + expectedLabel, + expectedDoc, + [ + new ParameterInformation('String s', null), + new ParameterInformation('bool b = true', null), + ], + ); + } + + test_simple() async { + final content = ''' + /// Does foo. + foo(String s, int i) { + foo(^); + } + '''; + final expectedLabel = 'foo(String s, int i)'; + final expectedDoc = 'Does foo.'; + + await initializeSupportingMarkupContent(); + await openFile(mainFileUri, withoutMarkers(content)); + await testSignature( + content, + expectedLabel, + expectedDoc, + [ + new ParameterInformation('String s', null), + new ParameterInformation('int i', null), + ], + ); + } + + test_unopenFile() async { + final content = ''' + /// Does foo. + foo(String s, int i) { + foo(^); + } + '''; + final expectedLabel = 'foo(String s, int i)'; + final expectedDoc = 'Does foo.'; + + newFile(mainFilePath, content: withoutMarkers(content)); + await initializeSupportingMarkupContent(); + await testSignature( + content, + expectedLabel, + expectedDoc, + [ + new ParameterInformation('String s', null), + new ParameterInformation('int i', null), + ], + ); + } + + Future<void> testSignature( + String fileContent, + String expectedLabel, + String expectedDoc, + List<ParameterInformation> expectedParams, { + MarkupKind expectedFormat = MarkupKind.Markdown, + }) async { + final res = + await getSignatureHelp(mainFileUri, positionFromMarker(fileContent)); + + expect(res.activeParameter, isNull); + expect(res.activeSignature, equals(0)); + expect(res.signatures, hasLength(1)); + final sig = res.signatures.first; + expect(sig.label, equals(expectedLabel)); + expect(sig.parameters, equals(expectedParams)); + + // Test the format matches the tests expectation. + // For clients that don't support MarkupContent it'll be a plain string, + // but otherwise it'll be a MarkupContent of type PlainText or Markdown. + final doc = sig.documentation; + if (expectedFormat == null) { + // Plain string. + expect(doc.valueEquals(expectedDoc), isTrue); + } else { + final expected = new MarkupContent(expectedFormat, expectedDoc); + expect(doc.valueEquals(expected), isTrue); + } + } +}
diff --git a/pkg/analysis_server/test/lsp/test_all.dart b/pkg/analysis_server/test/lsp/test_all.dart new file mode 100644 index 0000000..c889439 --- /dev/null +++ b/pkg/analysis_server/test/lsp/test_all.dart
@@ -0,0 +1,33 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:test_reflective_loader/test_reflective_loader.dart'; + +import 'completion_test.dart' as completion_test; +import 'definition_test.dart' as definition_test; +import 'diagnostic_test.dart' as diagnostic_test; +import 'document_symbols_test.dart' as document_symbols_test; +import 'file_modification_test.dart' as file_modification_test; +import 'format_test.dart' as format_test; +import 'hover_test.dart' as hover_test; +import 'initialization_test.dart' as initialization_test; +import 'references_test.dart' as references_test; +import 'server_test.dart' as server_test; +import 'signature_help_test.dart' as signature_help_test; + +main() { + defineReflectiveSuite(() { + completion_test.main(); + definition_test.main(); + diagnostic_test.main(); + document_symbols_test.main(); + file_modification_test.main(); + format_test.main(); + hover_test.main(); + initialization_test.main(); + references_test.main(); + server_test.main(); + signature_help_test.main(); + }, name: 'lsp'); +}
diff --git a/pkg/analysis_server/test/mock_sdk.dart b/pkg/analysis_server/test/mock_sdk.dart deleted file mode 100644 index 07f8f15..0000000 --- a/pkg/analysis_server/test/mock_sdk.dart +++ /dev/null
@@ -1,452 +0,0 @@ -// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file -// for details. All rights reserved. Use of this source code is governed by a -// BSD-style license that can be found in the LICENSE file. - -import 'package:analyzer/file_system/file_system.dart' as resource; -import 'package:analyzer/file_system/memory_file_system.dart' as resource; -import 'package:analyzer/src/context/context.dart'; -import 'package:analyzer/src/generated/engine.dart'; -import 'package:analyzer/src/generated/sdk.dart'; -import 'package:analyzer/src/generated/source.dart'; -import 'package:analyzer/src/summary/idl.dart' show PackageBundle; -import 'package:analyzer/src/summary/summary_file_builder.dart'; - -class MockSdk implements DartSdk { - static const MockSdkLibrary LIB_CORE = - const MockSdkLibrary('dart:core', '/lib/core/core.dart', ''' -library dart.core; - -import 'dart:async'; -import 'dart:_internal'; - -class Object { - const Object(); - bool operator ==(other) => identical(this, other); - String toString() => 'a string'; - int get hashCode => 0; - Type get runtimeType => null; - dynamic noSuchMethod(Invocation invocation) => null; -} - -class Function {} -class StackTrace {} -class Symbol {} -class Type {} - -abstract class Comparable<T> { - int compareTo(T other); -} - -abstract class String implements Comparable<String> { - external factory String.fromCharCodes(Iterable<int> charCodes, - [int start = 0, int end]); - bool get isEmpty => false; - bool get isNotEmpty => false; - int get length => 0; - String toUpperCase(); - List<int> get codeUnits; -} - -class bool extends Object {} - -abstract class num implements Comparable<num> { - bool operator <(num other); - bool operator <=(num other); - bool operator >(num other); - bool operator >=(num other); - num operator +(num other); - num operator -(num other); - num operator *(num other); - num operator /(num other); - int operator ^(int other); - int operator &(int other); - int operator |(int other); - int operator <<(int other); - int operator >>(int other); - int operator ~/(num other); - num operator %(num other); - int operator ~(); - int toInt(); - double toDouble(); - num abs(); - int round(); -} - -abstract class int extends num { - bool get isEven => false; - int operator -(); - external static int parse(String source, - { int radix, - int onError(String source) }); -} - -abstract class double extends num { - static const double NAN = 0.0 / 0.0; - static const double INFINITY = 1.0 / 0.0; - static const double NEGATIVE_INFINITY = -INFINITY; - static const double MIN_POSITIVE = 5e-324; - static const double MAX_FINITE = 1.7976931348623157e+308; - - double remainder(num other); - double operator +(num other); - double operator -(num other); - double operator *(num other); - double operator %(num other); - double operator /(num other); - int operator ~/(num other); - double operator -(); - double abs(); - double get sign; - int round(); - int floor(); - int ceil(); - int truncate(); - double roundToDouble(); - double floorToDouble(); - double ceilToDouble(); - double truncateToDouble(); - external static double parse(String source, - [double onError(String source)]); -} - -class DateTime extends Object {} -class Null extends Object {} - -class Deprecated extends Object { - final String expires; - const Deprecated(this.expires); -} -const Object deprecated = const Deprecated("next release"); - -class Exception { - factory Exception([var message]); -} - -class Iterator<E> { - bool moveNext(); - E get current; -} - -abstract class Iterable<E> { - Iterator<E> get iterator; - bool get isEmpty; - void forEach(void f(E element)); - Iterable<T> map<T>(T f(E e)) => null; - T fold<T>(T initialValue, T combine(T previousValue, E element)); - List<E> toList({bool growable: true}); -} - -class List<E> implements Iterable<E> { - List(); - void add(E value) {} - void addAll(Iterable<E> iterable) {} - List<R> cast<R>(); - E operator [](int index) => null; - void operator []=(int index, E value) {} - Iterator<E> get iterator => null; - void clear() {} - Iterable<E> where(bool test(E element)) {} - - bool get isEmpty => false; - E get first => null; - E get last => null; -} - -abstract class Map<K, V> extends Object { - Iterable<K> get keys; - int get length; - Iterable<V> get values; - V operator [](K key) => null; - void operator []=(K key, V value) {} - Map<RK, RV> cast<RK, RV>(); - bool containsKey(Object key); -} - -external bool identical(Object a, Object b); - -void print(Object object) {} - -class Set<E> implements Iterable<E> { - Set<R> cast<R>(); -} - -class Uri { - static List<int> parseIPv6Address(String host, [int start = 0, int end]) { - int parseHex(int start, int end) { - return 0; - } - return null; - } -} - -class _Override { const _Override(); } -const Object override = const _Override(); -'''); - static const MockSdkLibrary LIB_ASYNC = - const MockSdkLibrary('dart:async', '/lib/async/async.dart', ''' -library dart.async; - -import 'dart:math'; - -class Future<T> { - factory Future(computation()) => null; - factory Future.delayed(Duration duration, [T computation()]) => null; - factory Future.value([value]) => null; - static Future wait(List<Future> futures) => null; -} - -class FutureOr<T> {} - -class Stream<T> {} -abstract class StreamTransformer<S, T> {} -'''); - - static const MockSdkLibrary LIB_COLLECTION = const MockSdkLibrary( - 'dart:collection', '/lib/collection/collection.dart', ''' -library dart.collection; - -abstract class HashMap<K, V> implements Map<K, V> {} -abstract class LinkedHashMap<K, V> implements Map<K, V> {} -'''); - - static const MockSdkLibrary LIB_CONVERT = - const MockSdkLibrary('dart:convert', '/lib/convert/convert.dart', ''' -library dart.convert; - -import 'dart:async'; - -abstract class Converter<S, T> implements StreamTransformer {} -class JsonDecoder extends Converter<String, Object> {} -'''); - - static const MockSdkLibrary LIB_MATH = - const MockSdkLibrary('dart:math', '/lib/math/math.dart', ''' -library dart.math; -const double E = 2.718281828459045; -const double PI = 3.1415926535897932; -const double LN10 = 2.302585092994046; -T min<T extends num>(T a, T b) => null; -T max<T extends num>(T a, T b) => null; -external double cos(num radians); -external num pow(num x, num exponent); -external double sin(num radians); -external double sqrt(num x); -class Random { - bool nextBool() => true; - double nextDouble() => 2.0; - int nextInt() => 1; -} -'''); - - static const MockSdkLibrary LIB_HTML = const MockSdkLibrary( - 'dart:html', '/lib/html/dartium/html_dartium.dart', ''' -library dart.html; -class HtmlElement {} -'''); - - static const MockSdkLibrary LIB_INTERNAL = - const MockSdkLibrary('dart:_internal', '/lib/internal/internal.dart', ''' -library dart._internal; -external void printToConsole(String line); -'''); - - static const List<SdkLibrary> LIBRARIES = const [ - LIB_CORE, - LIB_ASYNC, - LIB_COLLECTION, - LIB_CONVERT, - LIB_MATH, - LIB_HTML, - LIB_INTERNAL, - ]; - - static const String librariesContent = r''' -const Map<String, LibraryInfo> libraries = const { - "async": const LibraryInfo("async/async.dart"), - "collection": const LibraryInfo("collection/collection.dart"), - "convert": const LibraryInfo("convert/convert.dart"), - "core": const LibraryInfo("core/core.dart"), - "html": const LibraryInfo("html/dartium/html_dartium.dart"), - "math": const LibraryInfo("math/math.dart"), - "_internal": const LibraryInfo("internal/internal.dart"), -}; -'''; - - final resource.MemoryResourceProvider provider; - - /** - * The [AnalysisContext] which is used for all of the sources. - */ - InternalAnalysisContext _analysisContext; - - /** - * The cached linked bundle of the SDK. - */ - PackageBundle _bundle; - - MockSdk( - {bool generateSummaryFiles: false, - resource.ResourceProvider resourceProvider}) - : provider = resourceProvider ?? new resource.MemoryResourceProvider() { - LIBRARIES.forEach((SdkLibrary library) { - provider.newFile(provider.convertPath(library.path), - (library as MockSdkLibrary).content); - }); - provider.newFile( - provider.convertPath( - '/lib/_internal/sdk_library_metadata/lib/libraries.dart'), - librariesContent); - if (generateSummaryFiles) { - List<int> bytes = _computeLinkedBundleBytes(); - provider.newFileWithBytes( - provider.convertPath('/lib/_internal/strong.sum'), bytes); - } - } - - @override - AnalysisContext get context { - if (_analysisContext == null) { - _analysisContext = new SdkAnalysisContext(null); - SourceFactory factory = new SourceFactory([new DartUriResolver(this)]); - _analysisContext.sourceFactory = factory; - } - return _analysisContext; - } - - @override - List<SdkLibrary> get sdkLibraries => LIBRARIES; - - @override - String get sdkVersion => throw unimplemented; - - UnimplementedError get unimplemented => new UnimplementedError(); - - @override - List<String> get uris { - List<String> uris = <String>[]; - for (SdkLibrary library in LIBRARIES) { - uris.add(library.shortName); - } - return uris; - } - - @override - Source fromFileUri(Uri uri) { - String filePath = provider.pathContext.fromUri(uri); - for (SdkLibrary library in sdkLibraries) { - String libraryPath = provider.convertPath(library.path); - if (filePath == libraryPath) { - try { - resource.File file = provider.getResource(filePath); - Uri dartUri = Uri.parse(library.shortName); - return file.createSource(dartUri); - } catch (exception) { - return null; - } - } - String libraryRootPath = provider.pathContext.dirname(libraryPath) + - provider.pathContext.separator; - if (filePath.startsWith(libraryRootPath)) { - String pathInLibrary = filePath.substring(libraryRootPath.length); - String uriStr = '${library.shortName}/$pathInLibrary'; - try { - resource.File file = provider.getResource(filePath); - Uri dartUri = Uri.parse(uriStr); - return file.createSource(dartUri); - } catch (exception) { - return null; - } - } - } - return null; - } - - @override - PackageBundle getLinkedBundle() { - if (_bundle == null) { - resource.File summaryFile = - provider.getFile(provider.convertPath('/lib/_internal/strong.sum')); - List<int> bytes; - if (summaryFile.exists) { - bytes = summaryFile.readAsBytesSync(); - } else { - bytes = _computeLinkedBundleBytes(); - } - _bundle = new PackageBundle.fromBuffer(bytes); - } - return _bundle; - } - - @override - SdkLibrary getSdkLibrary(String dartUri) { - // getSdkLibrary() is only used to determine whether a library is internal - // to the SDK. The mock SDK doesn't have any internals, so it's safe to - // return null. - return null; - } - - @override - Source mapDartUri(String dartUri) { - const Map<String, String> uriToPath = const { - "dart:core": "/lib/core/core.dart", - "dart:html": "/lib/html/dartium/html_dartium.dart", - "dart:async": "/lib/async/async.dart", - "dart:collection": "/lib/collection/collection.dart", - "dart:convert": "/lib/convert/convert.dart", - "dart:math": "/lib/math/math.dart", - "dart:_internal": "/lib/internal/internal.dart", - }; - - String path = uriToPath[dartUri]; - if (path != null) { - resource.File file = provider.getResource(provider.convertPath(path)); - Uri uri = new Uri(scheme: 'dart', path: dartUri.substring(5)); - return file.createSource(uri); - } - - // If we reach here then we tried to use a dartUri that's not in the - // table above. - return null; - } - - /** - * Compute the bytes of the linked bundle associated with this SDK. - */ - List<int> _computeLinkedBundleBytes() { - List<Source> librarySources = sdkLibraries - .map((SdkLibrary library) => mapDartUri(library.shortName)) - .toList(); - return new SummaryBuilder(librarySources, context).build(); - } -} - -class MockSdkLibrary implements SdkLibrary { - final String shortName; - final String path; - final String content; - - const MockSdkLibrary(this.shortName, this.path, this.content); - - @override - String get category => throw unimplemented; - - @override - bool get isDart2JsLibrary => throw unimplemented; - - @override - bool get isDocumented => throw unimplemented; - - @override - bool get isImplementation => false; - - @override - bool get isInternal => shortName.startsWith('dart:_'); - - @override - bool get isShared => throw unimplemented; - - @override - bool get isVmLibrary => throw unimplemented; - - UnimplementedError get unimplemented => new UnimplementedError(); -}
diff --git a/pkg/analysis_server/test/mocks.dart b/pkg/analysis_server/test/mocks.dart index 6c4b927..23f74f9 100644 --- a/pkg/analysis_server/test/mocks.dart +++ b/pkg/analysis_server/test/mocks.dart
@@ -3,12 +3,17 @@ // BSD-style license that can be found in the LICENSE file. import 'dart:async'; +import 'dart:convert'; import 'dart:io'; +import 'package:analysis_server/lsp_protocol/protocol_generated.dart' as lsp; +import 'package:analysis_server/lsp_protocol/protocol_generated.dart'; +import 'package:analysis_server/lsp_protocol/protocol_special.dart' as lsp; import 'package:analysis_server/protocol/protocol.dart'; import 'package:analysis_server/protocol/protocol_generated.dart'; import 'package:analysis_server/src/analysis_server.dart'; import 'package:analysis_server/src/channel/channel.dart'; +import 'package:analysis_server/src/lsp/channel/lsp_channel.dart'; import 'package:analyzer/src/generated/source.dart'; import 'package:analyzer/src/generated/timestamped_data.dart'; import 'package:test/test.dart'; @@ -43,6 +48,140 @@ Matcher isResponseSuccess(String id) => new _IsResponseSuccess(id); /** + * A mock [LspServerCommunicationChannel] for testing [LspAnalysisServer]. + */ +class MockLspServerChannel implements LspServerCommunicationChannel { + // TODO(dantup): Support server-to-client requests. We'll probably need to + // change IncomingMessage to just Message for both directions? + final StreamController<lsp.IncomingMessage> _clientToServer = + new StreamController<lsp.IncomingMessage>.broadcast(); + final StreamController<lsp.Message> _serverToClient = + new StreamController<lsp.Message>.broadcast(); + + bool _closed = false; + + String name; + + MockLspServerChannel(bool _printMessages) { + if (_printMessages) { + _serverToClient.stream + .listen((message) => print('<== ' + jsonEncode(message))); + _clientToServer.stream + .listen((message) => print('==> ' + jsonEncode(message))); + } + } + + Stream<lsp.Message> get serverToClient => _serverToClient.stream; + + @override + void close() { + _closed = true; + } + + /** + * A stream of [NotificationMessage]s from the server that may be errors. + */ + Stream<lsp.NotificationMessage> get errorNotificationsFromServer { + return notificationsFromServer.where(_isErrorNotification); + } + + @override + void listen(void Function(lsp.IncomingMessage message) onMessage, + {Function onError, void Function() onDone}) { + _clientToServer.stream.listen(onMessage, onError: onError, onDone: onDone); + } + + /** + * A stream of [NotificationMessage]s from the server. + */ + Stream<lsp.NotificationMessage> get notificationsFromServer { + return _serverToClient.stream + .where((m) => m is lsp.NotificationMessage) + .cast<lsp.NotificationMessage>(); + } + + @override + void sendNotification(lsp.NotificationMessage notification) { + // Don't deliver notifications after the connection is closed. + if (_closed) { + return; + } + _serverToClient.add(notification); + } + + void sendNotificationToServer(lsp.NotificationMessage notification) { + // Don't deliver notifications after the connection is closed. + if (_closed) { + return; + } + notification = _convertJson(notification, lsp.NotificationMessage.fromJson); + _clientToServer.add(notification); + } + + /** + * Send the given [request] to the server and return a future that will + * complete when a response associated with the [request] has been received. + * The value of the future will be the received response. + */ + Future<lsp.ResponseMessage> sendRequestToServer(lsp.RequestMessage request) { + // No further requests should be sent after the connection is closed. + if (_closed) { + throw new Exception('sendLspRequest after connection closed'); + } + request = _convertJson(request, lsp.RequestMessage.fromJson); + // Wrap send request in future to simulate WebSocket. + new Future(() => _clientToServer.add(request)); + return waitForResponse(request); + } + + @override + void sendResponse(lsp.ResponseMessage response) { + // Don't deliver responses after the connection is closed. + if (_closed) { + return; + } + // Wrap send response in future to simulate WebSocket. + new Future(() => _serverToClient.add(response)); + } + + /** + * Return a future that will complete when a response associated with the + * given [request] has been received. The value of the future will be the + * received response. The returned future will throw an exception if a server + * error is reported before the response has been received. + * + * Unlike [sendLspRequest], this method assumes that the [request] has already + * been sent to the server. + */ + Future<lsp.ResponseMessage> waitForResponse( + lsp.RequestMessage request) async { + // TODO(dantup): Make this throw if an error notifications comes in (as + // described above). + final response = await _serverToClient.stream.firstWhere((response) => + response is lsp.ResponseMessage && response.id == request.id); + return response; + } + + /// Round trips the object to JSON and back to ensure it behaves the same as + /// when running over the real STDIO server. Without this, the object passed + /// to the handlers will have concrete types as constructed in tests rather + /// than the maps as they would be (the server expects to do the conversion). + T _convertJson<T>( + lsp.ToJsonable message, T Function(Map<String, dynamic>) constructor) { + return constructor(jsonDecode(jsonEncode(message.toJson()))); + } + + /// Checks whether a notification is likely an error from the server (for + /// example a window/showMessage). This is useful for tests that want to + /// ensure no errors come from the server in response to notifications (which + /// don't have their own responses). + bool _isErrorNotification(lsp.NotificationMessage notification) { + return notification.method == Method.window_logMessage || + notification.method == Method.window_showMessage; + } +} + +/** * A mock [ServerCommunicationChannel] for testing [AnalysisServer]. */ class MockServerChannel implements ServerCommunicationChannel { @@ -55,6 +194,7 @@ List<Response> responsesReceived = []; List<Notification> notificationsReceived = []; + bool _closed = false; String name;
diff --git a/pkg/analysis_server/test/plugin/protocol_dart_test.dart b/pkg/analysis_server/test/plugin/protocol_dart_test.dart index 67f5ca5..ed8e850 100644 --- a/pkg/analysis_server/test/plugin/protocol_dart_test.dart +++ b/pkg/analysis_server/test/plugin/protocol_dart_test.dart
@@ -39,6 +39,8 @@ convertElementKind(engine.ElementKind.FUNCTION), ElementKind.FUNCTION); expect(convertElementKind(engine.ElementKind.FUNCTION_TYPE_ALIAS), ElementKind.FUNCTION_TYPE_ALIAS); + expect(convertElementKind(engine.ElementKind.GENERIC_FUNCTION_TYPE), + ElementKind.FUNCTION_TYPE_ALIAS); expect(convertElementKind(engine.ElementKind.GETTER), ElementKind.GETTER); expect(convertElementKind(engine.ElementKind.LABEL), ElementKind.LABEL); expect(convertElementKind(engine.ElementKind.LIBRARY), ElementKind.LIBRARY); @@ -169,7 +171,7 @@ } test_fromElement_CONSTRUCTOR_required_parameters_1() async { - addMetaPackageSource(); + addMetaPackage(); engine.Source source = addSource('/test.dart', ''' import 'package:meta/meta.dart'; class A { @@ -186,7 +188,7 @@ /// Verify parameter re-ordering for required params test_fromElement_CONSTRUCTOR_required_parameters_2() async { - addMetaPackageSource(); + addMetaPackage(); engine.Source source = addSource('/test.dart', ''' import 'package:meta/meta.dart'; class A { @@ -204,7 +206,7 @@ /// Verify parameter re-ordering for required params test_fromElement_CONSTRUCTOR_required_parameters_3() async { - addMetaPackageSource(); + addMetaPackage(); engine.Source source = addSource('/test.dart', ''' import 'package:meta/meta.dart'; class A { @@ -408,6 +410,30 @@ expect(element.flags, 0); } + test_fromElement_FUNCTION_TYPE_ALIAS_genericTypeAlias() async { + engine.Source source = addSource('/test.dart', ''' +typedef F<T> = int Function(String x); +'''); + engine.CompilationUnit unit = await resolveLibraryUnit(source); + engine.GenericTypeAliasElement engineElement = findElementInUnit(unit, 'F'); + // create notification Element + Element element = convertElement(engineElement); + expect(element.kind, ElementKind.FUNCTION_TYPE_ALIAS); + expect(element.name, 'F'); + expect(element.typeParameters, '<T>'); + { + Location location = element.location; + expect(location.file, convertPath('/test.dart')); + expect(location.offset, 8); + expect(location.length, 'F'.length); + expect(location.startLine, 1); + expect(location.startColumn, 9); + } + expect(element.parameters, '(String x)'); + expect(element.returnType, 'int'); + expect(element.flags, 0); + } + test_fromElement_GETTER() async { engine.Source source = addSource('/test.dart', ''' class A {
diff --git a/pkg/analysis_server/test/protocol_server_test.dart b/pkg/analysis_server/test/protocol_server_test.dart index 7ac554b..9d2e9ca 100644 --- a/pkg/analysis_server/test/protocol_server_test.dart +++ b/pkg/analysis_server/test/protocol_server_test.dart
@@ -128,7 +128,7 @@ engine.ElementKind.DYNAMIC: ElementKind.UNKNOWN, engine.ElementKind.ERROR: ElementKind.UNKNOWN, engine.ElementKind.EXPORT: ElementKind.UNKNOWN, - engine.ElementKind.GENERIC_FUNCTION_TYPE: ElementKind.UNKNOWN, + engine.ElementKind.GENERIC_FUNCTION_TYPE: ElementKind.FUNCTION_TYPE_ALIAS, engine.ElementKind.IMPORT: ElementKind.UNKNOWN, engine.ElementKind.NAME: ElementKind.UNKNOWN, engine.ElementKind.UNIVERSE: ElementKind.UNKNOWN
diff --git a/pkg/analysis_server/test/search/element_references_test.dart b/pkg/analysis_server/test/search/element_references_test.dart index fb3aa88..6473f65 100644 --- a/pkg/analysis_server/test/search/element_references_test.dart +++ b/pkg/analysis_server/test/search/element_references_test.dart
@@ -693,6 +693,18 @@ assertHasResult(SearchResultKind.REFERENCE, 'F f'); } + Future<void> test_typeReference_genericTypeAlias_function() async { + addTestFile(''' +typedef F = Function(); +main(F f) { +} +'''); + await findElementReferences('F =', false); + expect(searchElement.kind, ElementKind.FUNCTION_TYPE_ALIAS); + expect(results, hasLength(1)); + assertHasResult(SearchResultKind.REFERENCE, 'F f'); + } + Future<void> test_typeReference_typeVariable() async { addTestFile(''' class A<T> {
diff --git a/pkg/analysis_server/test/search/top_level_declarations_test.dart b/pkg/analysis_server/test/search/top_level_declarations_test.dart index 5e46628..7e1fd99 100644 --- a/pkg/analysis_server/test/search/top_level_declarations_test.dart +++ b/pkg/analysis_server/test/search/top_level_declarations_test.dart
@@ -67,16 +67,18 @@ class A {} // A class B = Object with A; typedef C(); -D() {} -var E = null; +typedef D(); +E() {} +var F = null; class ABC {} '''); - await findTopLevelDeclarations('^[A-E]\$'); + await findTopLevelDeclarations('^[A-F]\$'); assertHasDeclaration(ElementKind.CLASS, 'A'); assertHasDeclaration(ElementKind.CLASS, 'B'); assertHasDeclaration(ElementKind.FUNCTION_TYPE_ALIAS, 'C'); - assertHasDeclaration(ElementKind.FUNCTION, 'D'); - assertHasDeclaration(ElementKind.TOP_LEVEL_VARIABLE, 'E'); + assertHasDeclaration(ElementKind.FUNCTION_TYPE_ALIAS, 'D'); + assertHasDeclaration(ElementKind.FUNCTION, 'E'); + assertHasDeclaration(ElementKind.TOP_LEVEL_VARIABLE, 'F'); assertNoDeclaration(ElementKind.CLASS, 'ABC'); } }
diff --git a/pkg/analysis_server/test/services/completion/dart/arglist_contributor_test.dart b/pkg/analysis_server/test/services/completion/dart/arglist_contributor_test.dart index a75c2e4..d6c7124 100644 --- a/pkg/analysis_server/test/services/completion/dart/arglist_contributor_test.dart +++ b/pkg/analysis_server/test/services/completion/dart/arglist_contributor_test.dart
@@ -896,7 +896,7 @@ } test_ArgumentList_local_constructor_required_param_0() async { - addMetaPackageSource(); + addMetaPackage(); addTestSource(''' import 'package:meta/meta.dart'; class A { A({int one, @required String two: 'defaultValue'}) { } }
diff --git a/pkg/analysis_server/test/services/completion/dart/completion_contributor_util.dart b/pkg/analysis_server/test/services/completion/dart/completion_contributor_util.dart index fc67b56..acd42b0 100644 --- a/pkg/analysis_server/test/services/completion/dart/completion_contributor_util.dart +++ b/pkg/analysis_server/test/services/completion/dart/completion_contributor_util.dart
@@ -9,7 +9,6 @@ import 'package:analysis_server/src/services/completion/completion_performance.dart'; import 'package:analysis_server/src/services/completion/dart/completion_manager.dart' show DartCompletionRequestImpl; -import 'package:analyzer/src/dart/analysis/driver.dart'; import 'package:analyzer/src/generated/parser.dart' as analyzer; import 'package:analyzer_plugin/protocol/protocol_common.dart'; import 'package:test/test.dart'; @@ -460,19 +459,10 @@ return cs; } - /** - * Return a [Future] that completes with the containing library information - * after it is accessible via [context.getLibrariesContaining]. - */ - Future<void> computeLibrariesContaining([int times = 200]) { - return driver.getResult(testFile).then((result) => null); - } - Future computeSuggestions({int times = 200}) async { - AnalysisResult analysisResult = - await driver.getResult(convertPath(testFile)); + var resolveResult = await session.getResolvedUnit(testFile); CompletionRequestImpl baseRequest = new CompletionRequestImpl( - analysisResult, completionOffset, new CompletionPerformance()); + resolveResult, completionOffset, new CompletionPerformance()); // Build the request var request = await DartCompletionRequestImpl.from(baseRequest); @@ -553,7 +543,7 @@ @override void setUp() { super.setUp(); - testFile = resourceProvider.convertPath('/completionTest.dart'); + testFile = convertPath('/completionTest.dart'); contributor = createContributor(); } }
diff --git a/pkg/analysis_server/test/services/completion/dart/completion_manager_test.dart b/pkg/analysis_server/test/services/completion/dart/completion_manager_test.dart index 263f905..83ad6a8 100644 --- a/pkg/analysis_server/test/services/completion/dart/completion_manager_test.dart +++ b/pkg/analysis_server/test/services/completion/dart/completion_manager_test.dart
@@ -47,7 +47,7 @@ // Build the request CompletionRequestImpl baseRequest = new CompletionRequestImpl( - await driver.getResult(testFile), + await session.getResolvedUnit(testFile), completionOffset, new CompletionPerformance()); Completer<DartCompletionRequest> requestCompleter =
diff --git a/pkg/analysis_server/test/services/completion/dart/imported_reference_contributor_test.dart b/pkg/analysis_server/test/services/completion/dart/imported_reference_contributor_test.dart index 26100ebf..d36e5af 100644 --- a/pkg/analysis_server/test/services/completion/dart/imported_reference_contributor_test.dart +++ b/pkg/analysis_server/test/services/completion/dart/imported_reference_contributor_test.dart
@@ -1,12 +1,10 @@ -// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file +// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. import 'package:analysis_server/src/protocol_server.dart'; import 'package:analysis_server/src/provisional/completion/dart/completion_dart.dart'; import 'package:analysis_server/src/services/completion/dart/imported_reference_contributor.dart'; -import 'package:analyzer/src/generated/engine.dart'; -import 'package:analyzer/src/generated/source.dart'; import 'package:test/test.dart'; import 'package:test_reflective_loader/test_reflective_loader.dart'; @@ -30,7 +28,7 @@ /// Sanity check. Permutations tested in local_ref_contributor. test_ArgDefaults_function_with_required_named() async { - addMetaPackageSource(); + addMetaPackage(); resolveSource('/testB.dart', ''' lib B; @@ -504,7 +502,7 @@ await computeSuggestions(); expect(replacementOffset, completionOffset); expect(replacementLength, 0); - assertSuggestFunction('y', 'dynamic'); + assertSuggestFunction('y', 'Future<dynamic>'); assertNotSuggested('A'); assertSuggestClass('Object'); } @@ -1201,19 +1199,16 @@ } test_Block_unimported() async { - addPackageSource('myBar', 'bar.dart', 'class Foo2 { Foo2() { } }'); - addSource( - '/proj/testAB.dart', 'import "package:myBar/bar.dart"; class Foo { }'); - testFile = '/proj/completionTest.dart'; - addTestSource('class C {foo(){F^}}'); + addPackageFile('aaa', 'a.dart', 'class A {}'); + addTestSource('main() { ^ }'); await computeSuggestions(); - expect(replacementOffset, completionOffset - 1); - expect(replacementLength, 1); + expect(replacementOffset, completionOffset); + expect(replacementLength, 0); + // Not imported, so not suggested - assertNotSuggested('Foo'); - assertNotSuggested('Foo2'); - assertNotSuggested('Future'); + assertNotSuggested('A'); + assertNotSuggested('Completer'); } test_CascadeExpression_selector1() async { @@ -2367,6 +2362,36 @@ assertSuggestClass('Object'); } + test_functionTypeAlias_genericTypeAlias() async { + addSource('/a.dart', r''' +typedef F = void Function(); +'''); + addTestSource(r''' +import 'a.dart'; + +main() { + ^ +} +'''); + await computeSuggestions(); + assertSuggestFunctionTypeAlias('F', 'void'); + } + + test_functionTypeAlias_old() async { + addSource('/a.dart', r''' +typedef void F(); +'''); + addTestSource(r''' +import 'a.dart'; + +main() { + ^ +} +'''); + await computeSuggestions(); + assertSuggestFunctionTypeAlias('F', 'void'); + } + test_IfStatement() async { // SimpleIdentifier IfStatement addTestSource(''' @@ -2433,7 +2458,6 @@ } test_implicitCreation() async { - configurePreviewDart2(); addSource('/a.dart', ''' class A { A.a1(); @@ -2609,7 +2633,6 @@ } test_InstanceCreationExpression_filter() async { - configurePreviewDart2(); addSource('/a.dart', ''' class A {} class B extends A {} @@ -2637,7 +2660,12 @@ assertSuggestConstructor('D', elemOffset: -1); } + @failingTest test_InstanceCreationExpression_imported() async { + // This is failing because the constructor for Future is added twice. I + // suspect that we're adding it from both dart:core and dart:async and are + // not noticing that it's the same element. + // SimpleIdentifier TypeName ConstructorName InstanceCreationExpression addSource('/testA.dart', ''' int T1; @@ -2676,15 +2704,15 @@ test_InstanceCreationExpression_unimported() async { // SimpleIdentifier TypeName ConstructorName InstanceCreationExpression - addSource('/testAB.dart', 'class Foo { }'); - addTestSource('class C {foo(){new F^}}'); + addSource('/testAB.dart', 'class Clip { }'); + addTestSource('class A {foo(){new C^}}'); await computeSuggestions(); expect(replacementOffset, completionOffset - 1); expect(replacementLength, 1); // Not imported, so not suggested - assertNotSuggested('Future'); - assertNotSuggested('Foo'); + assertNotSuggested('Completer'); + assertNotSuggested('Clip'); } test_internal_sdk_libs() async { @@ -3252,9 +3280,7 @@ assertNotSuggested('_g'); assertSuggestClass('bool'); if (suggestConstructorsWithoutNew) { - // TODO(brianwilkerson) Should not suggest constructors for classes that - // cannot be instantiated. - assertSuggestConstructor('bool'); + assertSuggestConstructor('List'); } } @@ -3464,48 +3490,6 @@ assertNotSuggested('m'); } - /** - * Ensure that completions in one context don't appear in another - */ - test_multiple_contexts() async { - // Create a 2nd context with source - var context2 = AnalysisEngine.instance.createAnalysisContext(); - context2.sourceFactory = - new SourceFactory([new DartUriResolver(sdk), resourceResolver]); - String content2 = 'class ClassFromAnotherContext { }'; - Source source2 = - newFile('/context2/foo.dart', content: content2).createSource(); - ChangeSet changeSet = new ChangeSet(); - changeSet.addedSource(source2); - context2.applyChanges(changeSet); - context2.setContents(source2, content2); - - // Resolve the source in the 2nd context and update the index - var result = context2.performAnalysisTask(); - while (result.hasMoreWork) { - result = context2.performAnalysisTask(); - } - - // Check that source in 2nd context does not appear in completion in 1st - addSource('/context1/libA.dart', ''' - library libA; - class ClassInLocalContext {int x;}'''); - testFile = '/context1/completionTest.dart'; - addTestSource(''' - import "${convertAbsolutePathToUri("/context1/libA.dart")}"; - import "${convertAbsolutePathToUri("/foo.dart")}"; - main() {C^} - '''); - - await computeSuggestions(); - assertSuggestClass('ClassInLocalContext'); - if (suggestConstructorsWithoutNew) { - assertSuggestConstructor('ClassInLocalContext'); - } - // Assert contributor does not include results from 2nd context. - assertNotSuggested('ClassFromAnotherContext'); - } - test_new_instance() async { addTestSource('import "dart:math"; class A {x() {new Random().^}}'); @@ -3588,7 +3572,6 @@ class B { factory B.bar(int x) => null; } main() {new ^}'''); - await computeLibrariesContaining(); await computeSuggestions(); expect(replacementOffset, completionOffset); expect(replacementLength, 0); @@ -3624,7 +3607,6 @@ main() {new ^} var m;'''); - await computeLibrariesContaining(); await computeSuggestions(); expect(replacementOffset, completionOffset); expect(replacementLength, 0);
diff --git a/pkg/analysis_server/test/services/completion/dart/inherited_reference_contributor_test.dart b/pkg/analysis_server/test/services/completion/dart/inherited_reference_contributor_test.dart index d4689fe..d0b31fc 100644 --- a/pkg/analysis_server/test/services/completion/dart/inherited_reference_contributor_test.dart +++ b/pkg/analysis_server/test/services/completion/dart/inherited_reference_contributor_test.dart
@@ -1,6 +1,7 @@ -// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file +// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. + import 'dart:async'; import 'package:analysis_server/src/protocol_server.dart'; @@ -29,7 +30,7 @@ /// Sanity check. Permutations tested in local_ref_contributor. test_ArgDefaults_inherited_method_with_required_named() async { - addMetaPackageSource(); + addMetaPackage(); resolveSource('/testB.dart', ''' import 'package:meta/meta.dart'; @@ -72,7 +73,7 @@ assertNotSuggested('B'); assertNotSuggested('A'); assertNotSuggested('Object'); - assertSuggestMethod('y', 'A', 'dynamic'); + assertSuggestMethod('y', 'A', 'Future<dynamic>'); } test_Block_inherited_imported() async {
diff --git a/pkg/analysis_server/test/services/completion/dart/library_member_contributor_test.dart b/pkg/analysis_server/test/services/completion/dart/library_member_contributor_test.dart index 0bf6a76..2627c39 100644 --- a/pkg/analysis_server/test/services/completion/dart/library_member_contributor_test.dart +++ b/pkg/analysis_server/test/services/completion/dart/library_member_contributor_test.dart
@@ -94,7 +94,6 @@ part "${convertAbsolutePathToUri(testFile)}";'''); addTestSource('part of testA; foo() {bar.^}'); // Assume that libraries containing has been computed for part files - await computeLibrariesContaining(); await computeSuggestions(); assertSuggestClass('Future'); assertSuggestFunction('loadLibrary', 'Future<dynamic>'); @@ -195,7 +194,6 @@ part of testA; main() {b.^}'''); // Assume that libraries containing has been computed for part files - await computeLibrariesContaining(); await computeSuggestions(); expect(replacementOffset, completionOffset); expect(replacementLength, 0);
diff --git a/pkg/analysis_server/test/services/completion/dart/library_prefix_contributor_test.dart b/pkg/analysis_server/test/services/completion/dart/library_prefix_contributor_test.dart index 052103e..2d2cbac 100644 --- a/pkg/analysis_server/test/services/completion/dart/library_prefix_contributor_test.dart +++ b/pkg/analysis_server/test/services/completion/dart/library_prefix_contributor_test.dart
@@ -304,7 +304,6 @@ addTestSource(''' part of testB; main() {new ^ String x = "hello";}'''); - await computeLibrariesContaining(); await computeSuggestions(); assertSuggestLibraryPrefixes(['math', 't']); }
diff --git a/pkg/analysis_server/test/services/completion/dart/local_constructor_contributor_test.dart b/pkg/analysis_server/test/services/completion/dart/local_constructor_contributor_test.dart index d361dc9..7a841e7 100644 --- a/pkg/analysis_server/test/services/completion/dart/local_constructor_contributor_test.dart +++ b/pkg/analysis_server/test/services/completion/dart/local_constructor_contributor_test.dart
@@ -57,7 +57,7 @@ /// Sanity check. Permutations tested in local_ref_contributor. test_ArgDefaults_cons_with_required_named() async { - addMetaPackageSource(); + addMetaPackage(); addTestSource(''' import 'package:meta/meta.dart'; @@ -1142,18 +1142,15 @@ } test_Block_unimported() async { - addPackageSource('myBar', 'bar.dart', 'class Foo2 { Foo2() { } }'); - addSource( - '/proj/testAB.dart', 'import "package:myBar/bar.dart"; class Foo { }'); - testFile = '/proj/completionTest.dart'; - addTestSource('class C {foo(){F^}}'); - await computeSuggestions(); + addPackageFile('aaa', 'a.dart', 'class A {}'); + addTestSource('main() { ^ }'); - expect(replacementOffset, completionOffset - 1); - expect(replacementLength, 1); - assertNotSuggested('Foo'); - // TODO(danrubel) implement - assertNotSuggested('Foo2'); + await computeSuggestions(); + expect(replacementOffset, completionOffset); + expect(replacementLength, 0); + + // Not imported, so not suggested + assertNotSuggested('A'); assertNotSuggested('Future'); } @@ -3290,7 +3287,6 @@ part of libA; class B { factory B.bar(int x) => null; } main() {new ^}'''); - await computeLibrariesContaining(); await computeSuggestions(); expect(replacementOffset, completionOffset);
diff --git a/pkg/analysis_server/test/services/completion/dart/local_library_contributor_test.dart b/pkg/analysis_server/test/services/completion/dart/local_library_contributor_test.dart index 07d9364..dbe61ec 100644 --- a/pkg/analysis_server/test/services/completion/dart/local_library_contributor_test.dart +++ b/pkg/analysis_server/test/services/completion/dart/local_library_contributor_test.dart
@@ -39,7 +39,6 @@ part of libA; class B { factory B.bar(int x) => null; } main() {new ^}'''); - await computeLibrariesContaining(); await computeSuggestions(); expect(replacementOffset, completionOffset); expect(replacementLength, 0); @@ -74,7 +73,6 @@ class A { A({String boo: 'hoo'}) { } } main() {new ^} var m;'''); - await computeLibrariesContaining(); await computeSuggestions(); expect(replacementOffset, completionOffset); expect(replacementLength, 0); @@ -114,7 +112,6 @@ a = new ^ } var m;'''); - await computeLibrariesContaining(); await computeSuggestions(); expect(replacementOffset, completionOffset); expect(replacementLength, 0); @@ -165,7 +162,6 @@ A a = new ^ } var m;'''); - await computeLibrariesContaining(); await computeSuggestions(); expect(replacementOffset, completionOffset); expect(replacementLength, 0); @@ -214,7 +210,6 @@ part of libA; class B { factory B.bar(int x) => null; } main() {^}'''); - await computeLibrariesContaining(); await computeSuggestions(); expect(replacementOffset, completionOffset); expect(replacementLength, 0); @@ -261,7 +256,6 @@ class A { A({String boo: 'hoo'}) { } } main() {^} var m;'''); - await computeLibrariesContaining(); await computeSuggestions(); expect(replacementOffset, completionOffset); expect(replacementLength, 0);
diff --git a/pkg/analysis_server/test/services/completion/dart/local_reference_contributor_test.dart b/pkg/analysis_server/test/services/completion/dart/local_reference_contributor_test.dart index e96883c..2f3bad3 100644 --- a/pkg/analysis_server/test/services/completion/dart/local_reference_contributor_test.dart +++ b/pkg/analysis_server/test/services/completion/dart/local_reference_contributor_test.dart
@@ -1,4 +1,4 @@ -// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file +// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. @@ -87,7 +87,7 @@ } test_ArgDefaults_function_with_optional_positional() async { - addMetaPackageSource(); + addMetaPackage(); addTestSource(''' import 'package:meta/meta.dart'; @@ -102,7 +102,7 @@ } test_ArgDefaults_function_with_required_named() async { - addMetaPackageSource(); + addMetaPackage(); addTestSource(''' import 'package:meta/meta.dart'; @@ -117,7 +117,7 @@ } test_ArgDefaults_method_with_required_named() async { - addMetaPackageSource(); + addMetaPackage(); addTestSource(''' import 'package:meta/meta.dart'; @@ -783,7 +783,7 @@ await computeSuggestions(); expect(replacementOffset, completionOffset); expect(replacementLength, 0); - assertSuggestMethod('y', 'A', 'Future', + assertSuggestMethod('y', 'A', 'Future<dynamic>', relevance: DART_RELEVANCE_LOCAL_METHOD); assertSuggestClass('A'); assertNotSuggested('Object'); @@ -1415,18 +1415,15 @@ } test_Block_unimported() async { - addPackageSource('myBar', 'bar.dart', 'class Foo2 { Foo2() { } }'); - addSource( - '/proj/testAB.dart', 'import "package:myBar/bar.dart"; class Foo { }'); - testFile = '/proj/completionTest.dart'; - addTestSource('class C {foo(){F^}}'); - await computeSuggestions(); + addPackageFile('aaa', 'a.dart', 'class A {}'); + addTestSource('main() { ^ }'); - expect(replacementOffset, completionOffset - 1); - expect(replacementLength, 1); - assertNotSuggested('Foo'); - // TODO(danrubel) implement - assertNotSuggested('Foo2'); + await computeSuggestions(); + expect(replacementOffset, completionOffset); + expect(replacementLength, 0); + + // Not imported, so not suggested + assertNotSuggested('A'); assertNotSuggested('Future'); } @@ -1912,6 +1909,40 @@ assertSuggestParameter('y', 'int'); } + test_ConstructorFieldInitializer_name() async { + addTestSource(''' +class A { + final int foo; + A() : ^ +} +'''); + await computeSuggestions(); + + expect(replacementOffset, completionOffset); + expect(replacementLength, 0); + assertSuggestField('foo', 'int', relevance: DART_RELEVANCE_LOCAL_FIELD); + } + + test_ConstructorFieldInitializer_value() async { + addTestSource(''' +var foo = 0; + +class A { + final int bar; + A() : bar = ^ +} +'''); + await computeSuggestions(); + + expect(replacementOffset, completionOffset); + expect(replacementLength, 0); + assertSuggestTopLevelVar( + 'foo', + 'int', + relevance: DART_RELEVANCE_LOCAL_TOP_LEVEL_VARIABLE, + ); + } + test_ConstructorName_importedClass() async { // SimpleIdentifier PrefixedIdentifier TypeName ConstructorName // InstanceCreationExpression @@ -2747,6 +2778,28 @@ assertNotSuggested('Object'); } + test_functionTypeAlias_genericTypeAlias() async { + addTestSource(r''' +typedef F = void Function(); +main() { + ^ +} +'''); + await computeSuggestions(); + assertSuggestFunctionTypeAlias('F', 'void'); + } + + test_functionTypeAlias_old() async { + addTestSource(r''' +typedef void F(); +main() { + ^ +} +'''); + await computeSuggestions(); + assertSuggestFunctionTypeAlias('F', 'void'); + } + test_IfStatement() async { // SimpleIdentifier IfStatement addTestSource(''' @@ -3820,7 +3873,6 @@ class A { A({String boo: 'hoo'}) { } } main() {new ^} var m;'''); - await computeLibrariesContaining(); await computeSuggestions(); expect(replacementOffset, completionOffset);
diff --git a/pkg/analysis_server/test/services/completion/dart/override_contributor_test.dart b/pkg/analysis_server/test/services/completion/dart/override_contributor_test.dart index 8d5a329..cd1ffcc 100644 --- a/pkg/analysis_server/test/services/completion/dart/override_contributor_test.dart +++ b/pkg/analysis_server/test/services/completion/dart/override_contributor_test.dart
@@ -116,7 +116,6 @@ } '''); // assume information for context.getLibrariesContaining has been cached - await computeLibrariesContaining(); await computeSuggestions(); _assertOverride(''' @override
diff --git a/pkg/analysis_server/test/services/completion/dart/static_member_contributor_test.dart b/pkg/analysis_server/test/services/completion/dart/static_member_contributor_test.dart index 2987710..1907389 100644 --- a/pkg/analysis_server/test/services/completion/dart/static_member_contributor_test.dart +++ b/pkg/analysis_server/test/services/completion/dart/static_member_contributor_test.dart
@@ -98,7 +98,6 @@ } test_implicitCreation() async { - configurePreviewDart2(); addSource('/a.dart', ''' class A { A.foo(); @@ -257,7 +256,7 @@ import "dart:async" as async; void main() {async.Future.^.w()}'''); await computeSuggestions(); - assertSuggestMethod('wait', 'Future', 'Future<dynamic>'); + assertSuggestMethod('wait', 'Future', 'Future<List<T>>'); } test_PrefixedIdentifier_class_const() async {
diff --git a/pkg/analysis_server/test/services/completion/dart/type_member_contributor_test.dart b/pkg/analysis_server/test/services/completion/dart/type_member_contributor_test.dart index a39270d..d36ca4d 100644 --- a/pkg/analysis_server/test/services/completion/dart/type_member_contributor_test.dart +++ b/pkg/analysis_server/test/services/completion/dart/type_member_contributor_test.dart
@@ -81,7 +81,7 @@ } test_ArgDefaults_method_with_optional_positional() async { - addMetaPackageSource(); + addMetaPackage(); addTestSource(''' import 'package:meta/meta.dart'; @@ -96,7 +96,7 @@ } test_ArgDefaults_method_with_required_named() async { - addMetaPackageSource(); + addMetaPackage(); addTestSource(''' import 'package:meta/meta.dart'; @@ -1085,17 +1085,15 @@ } test_Block_unimported() async { - addPackageSource('myBar', 'bar.dart', 'class Foo2 { Foo2() { } }'); - addSource( - '/proj/testAB.dart', 'import "package:myBar/bar.dart"; class Foo { }'); - testFile = resourceProvider.convertPath('/proj/completionTest.dart'); - addTestSource('class C {foo(){F^}}'); + addPackageFile('aaa', 'a.dart', 'class A {}'); + addTestSource('main() { ^ }'); + await computeSuggestions(); - expect(replacementOffset, completionOffset - 1); - expect(replacementLength, 1); - assertNotSuggested('Foo'); - // TODO(danrubel) implement - assertNotSuggested('Foo2'); + expect(replacementOffset, completionOffset); + expect(replacementLength, 0); + + // Not imported, so not suggested + assertNotSuggested('A'); assertNotSuggested('Future'); }
diff --git a/pkg/analysis_server/test/services/completion/dart/uri_contributor_test.dart b/pkg/analysis_server/test/services/completion/dart/uri_contributor_test.dart index 7d66b12..c283cde 100644 --- a/pkg/analysis_server/test/services/completion/dart/uri_contributor_test.dart +++ b/pkg/analysis_server/test/services/completion/dart/uri_contributor_test.dart
@@ -67,9 +67,9 @@ } test_export_package2() async { - addPackageSource('foo', 'foo.dart', 'library foo;'); - addPackageSource('foo', 'baz/too.dart', 'library too;'); - addPackageSource('bar', 'bar.dart', 'library bar;'); + addPackageFile('foo', 'foo.dart', 'library foo;'); + addPackageFile('foo', 'baz/too.dart', 'library too;'); + addPackageFile('bar', 'bar.dart', 'library bar;'); addTestSource('export "package:foo/baz/^" import'); await computeSuggestions(); assertSuggest('package:foo/baz/too.dart', @@ -79,9 +79,9 @@ test_export_package2_off() async { try { UriContributor.suggestFilePaths = false; - addPackageSource('foo', 'foo.dart', 'library foo;'); - addPackageSource('foo', 'baz/too.dart', 'library too;'); - addPackageSource('bar', 'bar.dart', 'library bar;'); + addPackageFile('foo', 'foo.dart', 'library foo;'); + addPackageFile('foo', 'baz/too.dart', 'library too;'); + addPackageFile('bar', 'bar.dart', 'library bar;'); addTestSource('export "package:foo/baz/^" import'); await computeSuggestions(); assertNotSuggested('package:foo/baz/too.dart'); @@ -144,7 +144,7 @@ } test_import_file() async { - testFile = '/proj/completion.dart'; + testFile = convertPath('/proj/completion.dart'); addSource('/proj/other.dart', 'library other;'); addSource('/proj/foo/bar.dart', 'library bar;'); addSource('/blat.dart', 'library blat;'); @@ -161,7 +161,7 @@ } test_import_file2() async { - testFile = '/proj/completion.dart'; + testFile = convertPath('/proj/completion.dart'); addSource('/proj/other.dart', 'library other;'); addSource('/proj/foo/bar.dart', 'library bar;'); addSource('/blat.dart', 'library blat;'); @@ -180,7 +180,7 @@ test_import_file2_off() async { try { UriContributor.suggestFilePaths = false; - testFile = '/proj/completion.dart'; + testFile = convertPath('/proj/completion.dart'); addSource('/proj/other.dart', 'library other;'); addSource('/proj/foo/bar.dart', 'library bar;'); addSource('/blat.dart', 'library blat;'); @@ -200,7 +200,7 @@ } test_import_file_child() async { - testFile = '/proj/completion.dart'; + testFile = convertPath('/proj/completion.dart'); addSource('/proj/other.dart', 'library other;'); addSource('/proj/foo/bar.dart', 'library bar;'); addSource('/blat.dart', 'library blat;'); @@ -217,7 +217,7 @@ } test_import_file_outside_lib() async { - testFile = '/proj/lib/completion.dart'; + testFile = convertPath('/proj/lib/completion.dart'); addSource('/proj/lib/other.dart', 'library other;'); addSource('/proj/lib/foo/bar.dart', 'library bar;'); addSource('/proj/blat.dart', 'library blat;'); @@ -237,7 +237,7 @@ } test_import_file_parent() async { - testFile = '/proj/completion.dart'; + testFile = convertPath('/proj/completion.dart'); addSource('/proj/other.dart', 'library other;'); addSource('/proj/foo/bar.dart', 'library bar;'); addSource('/blat.dart', 'library blat;'); @@ -256,7 +256,7 @@ } test_import_file_parent2() async { - testFile = '/proj/completion.dart'; + testFile = convertPath('/proj/completion.dart'); addSource('/proj/other.dart', 'library other;'); addSource('/proj/foo/bar.dart', 'library bar;'); addSource('/blat.dart', 'library blat;'); @@ -273,7 +273,7 @@ } test_import_no_dot_folders() async { - testFile = '/proj/completion.dart'; + testFile = convertPath('/proj/completion.dart'); addSource('/proj/other.dart', 'library other;'); newFolder('/proj/.fooFolder'); addTestSource('import "package:^";'); @@ -282,7 +282,7 @@ } test_import_only_dart_files() async { - testFile = '/proj/completion.dart'; + testFile = convertPath('/proj/completion.dart'); addSource('/proj/other.dart', 'library other;'); newFile('/proj/analysis_options.yaml', content: '# analysis options'); addTestSource('import "package:^";'); @@ -291,9 +291,9 @@ } test_import_package() async { - addPackageSource('foo', 'foo.dart', 'library foo;'); - addPackageSource('foo', 'baz/too.dart', 'library too;'); - addPackageSource('bar', 'bar.dart', 'library bar;'); + addPackageFile('foo', 'foo.dart', 'library foo;'); + addPackageFile('foo', 'baz/too.dart', 'library too;'); + addPackageFile('bar', 'bar.dart', 'library bar;'); addTestSource('import "p^" import'); await computeSuggestions(); expect(replacementOffset, completionOffset - 1); @@ -310,9 +310,9 @@ } test_import_package2() async { - addPackageSource('foo', 'foo.dart', 'library foo;'); - addPackageSource('foo', 'baz/too.dart', 'library too;'); - addPackageSource('bar', 'bar.dart', 'library bar;'); + addPackageFile('foo', 'foo.dart', 'library foo;'); + addPackageFile('foo', 'baz/too.dart', 'library too;'); + addPackageFile('bar', 'bar.dart', 'library bar;'); addTestSource('import "package:foo/baz/^" import'); await computeSuggestions(); assertSuggest('package:foo/baz/too.dart', @@ -322,9 +322,9 @@ test_import_package2_off() async { try { UriContributor.suggestFilePaths = false; - addPackageSource('foo', 'foo.dart', 'library foo;'); - addPackageSource('foo', 'baz/too.dart', 'library too;'); - addPackageSource('bar', 'bar.dart', 'library bar;'); + addPackageFile('foo', 'foo.dart', 'library foo;'); + addPackageFile('foo', 'baz/too.dart', 'library too;'); + addPackageFile('bar', 'bar.dart', 'library bar;'); addTestSource('import "package:foo/baz/^" import'); await computeSuggestions(); assertNotSuggested('package:foo/baz/too.dart'); @@ -334,9 +334,9 @@ } test_import_package2_raw() async { - addPackageSource('foo', 'foo.dart', 'library foo;'); - addPackageSource('foo', 'baz/too.dart', 'library too;'); - addPackageSource('bar', 'bar.dart', 'library bar;'); + addPackageFile('foo', 'foo.dart', 'library foo;'); + addPackageFile('foo', 'baz/too.dart', 'library too;'); + addPackageFile('bar', 'bar.dart', 'library bar;'); addTestSource('import r"package:foo/baz/^" import'); await computeSuggestions(); assertSuggest('package:foo/baz/too.dart', @@ -344,9 +344,9 @@ } test_import_package2_with_trailing() async { - addPackageSource('foo', 'foo.dart', 'library foo;'); - addPackageSource('foo', 'baz/too.dart', 'library too;'); - addPackageSource('bar', 'bar.dart', 'library bar;'); + addPackageFile('foo', 'foo.dart', 'library foo;'); + addPackageFile('foo', 'baz/too.dart', 'library too;'); + addPackageFile('bar', 'bar.dart', 'library bar;'); addTestSource('import "package:foo/baz/^.dart" import'); await computeSuggestions(); assertSuggest('package:foo/baz/too.dart', @@ -356,8 +356,8 @@ } test_import_package_missing_lib() async { - var pkgSrc = addPackageSource('bar', 'bar.dart', 'library bar;'); - deleteFolder(dirname(pkgSrc.fullName)); + var pkgFile = addPackageFile('bar', 'bar.dart', 'library bar;'); + deleteFolder(pkgFile.parent.path); addTestSource('import "p^" class'); await computeSuggestions(); expect(replacementOffset, completionOffset - 1); @@ -368,9 +368,9 @@ } test_import_package_raw() async { - addPackageSource('foo', 'foo.dart', 'library foo;'); - addPackageSource('foo', 'baz/too.dart', 'library too;'); - addPackageSource('bar', 'bar.dart', 'library bar;'); + addPackageFile('foo', 'foo.dart', 'library foo;'); + addPackageFile('foo', 'baz/too.dart', 'library too;'); + addPackageFile('bar', 'bar.dart', 'library bar;'); addTestSource('import r"p^" import'); await computeSuggestions(); expect(replacementOffset, completionOffset - 1); @@ -460,7 +460,7 @@ } test_part_file() async { - testFile = '/proj/completion.dart'; + testFile = convertPath('/proj/completion.dart'); addSource('/proj/other.dart', 'library other;'); addSource('/proj/foo/bar.dart', 'library bar;'); addSource('/blat.dart', 'library blat;'); @@ -477,7 +477,7 @@ } test_part_file2() async { - testFile = '/proj/completion.dart'; + testFile = convertPath('/proj/completion.dart'); addSource('/proj/other.dart', 'library other;'); addSource('/proj/foo/bar.dart', 'library bar;'); addSource('/blat.dart', 'library blat;'); @@ -494,7 +494,7 @@ } test_part_file_child() async { - testFile = '/proj/completion.dart'; + testFile = convertPath('/proj/completion.dart'); addSource('/proj/other.dart', 'library other;'); addSource('/proj/foo/bar.dart', 'library bar;'); addSource('/blat.dart', 'library blat;'); @@ -511,7 +511,7 @@ } test_part_file_parent() async { - testFile = '/proj/completion.dart'; + testFile = convertPath('/proj/completion.dart'); addSource('/proj/other.dart', 'library other;'); addSource('/proj/foo/bar.dart', 'library bar;'); addSource('/blat.dart', 'library blat;'); @@ -541,7 +541,7 @@ } test_import_file() async { - testFile = '\\proj\\completion.dart'; + testFile = convertPath('\\proj\\completion.dart'); addSource('\\proj\\other.dart', 'library other;'); addSource('\\proj\\foo\\bar.dart', 'library bar;'); addSource('\\blat.dart', 'library blat;'); @@ -558,7 +558,7 @@ } test_import_file2() async { - testFile = '\\proj\\completion.dart'; + testFile = convertPath('\\proj\\completion.dart'); addSource('\\proj\\other.dart', 'library other;'); addSource('\\proj\\foo\\bar.dart', 'library bar;'); addSource('\\blat.dart', 'library blat;'); @@ -575,7 +575,7 @@ } test_import_file_child() async { - testFile = '\\proj\\completion.dart'; + testFile = convertPath('\\proj\\completion.dart'); addSource('\\proj\\other.dart', 'library other;'); addSource('\\proj\\foo\\bar.dart', 'library bar;'); addSource('\\blat.dart', 'library blat;'); @@ -592,7 +592,7 @@ } test_import_file_parent() async { - testFile = '\\proj\\completion.dart'; + testFile = convertPath('\\proj\\completion.dart'); addSource('\\proj\\other.dart', 'library other;'); addSource('\\proj\\foo\\bar.dart', 'library bar;'); addSource('\\blat.dart', 'library blat;'); @@ -609,7 +609,7 @@ } test_import_file_parent2() async { - testFile = '\\proj\\completion.dart'; + testFile = convertPath('\\proj\\completion.dart'); addSource('\\proj\\other.dart', 'library other;'); addSource('\\proj\\foo\\bar.dart', 'library bar;'); addSource('\\blat.dart', 'library blat;'); @@ -626,7 +626,7 @@ } test_part_file() async { - testFile = '\\proj\\completion.dart'; + testFile = convertPath('\\proj\\completion.dart'); addSource('\\proj\\other.dart', 'library other;'); addSource('\\proj\\foo\\bar.dart', 'library bar;'); addSource('\\blat.dart', 'library blat;'); @@ -643,7 +643,7 @@ } test_part_file2() async { - testFile = '\\proj\\completion.dart'; + testFile = convertPath('\\proj\\completion.dart'); addSource('\\proj\\other.dart', 'library other;'); addSource('\\proj\\foo\\bar.dart', 'library bar;'); addSource('\\blat.dart', 'library blat;'); @@ -660,7 +660,7 @@ } test_part_file_child() async { - testFile = '\\proj\\completion.dart'; + testFile = convertPath('\\proj\\completion.dart'); addSource('\\proj\\other.dart', 'library other;'); addSource('\\proj\\foo\\bar.dart', 'library bar;'); addSource('\\blat.dart', 'library blat;'); @@ -677,7 +677,7 @@ } test_part_file_parent() async { - testFile = '\\proj\\completion.dart'; + testFile = convertPath('\\proj\\completion.dart'); addSource('\\proj\\other.dart', 'library other;'); addSource('\\proj\\foo\\bar.dart', 'library bar;'); addSource('\\blat.dart', 'library blat;');
diff --git a/pkg/analysis_server/test/services/completion/postfix/postfix_completion_test.dart b/pkg/analysis_server/test/services/completion/postfix/postfix_completion_test.dart index e72c2e8..1fa242e 100644 --- a/pkg/analysis_server/test/services/completion/postfix/postfix_completion_test.dart +++ b/pkg/analysis_server/test/services/completion/postfix/postfix_completion_test.dart
@@ -79,15 +79,7 @@ verifyNoTestUnitErrors = false; await resolveTestUnit(code); - PostfixCompletionContext context = new PostfixCompletionContext( - testFile, - testAnalysisResult.lineInfo, - offset, - key, - testAnalysisResult.driver, - testUnit, - testUnitElement, - testAnalysisResult.errors); + var context = new PostfixCompletionContext(testAnalysisResult, offset, key); processor = new PostfixCompletionProcessor(context); } }
diff --git a/pkg/analysis_server/test/services/completion/statement/statement_completion_test.dart b/pkg/analysis_server/test/services/completion/statement/statement_completion_test.dart index 9ef3195..3fb9792 100644 --- a/pkg/analysis_server/test/services/completion/statement/statement_completion_test.dart +++ b/pkg/analysis_server/test/services/completion/statement/statement_completion_test.dart
@@ -4,7 +4,7 @@ import 'package:analysis_server/src/protocol_server.dart'; import 'package:analysis_server/src/services/completion/statement/statement_completion.dart'; -import 'package:analyzer/src/dart/analysis/driver.dart'; +import 'package:analyzer/dart/analysis/results.dart'; import 'package:test/test.dart'; import 'package:test_reflective_loader/test_reflective_loader.dart'; @@ -63,14 +63,8 @@ _computeCompletion(int offset) async { driver.changeFile(testFile); - AnalysisResult result = await driver.getResult(testFile); - StatementCompletionContext context = new StatementCompletionContext( - testFile, - result.lineInfo, - offset, - testUnit, - testUnitElement, - result.errors); + ResolvedUnitResult result = await session.getResolvedUnit(testFile); + var context = new StatementCompletionContext(result, offset); StatementCompletionProcessor processor = new StatementCompletionProcessor(context); StatementCompletion completion = await processor.compute();
diff --git a/pkg/analysis_server/test/services/correction/assist_test.dart b/pkg/analysis_server/test/services/correction/assist_test.dart deleted file mode 100644 index b9e542f..0000000 --- a/pkg/analysis_server/test/services/correction/assist_test.dart +++ /dev/null
@@ -1,6875 +0,0 @@ -// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file -// for details. All rights reserved. Use of this source code is governed by a -// BSD-style license that can be found in the LICENSE file. - -import 'dart:async'; - -import 'package:analysis_server/plugin/edit/assist/assist_core.dart'; -import 'package:analysis_server/plugin/edit/assist/assist_dart.dart'; -import 'package:analysis_server/src/services/correction/assist.dart'; -import 'package:analysis_server/src/services/correction/assist_internal.dart'; -import 'package:analyzer/dart/ast/ast.dart'; -import 'package:analyzer/dart/ast/standard_resolution_map.dart'; -import 'package:analyzer/dart/element/element.dart'; -import 'package:analyzer/src/dart/analysis/driver.dart'; -import 'package:analyzer/src/generated/engine.dart'; -import 'package:analyzer/src/generated/source.dart'; -import 'package:analyzer_plugin/protocol/protocol_common.dart'; -import 'package:analyzer_plugin/utilities/assist/assist.dart'; -import 'package:plugin/manager.dart'; -import 'package:test/test.dart'; -import 'package:test_reflective_loader/test_reflective_loader.dart'; - -import '../../abstract_single_unit.dart'; - -main() { - defineReflectiveSuite(() { - defineReflectiveTests(AssistProcessorTest); - }); -} - -@reflectiveTest -class AssistProcessorTest extends AbstractSingleUnitTest { - int offset; - int length; - - Assist assist; - SourceChange change; - String resultCode; - LinkedEditGroup linkedPositionGroup; - - bool get omitNew => true; - - /** - * Asserts that there is an [Assist] of the given [kind] at [offset] which - * produces the [expected] code when applied to [testCode]. - */ - assertHasAssist(AssistKind kind, String expected) async { - assist = await _assertHasAssist(kind); - change = assist.change; - expect(change.id, kind.id); - // apply to "file" - List<SourceFileEdit> fileEdits = change.edits; - expect(fileEdits, hasLength(1)); - resultCode = SourceEdit.applySequence(testCode, change.edits[0].edits); - // verify - expect(resultCode, expected); - } - - /** - * Calls [assertHasAssist] at the offset of [offsetSearch] in [testCode]. - */ - assertHasAssistAt( - String offsetSearch, AssistKind kind, String expected) async { - offset = findOffset(offsetSearch); - await assertHasAssist(kind, expected); - } - - /** - * Asserts that there is no [Assist] of the given [kind] at [offset]. - */ - assertNoAssist(AssistKind kind) async { - List<Assist> assists = await _computeAssists(); - for (Assist assist in assists) { - if (assist.kind == kind) { - fail('Unexpected assist $kind in\n${assists.join('\n')}'); - } - } - } - - /** - * Calls [assertNoAssist] at the offset of [offsetSearch] in [testCode]. - */ - assertNoAssistAt(String offsetSearch, AssistKind kind) async { - offset = findOffset(offsetSearch); - await assertNoAssist(kind); - } - - List<LinkedEditSuggestion> expectedSuggestions( - LinkedEditSuggestionKind kind, List<String> values) { - return values.map((value) { - return new LinkedEditSuggestion(value, kind); - }).toList(); - } - - void processRequiredPlugins() { - ExtensionManager manager = new ExtensionManager(); - manager.processPlugins(AnalysisEngine.instance.requiredPlugins); - } - - void setUp() { - super.setUp(); - offset = 0; - length = 0; - } - - test_addTypeAnnotation_BAD_privateType_closureParameter() async { - addSource('/project/my_lib.dart', ''' -library my_lib; -class A {} -class _B extends A {} -foo(f(_B p)) {} -'''); - await resolveTestUnit(''' -import 'my_lib.dart'; -main() { - foo((test) {}); -} - '''); - await assertNoAssistAt('test)', DartAssistKind.ADD_TYPE_ANNOTATION); - } - - test_addTypeAnnotation_BAD_privateType_declaredIdentifier() async { - addSource('/project/my_lib.dart', ''' -library my_lib; -class A {} -class _B extends A {} -List<_B> getValues() => []; -'''); - await resolveTestUnit(''' -import 'my_lib.dart'; -class A<T> { - main() { - for (var item in getValues()) { - } - } -} -'''); - await assertNoAssistAt('var item', DartAssistKind.ADD_TYPE_ANNOTATION); - } - - test_addTypeAnnotation_BAD_privateType_list() async { - // This is now failing because we're suggesting "List" rather than nothing. - // Is it really better to produce nothing? - addSource('/project/my_lib.dart', ''' -library my_lib; -class A {} -class _B extends A {} -List<_B> getValues() => []; -'''); - await resolveTestUnit(''' -import 'my_lib.dart'; -main() { - var v = getValues(); -} -'''); - await assertHasAssistAt('var ', DartAssistKind.ADD_TYPE_ANNOTATION, ''' -import 'my_lib.dart'; -main() { - List v = getValues(); -} -'''); - } - - test_addTypeAnnotation_BAD_privateType_variable() async { - addSource('/project/my_lib.dart', ''' -library my_lib; -class A {} -class _B extends A {} -_B getValue() => new _B(); -'''); - await resolveTestUnit(''' -import 'my_lib.dart'; -main() { - var v = getValue(); -} -'''); - await assertNoAssistAt('var ', DartAssistKind.ADD_TYPE_ANNOTATION); - } - - test_addTypeAnnotation_classField_OK_final() async { - await resolveTestUnit(''' -class A { - final f = 0; -} -'''); - await assertHasAssistAt('final ', DartAssistKind.ADD_TYPE_ANNOTATION, ''' -class A { - final int f = 0; -} -'''); - } - - test_addTypeAnnotation_classField_OK_int() async { - await resolveTestUnit(''' -class A { - var f = 0; -} -'''); - await await assertHasAssistAt( - 'var ', DartAssistKind.ADD_TYPE_ANNOTATION, ''' -class A { - int f = 0; -} -'''); - } - - test_addTypeAnnotation_declaredIdentifier_BAD_hasTypeAnnotation() async { - await resolveTestUnit(''' -main(List<String> items) { - for (String item in items) { - } -} -'''); - await assertNoAssistAt('item in', DartAssistKind.ADD_TYPE_ANNOTATION); - } - - test_addTypeAnnotation_declaredIdentifier_BAD_inForEachBody() async { - await resolveTestUnit(''' -main(List<String> items) { - for (var item in items) { - 42; - } -} -'''); - await assertNoAssistAt('42;', DartAssistKind.ADD_TYPE_ANNOTATION); - } - - test_addTypeAnnotation_declaredIdentifier_BAD_unknownType() async { - verifyNoTestUnitErrors = false; - await resolveTestUnit(''' -main() { - for (var item in unknownList) { - } -} -'''); - await assertNoAssistAt('item in', DartAssistKind.ADD_TYPE_ANNOTATION); - } - - test_addTypeAnnotation_declaredIdentifier_generic_OK() async { - await resolveTestUnit(''' -class A<T> { - main(List<List<T>> items) { - for (var item in items) { - } - } -} -'''); - await assertHasAssistAt('item in', DartAssistKind.ADD_TYPE_ANNOTATION, ''' -class A<T> { - main(List<List<T>> items) { - for (List<T> item in items) { - } - } -} -'''); - } - - test_addTypeAnnotation_declaredIdentifier_OK() async { - await resolveTestUnit(''' -main(List<String> items) { - for (var item in items) { - } -} -'''); - // on identifier - await assertHasAssistAt('item in', DartAssistKind.ADD_TYPE_ANNOTATION, ''' -main(List<String> items) { - for (String item in items) { - } -} -'''); - // on "for" - await assertHasAssistAt('for (', DartAssistKind.ADD_TYPE_ANNOTATION, ''' -main(List<String> items) { - for (String item in items) { - } -} -'''); - } - - test_addTypeAnnotation_declaredIdentifier_OK_addImport_dartUri() async { - addSource('/project/my_lib.dart', r''' -import 'dart:async'; -List<Future<int>> getFutures() => null; -'''); - await resolveTestUnit(''' -import 'my_lib.dart'; -main() { - for (var future in getFutures()) { - } -} -'''); - await assertHasAssistAt('future in', DartAssistKind.ADD_TYPE_ANNOTATION, ''' -import 'dart:async'; - -import 'my_lib.dart'; -main() { - for (Future<int> future in getFutures()) { - } -} -'''); - } - - test_addTypeAnnotation_declaredIdentifier_OK_final() async { - await resolveTestUnit(''' -main(List<String> items) { - for (final item in items) { - } -} -'''); - await assertHasAssistAt('item in', DartAssistKind.ADD_TYPE_ANNOTATION, ''' -main(List<String> items) { - for (final String item in items) { - } -} -'''); - } - - test_addTypeAnnotation_local_BAD_bottom() async { - await resolveTestUnit(''' -main() { - var v = throw 42; -} -'''); - await assertNoAssistAt('var ', DartAssistKind.ADD_TYPE_ANNOTATION); - } - - test_addTypeAnnotation_local_BAD_hasTypeAnnotation() async { - await resolveTestUnit(''' -main() { - int v = 42; -} -'''); - await assertNoAssistAt(' = 42', DartAssistKind.ADD_TYPE_ANNOTATION); - } - - test_addTypeAnnotation_local_BAD_multiple() async { - await resolveTestUnit(''' -main() { - var a = 1, b = ''; -} -'''); - await assertNoAssistAt('var ', DartAssistKind.ADD_TYPE_ANNOTATION); - } - - test_addTypeAnnotation_local_BAD_noValue() async { - verifyNoTestUnitErrors = false; - await resolveTestUnit(''' -main() { - var v; -} -'''); - await assertNoAssistAt('var ', DartAssistKind.ADD_TYPE_ANNOTATION); - } - - test_addTypeAnnotation_local_BAD_null() async { - await resolveTestUnit(''' -main() { - var v = null; -} -'''); - await assertNoAssistAt('var ', DartAssistKind.ADD_TYPE_ANNOTATION); - } - - test_addTypeAnnotation_local_BAD_onInitializer() async { - await resolveTestUnit(''' -main() { - var abc = 0; -} -'''); - await assertNoAssistAt('0;', DartAssistKind.ADD_TYPE_ANNOTATION); - } - - test_addTypeAnnotation_local_BAD_unknown() async { - verifyNoTestUnitErrors = false; - await resolveTestUnit(''' -main() { - var v = unknownVar; -} -'''); - await assertNoAssistAt('var ', DartAssistKind.ADD_TYPE_ANNOTATION); - } - - test_addTypeAnnotation_local_generic_OK_literal() async { - await resolveTestUnit(''' -class A { - main(List<int> items) { - var v = items; - } -} -'''); - await assertHasAssistAt('v =', DartAssistKind.ADD_TYPE_ANNOTATION, ''' -class A { - main(List<int> items) { - List<int> v = items; - } -} -'''); - } - - test_addTypeAnnotation_local_generic_OK_local() async { - await resolveTestUnit(''' -class A<T> { - main(List<T> items) { - var v = items; - } -} -'''); - await assertHasAssistAt('v =', DartAssistKind.ADD_TYPE_ANNOTATION, ''' -class A<T> { - main(List<T> items) { - List<T> v = items; - } -} -'''); - } - - test_addTypeAnnotation_local_OK_addImport_dartUri() async { - addSource('/project/my_lib.dart', r''' -import 'dart:async'; -Future<int> getFutureInt() => null; -'''); - await resolveTestUnit(''' -import 'my_lib.dart'; -main() { - var v = getFutureInt(); -} -'''); - await assertHasAssistAt('v =', DartAssistKind.ADD_TYPE_ANNOTATION, ''' -import 'dart:async'; - -import 'my_lib.dart'; -main() { - Future<int> v = getFutureInt(); -} -'''); - } - - test_addTypeAnnotation_local_OK_addImport_notLibraryUnit() async { - // prepare library - addSource('/project/my_lib.dart', r''' -import 'dart:async'; -Future<int> getFutureInt() => null; -'''); - // prepare code - String appCode = r''' -library my_app; -import 'my_lib.dart'; -part 'test.dart'; -'''; - testCode = r''' -part of my_app; -main() { - var v = getFutureInt(); -} -'''; - // add sources - addSource('/project/app.dart', appCode); - testSource = addSource('/project/test.dart', testCode); - // resolve - await resolveTestUnit(testCode); - // prepare the assist - offset = findOffset('v = '); - assist = await _assertHasAssist(DartAssistKind.ADD_TYPE_ANNOTATION); - change = assist.change; - // verify - { - var testFileEdit = change.getFileEdit(convertPath('/project/app.dart')); - var resultCode = SourceEdit.applySequence(appCode, testFileEdit.edits); - expect(resultCode, ''' -library my_app; -import 'dart:async'; - -import 'my_lib.dart'; -part 'test.dart'; -'''); - } - { - var testFileEdit = change.getFileEdit(convertPath('/project/test.dart')); - var resultCode = SourceEdit.applySequence(testCode, testFileEdit.edits); - expect(resultCode, ''' -part of my_app; -main() { - Future<int> v = getFutureInt(); -} -'''); - } - } - - test_addTypeAnnotation_local_OK_addImport_relUri() async { - addSource('/project/aa/bbb/lib_a.dart', r''' -class MyClass {} -'''); - addSource('/project/ccc/lib_b.dart', r''' -import '../aa/bbb/lib_a.dart'; -MyClass newMyClass() => null; -'''); - await resolveTestUnit(''' -import 'ccc/lib_b.dart'; -main() { - var v = newMyClass(); -} -'''); - await assertHasAssistAt('v =', DartAssistKind.ADD_TYPE_ANNOTATION, ''' -import 'aa/bbb/lib_a.dart'; -import 'ccc/lib_b.dart'; -main() { - MyClass v = newMyClass(); -} -'''); - } - - test_addTypeAnnotation_local_OK_Function() async { - await resolveTestUnit(''' -main() { - var v = () => 1; -} -'''); - await assertHasAssistAt('v =', DartAssistKind.ADD_TYPE_ANNOTATION, ''' -main() { - int Function() v = () => 1; -} -'''); - } - - test_addTypeAnnotation_local_OK_int() async { - await resolveTestUnit(''' -main() { - var v = 0; -} -'''); - await assertHasAssistAt('v =', DartAssistKind.ADD_TYPE_ANNOTATION, ''' -main() { - int v = 0; -} -'''); - } - - test_addTypeAnnotation_local_OK_List() async { - await resolveTestUnit(''' -main() { - var v = <String>[]; -} -'''); - await assertHasAssistAt('v =', DartAssistKind.ADD_TYPE_ANNOTATION, ''' -main() { - List<String> v = <String>[]; -} -'''); - } - - test_addTypeAnnotation_local_OK_localType() async { - await resolveTestUnit(''' -class C {} -C f() => null; -main() { - var x = f(); -} -'''); - await assertHasAssistAt('x =', DartAssistKind.ADD_TYPE_ANNOTATION, ''' -class C {} -C f() => null; -main() { - C x = f(); -} -'''); - } - - test_addTypeAnnotation_local_OK_onName() async { - await resolveTestUnit(''' -main() { - var abc = 0; -} -'''); - await assertHasAssistAt('bc', DartAssistKind.ADD_TYPE_ANNOTATION, ''' -main() { - int abc = 0; -} -'''); - } - - test_addTypeAnnotation_local_OK_onVar() async { - await resolveTestUnit(''' -main() { - var v = 0; -} -'''); - await assertHasAssistAt('var ', DartAssistKind.ADD_TYPE_ANNOTATION, ''' -main() { - int v = 0; -} -'''); - } - - test_addTypeAnnotation_OK_privateType_sameLibrary() async { - await resolveTestUnit(''' -class _A {} -_A getValue() => new _A(); -main() { - var v = getValue(); -} -'''); - await assertHasAssistAt('var ', DartAssistKind.ADD_TYPE_ANNOTATION, ''' -class _A {} -_A getValue() => new _A(); -main() { - _A v = getValue(); -} -'''); - } - - test_addTypeAnnotation_parameter_BAD_hasExplicitType() async { - await resolveTestUnit(''' -foo(f(int p)) {} -main() { - foo((num test) {}); -} -'''); - await assertNoAssistAt('test', DartAssistKind.ADD_TYPE_ANNOTATION); - } - - test_addTypeAnnotation_parameter_BAD_noPropagatedType() async { - await resolveTestUnit(''' -foo(f(p)) {} -main() { - foo((test) {}); -} -'''); - await assertNoAssistAt('test', DartAssistKind.ADD_TYPE_ANNOTATION); - } - - test_addTypeAnnotation_parameter_OK() async { - await resolveTestUnit(''' -foo(f(int p)) {} -main() { - foo((test) {}); -} -'''); - await assertHasAssistAt('test', DartAssistKind.ADD_TYPE_ANNOTATION, ''' -foo(f(int p)) {} -main() { - foo((int test) {}); -} -'''); - } - - test_addTypeAnnotation_topLevelField_BAD_multiple() async { - await resolveTestUnit(''' -var A = 1, V = ''; -'''); - await assertNoAssistAt('var ', DartAssistKind.ADD_TYPE_ANNOTATION); - } - - test_addTypeAnnotation_topLevelField_BAD_noValue() async { - await resolveTestUnit(''' -var V; -'''); - await assertNoAssistAt('var ', DartAssistKind.ADD_TYPE_ANNOTATION); - } - - test_addTypeAnnotation_topLevelField_OK_int() async { - await resolveTestUnit(''' -var V = 0; -'''); - await assertHasAssistAt('var ', DartAssistKind.ADD_TYPE_ANNOTATION, ''' -int V = 0; -'''); - } - - test_assignToLocalVariable() async { - await resolveTestUnit(''' -main() { - List<int> bytes; - readBytes(); -} -List<int> readBytes() => <int>[]; -'''); - await assertHasAssistAt( - 'readBytes();', DartAssistKind.ASSIGN_TO_LOCAL_VARIABLE, ''' -main() { - List<int> bytes; - var readBytes = readBytes(); -} -List<int> readBytes() => <int>[]; -'''); - _assertLinkedGroup( - change.linkedEditGroups[0], - ['readBytes = '], - expectedSuggestions(LinkedEditSuggestionKind.VARIABLE, - ['list', 'bytes2', 'readBytes'])); - } - - test_assignToLocalVariable_alreadyAssignment() async { - await resolveTestUnit(''' -main() { - var vvv; - vvv = 42; -} -'''); - await assertNoAssistAt('vvv =', DartAssistKind.ASSIGN_TO_LOCAL_VARIABLE); - } - - test_assignToLocalVariable_inClosure() async { - await resolveTestUnit(r''' -main() { - print(() { - 12345; - }); -} -'''); - await assertHasAssistAt('345', DartAssistKind.ASSIGN_TO_LOCAL_VARIABLE, ''' -main() { - print(() { - var i = 12345; - }); -} -'''); - } - - test_assignToLocalVariable_invocationArgument() async { - await resolveTestUnit(r''' -main() { - f(12345); -} -void f(p) {} -'''); - await assertNoAssistAt('345', DartAssistKind.ASSIGN_TO_LOCAL_VARIABLE); - } - - test_assignToLocalVariable_throw() async { - await resolveTestUnit(''' -main() { - throw 42; -} -'''); - await assertNoAssistAt('throw ', DartAssistKind.ASSIGN_TO_LOCAL_VARIABLE); - } - - test_assignToLocalVariable_void() async { - await resolveTestUnit(''' -main() { - f(); -} -void f() {} -'''); - await assertNoAssistAt('f();', DartAssistKind.ASSIGN_TO_LOCAL_VARIABLE); - } - - test_convertClassToMixin_abstract() async { - await resolveTestUnit(''' -abstract class A {} -'''); - await assertHasAssistAt('A', DartAssistKind.CONVERT_CLASS_TO_MIXIN, ''' -mixin A {} -'''); - } - - test_convertClassToMixin_extends_noSuper() async { - await resolveTestUnit(''' -class A {} -class B extends A {} -'''); - await assertHasAssistAt('B', DartAssistKind.CONVERT_CLASS_TO_MIXIN, ''' -class A {} -mixin B implements A {} -'''); - } - - test_convertClassToMixin_extends_super() async { - await resolveTestUnit(''' -class A { - a() {} -} -class B extends A { - b() { - super.a(); - } -} -'''); - await assertHasAssistAt('B', DartAssistKind.CONVERT_CLASS_TO_MIXIN, ''' -class A { - a() {} -} -mixin B on A { - b() { - super.a(); - } -} -'''); - } - - test_convertClassToMixin_extends_superSuper() async { - await resolveTestUnit(''' -class A { - a() {} -} -class B extends A {} -class C extends B { - c() { - super.a(); - } -} -'''); - await assertHasAssistAt('C', DartAssistKind.CONVERT_CLASS_TO_MIXIN, ''' -class A { - a() {} -} -class B extends A {} -mixin C on B { - c() { - super.a(); - } -} -'''); - } - - test_convertClassToMixin_extendsImplements_noSuper() async { - await resolveTestUnit(''' -class A {} -class B {} -class C extends A implements B {} -'''); - await assertHasAssistAt('C', DartAssistKind.CONVERT_CLASS_TO_MIXIN, ''' -class A {} -class B {} -mixin C implements A, B {} -'''); - } - - test_convertClassToMixin_extendsImplements_super_extends() async { - await resolveTestUnit(''' -class A { - a() {} -} -class B {} -class C extends A implements B { - c() { - super.a(); - } -} -'''); - await assertHasAssistAt('C', DartAssistKind.CONVERT_CLASS_TO_MIXIN, ''' -class A { - a() {} -} -class B {} -mixin C on A implements B { - c() { - super.a(); - } -} -'''); - } - - test_convertClassToMixin_extendsWith_noSuper() async { - await resolveTestUnit(''' -class A {} -class B {} -class C extends A with B {} -'''); - await assertHasAssistAt('C', DartAssistKind.CONVERT_CLASS_TO_MIXIN, ''' -class A {} -class B {} -mixin C implements A, B {} -'''); - } - - test_convertClassToMixin_extendsWith_super_both() async { - await resolveTestUnit(''' -class A { - a() {} -} -class B { - b() {} -} -class C extends A with B { - c() { - super.a(); - super.b(); - } -} -'''); - await assertHasAssistAt('C', DartAssistKind.CONVERT_CLASS_TO_MIXIN, ''' -class A { - a() {} -} -class B { - b() {} -} -mixin C on A, B { - c() { - super.a(); - super.b(); - } -} -'''); - } - - test_convertClassToMixin_extendsWith_super_extends() async { - await resolveTestUnit(''' -class A { - a() {} -} -class B { - b() {} -} -class C extends A with B { - c() { - super.a(); - } -} -'''); - await assertHasAssistAt('C', DartAssistKind.CONVERT_CLASS_TO_MIXIN, ''' -class A { - a() {} -} -class B { - b() {} -} -mixin C on A implements B { - c() { - super.a(); - } -} -'''); - } - - test_convertClassToMixin_extendsWith_super_with() async { - await resolveTestUnit(''' -class A { - a() {} -} -class B { - b() {} -} -class C extends A with B { - c() { - super.b(); - } -} -'''); - await assertHasAssistAt('C', DartAssistKind.CONVERT_CLASS_TO_MIXIN, ''' -class A { - a() {} -} -class B { - b() {} -} -mixin C on B implements A { - c() { - super.b(); - } -} -'''); - } - - test_convertClassToMixin_extendsWithImplements_noSuper() async { - await resolveTestUnit(''' -class A {} -class B {} -class C {} -class D extends A with B implements C {} -'''); - await assertHasAssistAt('D', DartAssistKind.CONVERT_CLASS_TO_MIXIN, ''' -class A {} -class B {} -class C {} -mixin D implements A, B, C {} -'''); - } - - test_convertClassToMixin_extendsWithImplements_super_both() async { - await resolveTestUnit(''' -class A { - a() {} -} -class B { - b() {} -} -class C {} -class D extends A with B implements C { - d() { - super.a(); - super.b(); - } -} -'''); - await assertHasAssistAt('D', DartAssistKind.CONVERT_CLASS_TO_MIXIN, ''' -class A { - a() {} -} -class B { - b() {} -} -class C {} -mixin D on A, B implements C { - d() { - super.a(); - super.b(); - } -} -'''); - } - - test_convertClassToMixin_extendsWithImplements_super_extends() async { - await resolveTestUnit(''' -class A { - a() {} -} -class B { - b() {} -} -class C {} -class D extends A with B implements C { - d() { - super.a(); - } -} -'''); - await assertHasAssistAt('D', DartAssistKind.CONVERT_CLASS_TO_MIXIN, ''' -class A { - a() {} -} -class B { - b() {} -} -class C {} -mixin D on A implements B, C { - d() { - super.a(); - } -} -'''); - } - - test_convertClassToMixin_extendsWithImplements_super_with() async { - await resolveTestUnit(''' -class A { - a() {} -} -class B { - b() {} -} -class C {} -class D extends A with B implements C { - d() { - super.b(); - } -} -'''); - await assertHasAssistAt('D', DartAssistKind.CONVERT_CLASS_TO_MIXIN, ''' -class A { - a() {} -} -class B { - b() {} -} -class C {} -mixin D on B implements A, C { - d() { - super.b(); - } -} -'''); - } - - test_convertClassToMixin_implements() async { - await resolveTestUnit(''' -class A {} -class B implements A {} -'''); - await assertHasAssistAt('B', DartAssistKind.CONVERT_CLASS_TO_MIXIN, ''' -class A {} -mixin B implements A {} -'''); - } - - test_convertClassToMixin_noClauses_invalidSelection() async { - await resolveTestUnit(''' -class A {} -'''); - await assertNoAssistAt( - '{}', - DartAssistKind.CONVERT_CLASS_TO_MIXIN, - ); - } - - test_convertClassToMixin_noClauses_selectKeyword() async { - await resolveTestUnit(''' -class A {} -'''); - await assertHasAssistAt('class', DartAssistKind.CONVERT_CLASS_TO_MIXIN, ''' -mixin A {} -'''); - } - - test_convertClassToMixin_noClauses_selectName() async { - await resolveTestUnit(''' -class A {} -'''); - await assertHasAssistAt('A', DartAssistKind.CONVERT_CLASS_TO_MIXIN, ''' -mixin A {} -'''); - } - - test_convertClassToMixin_with_noSuper() async { - await resolveTestUnit(''' -class A {} -class B with A {} -'''); - await assertHasAssistAt('B', DartAssistKind.CONVERT_CLASS_TO_MIXIN, ''' -class A {} -mixin B implements A {} -'''); - } - - test_convertClassToMixin_with_super() async { - await resolveTestUnit(''' -class A { - a() {} -} -class B with A { - b() { - super.a(); - } -} -'''); - await assertHasAssistAt('B', DartAssistKind.CONVERT_CLASS_TO_MIXIN, ''' -class A { - a() {} -} -mixin B on A { - b() { - super.a(); - } -} -'''); - } - - test_convertDocumentationIntoBlock_BAD_alreadyBlock() async { - await resolveTestUnit(''' -/** - * AAAAAAA - */ -class A {} -'''); - await assertNoAssistAt( - 'AAA', DartAssistKind.CONVERT_DOCUMENTATION_INTO_BLOCK); - } - - test_convertDocumentationIntoBlock_BAD_notDocumentation() async { - await resolveTestUnit(''' -// AAAA -class A {} -'''); - await assertNoAssistAt( - 'AAA', DartAssistKind.CONVERT_DOCUMENTATION_INTO_BLOCK); - } - - test_convertDocumentationIntoBlock_OK_noSpaceBeforeText() async { - await resolveTestUnit(''' -class A { - /// AAAAA - ///BBBBB - /// - /// CCCCC - mmm() {} -} -'''); - await assertHasAssistAt( - 'AAAAA', DartAssistKind.CONVERT_DOCUMENTATION_INTO_BLOCK, ''' -class A { - /** - * AAAAA - *BBBBB - * - * CCCCC - */ - mmm() {} -} -'''); - } - - test_convertDocumentationIntoBlock_OK_onReference() async { - await resolveTestUnit(''' -/// AAAAAAA [int] AAAAAAA -class A {} -'''); - await assertHasAssistAt( - 'nt]', DartAssistKind.CONVERT_DOCUMENTATION_INTO_BLOCK, ''' -/** - * AAAAAAA [int] AAAAAAA - */ -class A {} -'''); - } - - test_convertDocumentationIntoBlock_OK_onText() async { - await resolveTestUnit(''' -class A { - /// AAAAAAA [int] AAAAAAA - /// BBBBBBBB BBBB BBBB - /// CCC [A] CCCCCCCCCCC - mmm() {} -} -'''); - await assertHasAssistAt( - 'AAA [', DartAssistKind.CONVERT_DOCUMENTATION_INTO_BLOCK, ''' -class A { - /** - * AAAAAAA [int] AAAAAAA - * BBBBBBBB BBBB BBBB - * CCC [A] CCCCCCCCCCC - */ - mmm() {} -} -'''); - } - - test_convertDocumentationIntoLine_BAD_alreadyLine() async { - await resolveTestUnit(''' -/// AAAAAAA -class A {} -'''); - await assertNoAssistAt( - 'AAA', DartAssistKind.CONVERT_DOCUMENTATION_INTO_LINE); - } - - test_convertDocumentationIntoLine_BAD_notDocumentation() async { - await resolveTestUnit(''' -/* AAAA */ -class A {} -'''); - await assertNoAssistAt( - 'AAA', DartAssistKind.CONVERT_DOCUMENTATION_INTO_LINE); - } - - test_convertDocumentationIntoLine_OK_onReference() async { - await resolveTestUnit(''' -/** - * AAAAAAA [int] AAAAAAA - */ -class A {} -'''); - await assertHasAssistAt( - 'nt]', DartAssistKind.CONVERT_DOCUMENTATION_INTO_LINE, ''' -/// AAAAAAA [int] AAAAAAA -class A {} -'''); - } - - test_convertDocumentationIntoLine_OK_onText() async { - await resolveTestUnit(''' -class A { - /** - * AAAAAAA [int] AAAAAAA - * BBBBBBBB BBBB BBBB - * CCC [A] CCCCCCCCCCC - */ - mmm() {} -} -'''); - await assertHasAssistAt( - 'AAA [', DartAssistKind.CONVERT_DOCUMENTATION_INTO_LINE, ''' -class A { - /// AAAAAAA [int] AAAAAAA - /// BBBBBBBB BBBB BBBB - /// CCC [A] CCCCCCCCCCC - mmm() {} -} -'''); - } - - test_convertDocumentationIntoLine_OK_onText_hasFirstLine() async { - await resolveTestUnit(''' -class A { - /** AAAAAAA [int] AAAAAAA - * BBBBBBBB BBBB BBBB - * CCC [A] CCCCCCCCCCC - */ - mmm() {} -} -'''); - await assertHasAssistAt( - 'AAA [', DartAssistKind.CONVERT_DOCUMENTATION_INTO_LINE, ''' -class A { - /// AAAAAAA [int] AAAAAAA - /// BBBBBBBB BBBB BBBB - /// CCC [A] CCCCCCCCCCC - mmm() {} -} -'''); - } - - test_convertPartOfToUri_file_nonSibling() async { - addSource('/pkg/lib/foo.dart', ''' -library foo; -part 'src/bar.dart'; -'''); - testFile = resourceProvider.convertPath('/pkg/lib/src/bar.dart'); - await resolveTestUnit(''' -part of foo; -'''); - await assertHasAssistAt('foo', DartAssistKind.CONVERT_PART_OF_TO_URI, ''' -part of '../foo.dart'; -'''); - } - - test_convertPartOfToUri_file_sibling() async { - addSource('/pkg/foo.dart', ''' -library foo; -part 'bar.dart'; -'''); - testFile = resourceProvider.convertPath('/pkg/bar.dart'); - await resolveTestUnit(''' -part of foo; -'''); - await assertHasAssistAt('foo', DartAssistKind.CONVERT_PART_OF_TO_URI, ''' -part of 'foo.dart'; -'''); - } - - test_convertToAsyncBody_BAD_async() async { - await resolveTestUnit(''' -import 'dart:async'; -Future<String> f() async => ''; -'''); - await assertNoAssistAt('=>', DartAssistKind.CONVERT_INTO_ASYNC_BODY); - } - - test_convertToAsyncBody_BAD_asyncStar() async { - await resolveTestUnit(''' -import 'dart:async'; -Stream<String> f() async* {} -'''); - await assertNoAssistAt('{}', DartAssistKind.CONVERT_INTO_ASYNC_BODY); - } - - test_convertToAsyncBody_BAD_constructor() async { - await resolveTestUnit(''' -class C { - C() {} -} -'''); - await assertNoAssistAt('{}', DartAssistKind.CONVERT_INTO_ASYNC_BODY); - } - - test_convertToAsyncBody_BAD_inBody_block() async { - await resolveTestUnit(''' -class C { - void foo() { - print(42); - } -} -'''); - await assertNoAssistAt('print', DartAssistKind.CONVERT_INTO_ASYNC_BODY); - } - - test_convertToAsyncBody_BAD_inBody_expression() async { - await resolveTestUnit(''' -class C { - void foo() => print(42); -} -'''); - await assertNoAssistAt('print', DartAssistKind.CONVERT_INTO_ASYNC_BODY); - } - - test_convertToAsyncBody_BAD_syncStar() async { - await resolveTestUnit(''' -Iterable<String> f() sync* {} -'''); - await assertNoAssistAt('{}', DartAssistKind.CONVERT_INTO_ASYNC_BODY); - } - - test_convertToAsyncBody_OK_closure() async { - await resolveTestUnit(''' -main() { - f(() => 123); -} -f(g) {} -'''); - await assertHasAssistAt('=>', DartAssistKind.CONVERT_INTO_ASYNC_BODY, ''' -main() { - f(() async => 123); -} -f(g) {} -'''); - } - - test_convertToAsyncBody_OK_function() async { - // TODO(brianwilkerson) Remove the "class C {}" when the bug in the builder - // is fixed that causes the import to be incorrectly inserted when the first - // character in the file is also being modified. - await resolveTestUnit(''' -class C {} -String f() => ''; -'''); - await assertHasAssistAt('=>', DartAssistKind.CONVERT_INTO_ASYNC_BODY, ''' -import 'dart:async'; - -class C {} -Future<String> f() async => ''; -'''); - } - - test_convertToAsyncBody_OK_getter_expression_noSpace() async { - await resolveTestUnit(''' -class C { - int get g=>0; -} -'''); - await assertHasAssistAt('get g', DartAssistKind.CONVERT_INTO_ASYNC_BODY, ''' -import 'dart:async'; - -class C { - Future<int> get g async =>0; -} -'''); - } - - test_convertToAsyncBody_OK_method() async { - await resolveTestUnit(''' -class C { - int m() { return 0; } -} -'''); - await assertHasAssistAt( - '{ return', DartAssistKind.CONVERT_INTO_ASYNC_BODY, ''' -import 'dart:async'; - -class C { - Future<int> m() async { return 0; } -} -'''); - } - - test_convertToAsyncBody_OK_method_abstract() async { - await resolveTestUnit(''' -abstract class C { - int m(); -} -'''); - await assertHasAssistAt('m()', DartAssistKind.CONVERT_INTO_ASYNC_BODY, ''' -import 'dart:async'; - -abstract class C { - Future<int> m(); -} -'''); - } - - test_convertToAsyncBody_OK_method_noReturnType() async { - await resolveTestUnit(''' -class C { - m() { return 0; } -} -'''); - await assertHasAssistAt( - '{ return', DartAssistKind.CONVERT_INTO_ASYNC_BODY, ''' -class C { - m() async { return 0; } -} -'''); - } - - test_convertToBlockBody_BAD_inExpression() async { - await resolveTestUnit(''' -main() => 123; -'''); - await assertNoAssistAt('123;', DartAssistKind.CONVERT_INTO_BLOCK_BODY); - } - - test_convertToBlockBody_BAD_noEnclosingFunction() async { - await resolveTestUnit(''' -var v = 123; -'''); - await assertNoAssistAt('v =', DartAssistKind.CONVERT_INTO_BLOCK_BODY); - } - - test_convertToBlockBody_BAD_notExpressionBlock() async { - await resolveTestUnit(''' -fff() { - return 123; -} -'''); - await assertNoAssistAt('fff() {', DartAssistKind.CONVERT_INTO_BLOCK_BODY); - } - - test_convertToBlockBody_OK_async() async { - await resolveTestUnit(''' -class A { - mmm() async => 123; -} -'''); - await assertHasAssistAt('mmm()', DartAssistKind.CONVERT_INTO_BLOCK_BODY, ''' -class A { - mmm() async { - return 123; - } -} -'''); - } - - test_convertToBlockBody_OK_closure() async { - await resolveTestUnit(''' -setup(x) {} -main() { - setup(() => 42); -} -'''); - await assertHasAssistAt( - '() => 42', DartAssistKind.CONVERT_INTO_BLOCK_BODY, ''' -setup(x) {} -main() { - setup(() { - return 42; - }); -} -'''); - { - Position exitPos = change.selection; - expect(exitPos, isNotNull); - expect(exitPos.file, testFile); - expect(exitPos.offset - 3, resultCode.indexOf('42;')); - } - } - - test_convertToBlockBody_OK_closure_voidExpression() async { - await resolveTestUnit(''' -setup(x) {} -main() { - setup(() => print('done')); -} -'''); - await assertHasAssistAt( - '() => print', DartAssistKind.CONVERT_INTO_BLOCK_BODY, ''' -setup(x) {} -main() { - setup(() { - print('done'); - }); -} -'''); - { - Position exitPos = change.selection; - expect(exitPos, isNotNull); - expect(exitPos.file, testFile); - expect(exitPos.offset - 3, resultCode.indexOf("');")); - } - } - - test_convertToBlockBody_OK_constructor() async { - await resolveTestUnit(''' -class A { - factory A() => null; -} -'''); - await assertHasAssistAt('A()', DartAssistKind.CONVERT_INTO_BLOCK_BODY, ''' -class A { - factory A() { - return null; - } -} -'''); - } - - test_convertToBlockBody_OK_method() async { - await resolveTestUnit(''' -class A { - mmm() => 123; -} -'''); - await assertHasAssistAt('mmm()', DartAssistKind.CONVERT_INTO_BLOCK_BODY, ''' -class A { - mmm() { - return 123; - } -} -'''); - } - - test_convertToBlockBody_OK_onArrow() async { - await resolveTestUnit(''' -fff() => 123; -'''); - await assertHasAssistAt('=>', DartAssistKind.CONVERT_INTO_BLOCK_BODY, ''' -fff() { - return 123; -} -'''); - } - - test_convertToBlockBody_OK_onName() async { - await resolveTestUnit(''' -fff() => 123; -'''); - await assertHasAssistAt('fff()', DartAssistKind.CONVERT_INTO_BLOCK_BODY, ''' -fff() { - return 123; -} -'''); - } - - test_convertToBlockBody_OK_throw() async { - await resolveTestUnit(''' -class A { - mmm() => throw 'error'; -} -'''); - await assertHasAssistAt('mmm()', DartAssistKind.CONVERT_INTO_BLOCK_BODY, ''' -class A { - mmm() { - throw 'error'; - } -} -'''); - } - - test_convertToDoubleQuotedString_BAD_one_embeddedTarget() async { - await resolveTestUnit(''' -main() { - print('a"b"c'); -} -'''); - await assertNoAssistAt( - "'a", DartAssistKind.CONVERT_TO_DOUBLE_QUOTED_STRING); - } - - test_convertToDoubleQuotedString_BAD_one_enclosingTarget() async { - await resolveTestUnit(''' -main() { - print("abc"); -} -'''); - await assertNoAssistAt( - '"ab', DartAssistKind.CONVERT_TO_DOUBLE_QUOTED_STRING); - } - - test_convertToDoubleQuotedString_BAD_three_embeddedTarget() async { - await resolveTestUnit(""" -main() { - print('''a""\"c'''); -} -"""); - await assertNoAssistAt( - "'a", DartAssistKind.CONVERT_TO_DOUBLE_QUOTED_STRING); - } - - test_convertToDoubleQuotedString_BAD_three_enclosingTarget() async { - await resolveTestUnit(''' -main() { - print("""abc"""); -} -'''); - await assertNoAssistAt( - '"ab', DartAssistKind.CONVERT_TO_DOUBLE_QUOTED_STRING); - } - - test_convertToDoubleQuotedString_OK_one_interpolation() async { - await resolveTestUnit(r''' -main() { - var b = 'b'; - var c = 'c'; - print('a $b-${c} d'); -} -'''); - await assertHasAssistAt( - r"'a $b", DartAssistKind.CONVERT_TO_DOUBLE_QUOTED_STRING, r''' -main() { - var b = 'b'; - var c = 'c'; - print("a $b-${c} d"); -} -'''); - } - - test_convertToDoubleQuotedString_OK_one_raw() async { - await resolveTestUnit(''' -main() { - print(r'abc'); -} -'''); - await assertHasAssistAt( - "'ab", DartAssistKind.CONVERT_TO_DOUBLE_QUOTED_STRING, ''' -main() { - print(r"abc"); -} -'''); - } - - test_convertToDoubleQuotedString_OK_one_simple() async { - await resolveTestUnit(''' -main() { - print('abc'); -} -'''); - await assertHasAssistAt( - "'ab", DartAssistKind.CONVERT_TO_DOUBLE_QUOTED_STRING, ''' -main() { - print("abc"); -} -'''); - } - - test_convertToDoubleQuotedString_OK_three_interpolation() async { - await resolveTestUnit(r""" -main() { - var b = 'b'; - var c = 'c'; - print('''a $b-${c} d'''); -} -"""); - await assertHasAssistAt( - r"'a $b", DartAssistKind.CONVERT_TO_DOUBLE_QUOTED_STRING, r''' -main() { - var b = 'b'; - var c = 'c'; - print("""a $b-${c} d"""); -} -'''); - } - - test_convertToDoubleQuotedString_OK_three_raw() async { - await resolveTestUnit(""" -main() { - print(r'''abc'''); -} -"""); - await assertHasAssistAt( - "'ab", DartAssistKind.CONVERT_TO_DOUBLE_QUOTED_STRING, ''' -main() { - print(r"""abc"""); -} -'''); - } - - test_convertToDoubleQuotedString_OK_three_simple() async { - await resolveTestUnit(""" -main() { - print('''abc'''); -} -"""); - await assertHasAssistAt( - "'ab", DartAssistKind.CONVERT_TO_DOUBLE_QUOTED_STRING, ''' -main() { - print("""abc"""); -} -'''); - } - - test_convertToExpressionBody_BAD_already() async { - await resolveTestUnit(''' -fff() => 42; -'''); - await assertNoAssistAt( - 'fff()', DartAssistKind.CONVERT_INTO_EXPRESSION_BODY); - } - - test_convertToExpressionBody_BAD_inExpression() async { - await resolveTestUnit(''' -main() { - return 42; -} -'''); - await assertNoAssistAt('42;', DartAssistKind.CONVERT_INTO_EXPRESSION_BODY); - } - - test_convertToExpressionBody_BAD_moreThanOneStatement() async { - await resolveTestUnit(''' -fff() { - var v = 42; - return v; -} -'''); - await assertNoAssistAt( - 'fff()', DartAssistKind.CONVERT_INTO_EXPRESSION_BODY); - } - - test_convertToExpressionBody_BAD_noEnclosingFunction() async { - await resolveTestUnit(''' -var V = 42; -'''); - await assertNoAssistAt('V = ', DartAssistKind.CONVERT_INTO_EXPRESSION_BODY); - } - - test_convertToExpressionBody_BAD_noReturn() async { - await resolveTestUnit(''' -fff() { - var v = 42; -} -'''); - await assertNoAssistAt( - 'fff()', DartAssistKind.CONVERT_INTO_EXPRESSION_BODY); - } - - test_convertToExpressionBody_BAD_noReturnValue() async { - await resolveTestUnit(''' -fff() { - return; -} -'''); - await assertNoAssistAt( - 'fff()', DartAssistKind.CONVERT_INTO_EXPRESSION_BODY); - } - - test_convertToExpressionBody_OK_async() async { - await resolveTestUnit(''' -class A { - mmm() async { - return 42; - } -} -'''); - await assertHasAssistAt( - 'mmm', DartAssistKind.CONVERT_INTO_EXPRESSION_BODY, ''' -class A { - mmm() async => 42; -} -'''); - } - - test_convertToExpressionBody_OK_closure() async { - await resolveTestUnit(''' -setup(x) {} -main() { - setup(() { - return 42; - }); -} -'''); - await assertHasAssistAt( - 'return', DartAssistKind.CONVERT_INTO_EXPRESSION_BODY, ''' -setup(x) {} -main() { - setup(() => 42); -} -'''); - } - - test_convertToExpressionBody_OK_closure_voidExpression() async { - await resolveTestUnit(''' -setup(x) {} -main() { - setup((_) { - print('test'); - }); -} -'''); - await assertHasAssistAt( - '(_) {', DartAssistKind.CONVERT_INTO_EXPRESSION_BODY, ''' -setup(x) {} -main() { - setup((_) => print('test')); -} -'''); - } - - test_convertToExpressionBody_OK_constructor() async { - await resolveTestUnit(''' -class A { - factory A() { - return null; - } -} -'''); - await assertHasAssistAt( - 'A()', DartAssistKind.CONVERT_INTO_EXPRESSION_BODY, ''' -class A { - factory A() => null; -} -'''); - } - - test_convertToExpressionBody_OK_function_onBlock() async { - await resolveTestUnit(''' -fff() { - return 42; -} -'''); - await assertHasAssistAt( - '{', DartAssistKind.CONVERT_INTO_EXPRESSION_BODY, ''' -fff() => 42; -'''); - } - - test_convertToExpressionBody_OK_function_onName() async { - await resolveTestUnit(''' -fff() { - return 42; -} -'''); - await assertHasAssistAt( - 'ff()', DartAssistKind.CONVERT_INTO_EXPRESSION_BODY, ''' -fff() => 42; -'''); - } - - test_convertToExpressionBody_OK_method_onBlock() async { - await resolveTestUnit(''' -class A { - m() { // marker - return 42; - } -} -'''); - await assertHasAssistAt( - '{ // marker', DartAssistKind.CONVERT_INTO_EXPRESSION_BODY, ''' -class A { - m() => 42; -} -'''); - } - - test_convertToExpressionBody_OK_topFunction_onReturnStatement() async { - await resolveTestUnit(''' -fff() { - return 42; -} -'''); - await assertHasAssistAt( - 'return', DartAssistKind.CONVERT_INTO_EXPRESSION_BODY, ''' -fff() => 42; -'''); - } - - test_convertToFieldParameter_BAD_additionalUse() async { - await resolveTestUnit(''' -class A { - int aaa2; - int bbb2; - A(int aaa) : aaa2 = aaa, bbb2 = aaa; -} -'''); - await assertNoAssistAt('aaa)', DartAssistKind.CONVERT_TO_FIELD_PARAMETER); - } - - test_convertToFieldParameter_BAD_notPureAssignment() async { - await resolveTestUnit(''' -class A { - int aaa2; - A(int aaa) : aaa2 = aaa * 2; -} -'''); - await assertNoAssistAt('aaa)', DartAssistKind.CONVERT_TO_FIELD_PARAMETER); - } - - test_convertToFieldParameter_OK_firstInitializer() async { - await resolveTestUnit(''' -class A { - int aaa2; - int bbb2; - A(int aaa, int bbb) : aaa2 = aaa, bbb2 = bbb; -} -'''); - await assertHasAssistAt( - 'aaa, ', DartAssistKind.CONVERT_TO_FIELD_PARAMETER, ''' -class A { - int aaa2; - int bbb2; - A(this.aaa2, int bbb) : bbb2 = bbb; -} -'''); - } - - test_convertToFieldParameter_OK_onParameterName_inInitializer() async { - await resolveTestUnit(''' -class A { - int test2; - A(int test) : test2 = test { - } -} -'''); - await assertHasAssistAt( - 'test {', DartAssistKind.CONVERT_TO_FIELD_PARAMETER, ''' -class A { - int test2; - A(this.test2) { - } -} -'''); - } - - test_convertToFieldParameter_OK_onParameterName_inParameters() async { - await resolveTestUnit(''' -class A { - int test; - A(int test) : test = test { - } -} -'''); - await assertHasAssistAt( - 'test)', DartAssistKind.CONVERT_TO_FIELD_PARAMETER, ''' -class A { - int test; - A(this.test) { - } -} -'''); - } - - test_convertToFieldParameter_OK_secondInitializer() async { - await resolveTestUnit(''' -class A { - int aaa2; - int bbb2; - A(int aaa, int bbb) : aaa2 = aaa, bbb2 = bbb; -} -'''); - await assertHasAssistAt( - 'bbb)', DartAssistKind.CONVERT_TO_FIELD_PARAMETER, ''' -class A { - int aaa2; - int bbb2; - A(int aaa, this.bbb2) : aaa2 = aaa; -} -'''); - } - - test_convertToFinalField_BAD_hasSetter_inThisClass() async { - await resolveTestUnit(''' -class A { - int get foo => null; - void set foo(_) {} -} -'''); - await assertNoAssistAt('get foo', DartAssistKind.CONVERT_INTO_FINAL_FIELD); - } - - test_convertToFinalField_BAD_notExpressionBody() async { - await resolveTestUnit(''' -class A { - int get foo { - int v = 1 + 2; - return v + 3; - } -} -'''); - await assertNoAssistAt('get foo', DartAssistKind.CONVERT_INTO_FINAL_FIELD); - } - - test_convertToFinalField_BAD_notGetter() async { - await resolveTestUnit(''' -class A { - int foo() => 42; -} -'''); - await assertNoAssistAt('foo', DartAssistKind.CONVERT_INTO_FINAL_FIELD); - } - - test_convertToFinalField_OK_blockBody_onlyReturnStatement() async { - await resolveTestUnit(''' -class A { - int get foo { - return 1 + 2; - } -} -'''); - await assertHasAssistAt( - 'get foo', DartAssistKind.CONVERT_INTO_FINAL_FIELD, ''' -class A { - final int foo = 1 + 2; -} -'''); - } - - test_convertToFinalField_OK_hasOverride() async { - await resolveTestUnit(''' -const myAnnotation = const Object(); -class A { - @myAnnotation - int get foo => 42; -} -'''); - await assertHasAssistAt( - 'get foo', DartAssistKind.CONVERT_INTO_FINAL_FIELD, ''' -const myAnnotation = const Object(); -class A { - @myAnnotation - final int foo = 42; -} -'''); - } - - test_convertToFinalField_OK_hasSetter_inSuper() async { - await resolveTestUnit(''' -class A { - void set foo(_) {} -} -class B extends A { - int get foo => null; -} -'''); - await assertHasAssistAt( - 'get foo', DartAssistKind.CONVERT_INTO_FINAL_FIELD, ''' -class A { - void set foo(_) {} -} -class B extends A { - final int foo; -} -'''); - } - - test_convertToFinalField_OK_noReturnType() async { - await resolveTestUnit(''' -class A { - get foo => 42; -} -'''); - await assertHasAssistAt( - 'get foo', DartAssistKind.CONVERT_INTO_FINAL_FIELD, ''' -class A { - final foo = 42; -} -'''); - } - - test_convertToFinalField_OK_noReturnType_static() async { - await resolveTestUnit(''' -class A { - static get foo => 42; -} -'''); - await assertHasAssistAt( - 'get foo', DartAssistKind.CONVERT_INTO_FINAL_FIELD, ''' -class A { - static final foo = 42; -} -'''); - } - - test_convertToFinalField_OK_notNull() async { - await resolveTestUnit(''' -class A { - int get foo => 1 + 2; -} -'''); - await assertHasAssistAt( - 'get foo', DartAssistKind.CONVERT_INTO_FINAL_FIELD, ''' -class A { - final int foo = 1 + 2; -} -'''); - } - - test_convertToFinalField_OK_null() async { - await resolveTestUnit(''' -class A { - int get foo => null; -} -'''); - await assertHasAssistAt( - 'get foo', DartAssistKind.CONVERT_INTO_FINAL_FIELD, ''' -class A { - final int foo; -} -'''); - } - - test_convertToFinalField_OK_onName() async { - await resolveTestUnit(''' -class A { - int get foo => 42; -} -'''); - await assertHasAssistAt('foo', DartAssistKind.CONVERT_INTO_FINAL_FIELD, ''' -class A { - final int foo = 42; -} -'''); - } - - test_convertToFinalField_OK_onReturnType_parameterized() async { - await resolveTestUnit(''' -class A { - List<int> get foo => null; -} -'''); - await assertHasAssistAt( - 'nt> get', DartAssistKind.CONVERT_INTO_FINAL_FIELD, ''' -class A { - final List<int> foo; -} -'''); - } - - test_convertToFinalField_OK_onReturnType_simple() async { - await resolveTestUnit(''' -class A { - int get foo => 42; -} -'''); - await assertHasAssistAt( - 'int get', DartAssistKind.CONVERT_INTO_FINAL_FIELD, ''' -class A { - final int foo = 42; -} -'''); - } - - test_convertToForIndex_BAD_bodyNotBlock() async { - await resolveTestUnit(''' -main(List<String> items) { - for (String item in items) print(item); -} -'''); - await assertNoAssistAt( - 'for (String', DartAssistKind.CONVERT_INTO_FOR_INDEX); - } - - test_convertToForIndex_BAD_doesNotDeclareVariable() async { - await resolveTestUnit(''' -main(List<String> items) { - String item; - for (item in items) { - print(item); - } -} -'''); - await assertNoAssistAt('for (item', DartAssistKind.CONVERT_INTO_FOR_INDEX); - } - - test_convertToForIndex_BAD_iterableIsNotVariable() async { - await resolveTestUnit(''' -main() { - for (String item in ['a', 'b', 'c']) { - print(item); - } -} -'''); - await assertNoAssistAt( - 'for (String', DartAssistKind.CONVERT_INTO_FOR_INDEX); - } - - test_convertToForIndex_BAD_iterableNotList() async { - await resolveTestUnit(''' -main(Iterable<String> items) { - for (String item in items) { - print(item); - } -} -'''); - await assertNoAssistAt( - 'for (String', DartAssistKind.CONVERT_INTO_FOR_INDEX); - } - - test_convertToForIndex_BAD_usesIJK() async { - await resolveTestUnit(''' -main(List<String> items) { - for (String item in items) { - print(item); - int i, j, k; - } -} -'''); - await assertNoAssistAt( - 'for (String', DartAssistKind.CONVERT_INTO_FOR_INDEX); - } - - test_convertToForIndex_OK_onDeclaredIdentifier_name() async { - await resolveTestUnit(''' -main(List<String> items) { - for (String item in items) { - print(item); - } -} -'''); - await assertHasAssistAt( - 'item in', DartAssistKind.CONVERT_INTO_FOR_INDEX, ''' -main(List<String> items) { - for (int i = 0; i < items.length; i++) { - String item = items[i]; - print(item); - } -} -'''); - } - - test_convertToForIndex_OK_onDeclaredIdentifier_type() async { - await resolveTestUnit(''' -main(List<String> items) { - for (String item in items) { - print(item); - } -} -'''); - await assertHasAssistAt( - 'tring item', DartAssistKind.CONVERT_INTO_FOR_INDEX, ''' -main(List<String> items) { - for (int i = 0; i < items.length; i++) { - String item = items[i]; - print(item); - } -} -'''); - } - - test_convertToForIndex_OK_onFor() async { - await resolveTestUnit(''' -main(List<String> items) { - for (String item in items) { - print(item); - } -} -'''); - await assertHasAssistAt( - 'for (String', DartAssistKind.CONVERT_INTO_FOR_INDEX, ''' -main(List<String> items) { - for (int i = 0; i < items.length; i++) { - String item = items[i]; - print(item); - } -} -'''); - } - - test_convertToForIndex_OK_usesI() async { - await resolveTestUnit(''' -main(List<String> items) { - for (String item in items) { - int i = 0; - } -} -'''); - await assertHasAssistAt( - 'for (String', DartAssistKind.CONVERT_INTO_FOR_INDEX, ''' -main(List<String> items) { - for (int j = 0; j < items.length; j++) { - String item = items[j]; - int i = 0; - } -} -'''); - } - - test_convertToForIndex_OK_usesIJ() async { - await resolveTestUnit(''' -main(List<String> items) { - for (String item in items) { - print(item); - int i = 0, j = 1; - } -} -'''); - await assertHasAssistAt( - 'for (String', DartAssistKind.CONVERT_INTO_FOR_INDEX, ''' -main(List<String> items) { - for (int k = 0; k < items.length; k++) { - String item = items[k]; - print(item); - int i = 0, j = 1; - } -} -'''); - } - - test_convertToFunctionSyntax_BAD_functionTypeAlias_insideParameterList() async { - await resolveTestUnit(''' -typedef String F(int x, int y); -'''); - await assertNoAssistAt( - 'x,', DartAssistKind.CONVERT_INTO_GENERIC_FUNCTION_SYNTAX); - } - - test_convertToFunctionSyntax_BAD_functionTypeAlias_noParameterTypes() async { - await resolveTestUnit(''' -typedef String F(x); -'''); - await assertNoAssistAt( - 'def', DartAssistKind.CONVERT_INTO_GENERIC_FUNCTION_SYNTAX); - } - - test_convertToFunctionSyntax_BAD_functionTypedParameter_insideParameterList() async { - await resolveTestUnit(''' -g(String f(int x, int y)) {} -'''); - await assertNoAssistAt( - 'x,', DartAssistKind.CONVERT_INTO_GENERIC_FUNCTION_SYNTAX); - } - - test_convertToFunctionSyntax_BAD_functionTypedParameter_noParameterTypes() async { - await resolveTestUnit(''' -g(String f(x)) {} -'''); - await assertNoAssistAt( - 'f(', DartAssistKind.CONVERT_INTO_GENERIC_FUNCTION_SYNTAX); - } - - test_convertToFunctionSyntax_OK_functionTypeAlias_noReturnType_noTypeParameters() async { - await resolveTestUnit(''' -typedef String F(int x); -'''); - await assertHasAssistAt( - 'def', DartAssistKind.CONVERT_INTO_GENERIC_FUNCTION_SYNTAX, ''' -typedef F = String Function(int x); -'''); - } - - test_convertToFunctionSyntax_OK_functionTypeAlias_noReturnType_typeParameters() async { - await resolveTestUnit(''' -typedef F<P, R>(P x); -'''); - await assertHasAssistAt( - 'def', DartAssistKind.CONVERT_INTO_GENERIC_FUNCTION_SYNTAX, ''' -typedef F<P, R> = Function(P x); -'''); - } - - test_convertToFunctionSyntax_OK_functionTypeAlias_returnType_noTypeParameters() async { - await resolveTestUnit(''' -typedef String F(int x); -'''); - await assertHasAssistAt( - 'def', DartAssistKind.CONVERT_INTO_GENERIC_FUNCTION_SYNTAX, ''' -typedef F = String Function(int x); -'''); - } - - test_convertToFunctionSyntax_OK_functionTypeAlias_returnType_typeParameters() async { - await resolveTestUnit(''' -typedef R F<P, R>(P x); -'''); - await assertHasAssistAt( - 'def', DartAssistKind.CONVERT_INTO_GENERIC_FUNCTION_SYNTAX, ''' -typedef F<P, R> = R Function(P x); -'''); - } - - test_convertToFunctionSyntax_OK_functionTypedParameter_noReturnType_noTypeParameters() async { - await resolveTestUnit(''' -g(f(int x)) {} -'''); - await assertHasAssistAt( - 'f(', DartAssistKind.CONVERT_INTO_GENERIC_FUNCTION_SYNTAX, ''' -g(Function(int x) f) {} -'''); - } - - test_convertToFunctionSyntax_OK_functionTypedParameter_returnType() async { - await resolveTestUnit(''' -g(String f(int x)) {} -'''); - await assertHasAssistAt( - 'f(', DartAssistKind.CONVERT_INTO_GENERIC_FUNCTION_SYNTAX, ''' -g(String Function(int x) f) {} -'''); - } - - test_convertToGetter_BAD_noInitializer() async { - verifyNoTestUnitErrors = false; - await resolveTestUnit(''' -class A { - final int foo; -} -'''); - await assertNoAssistAt('foo', DartAssistKind.CONVERT_INTO_GETTER); - } - - test_convertToGetter_BAD_notFinal() async { - await resolveTestUnit(''' -class A { - int foo = 1; -} -'''); - await assertNoAssistAt('foo', DartAssistKind.CONVERT_INTO_GETTER); - } - - test_convertToGetter_BAD_notSingleField() async { - await resolveTestUnit(''' -class A { - final int foo = 1, bar = 2; -} -'''); - await assertNoAssistAt('foo', DartAssistKind.CONVERT_INTO_GETTER); - } - - test_convertToGetter_OK() async { - await resolveTestUnit(''' -const myAnnotation = const Object(); -class A { - @myAnnotation - final int foo = 1 + 2; -} -'''); - await assertHasAssistAt('foo =', DartAssistKind.CONVERT_INTO_GETTER, ''' -const myAnnotation = const Object(); -class A { - @myAnnotation - int get foo => 1 + 2; -} -'''); - } - - test_convertToGetter_OK_noType() async { - await resolveTestUnit(''' -class A { - final foo = 42; -} -'''); - await assertHasAssistAt('foo =', DartAssistKind.CONVERT_INTO_GETTER, ''' -class A { - get foo => 42; -} -'''); - } - - test_convertToIntLiteral() async { - await resolveTestUnit(''' -const double myDouble = 42.0; -'''); - await assertHasAssistAt('42.0', DartAssistKind.CONVERT_TO_INT_LITERAL, ''' -const double myDouble = 42; -'''); - } - - test_convertToIntLiteral_e() async { - await resolveTestUnit(''' -const double myDouble = 4.2e1; -'''); - await assertHasAssistAt('4.2e1', DartAssistKind.CONVERT_TO_INT_LITERAL, ''' -const double myDouble = 42; -'''); - } - - test_convertToIntLiteral_eBig() async { - await resolveTestUnit(''' -const double myDouble = 4.2e99999; -'''); - await assertNoAssistAt('4.2e99999', DartAssistKind.CONVERT_TO_INT_LITERAL); - } - - test_convertToIntLiteral_notDouble() async { - await resolveTestUnit(''' -const double myDouble = 42; -'''); - await assertNoAssistAt('42', DartAssistKind.CONVERT_TO_INT_LITERAL); - } - - test_convertToIsNot_BAD_is_alreadyIsNot() async { - await resolveTestUnit(''' -main(p) { - p is! String; -} -'''); - await assertNoAssistAt('is!', DartAssistKind.CONVERT_INTO_IS_NOT); - } - - test_convertToIsNot_BAD_is_noEnclosingParenthesis() async { - await resolveTestUnit(''' -main(p) { - p is String; -} -'''); - await assertNoAssistAt('is String', DartAssistKind.CONVERT_INTO_IS_NOT); - } - - test_convertToIsNot_BAD_is_noPrefix() async { - await resolveTestUnit(''' -main(p) { - (p is String); -} -'''); - await assertNoAssistAt('is String', DartAssistKind.CONVERT_INTO_IS_NOT); - } - - test_convertToIsNot_BAD_is_notIsExpression() async { - await resolveTestUnit(''' -main(p) { - 123 + 456; -} -'''); - await assertNoAssistAt('123 +', DartAssistKind.CONVERT_INTO_IS_NOT); - } - - test_convertToIsNot_BAD_is_notTheNotOperator() async { - verifyNoTestUnitErrors = false; - await resolveTestUnit(''' -main(p) { - ++(p is String); -} -'''); - await assertNoAssistAt('is String', DartAssistKind.CONVERT_INTO_IS_NOT); - } - - test_convertToIsNot_BAD_not_alreadyIsNot() async { - await resolveTestUnit(''' -main(p) { - !(p is! String); -} -'''); - await assertNoAssistAt('!(p', DartAssistKind.CONVERT_INTO_IS_NOT); - } - - test_convertToIsNot_BAD_not_noEnclosingParenthesis() async { - await resolveTestUnit(''' -main(p) { - !p; -} -'''); - await assertNoAssistAt('!p', DartAssistKind.CONVERT_INTO_IS_NOT); - } - - test_convertToIsNot_BAD_not_notIsExpression() async { - await resolveTestUnit(''' -main(p) { - !(p == null); -} -'''); - await assertNoAssistAt('!(p', DartAssistKind.CONVERT_INTO_IS_NOT); - } - - test_convertToIsNot_BAD_not_notTheNotOperator() async { - verifyNoTestUnitErrors = false; - await resolveTestUnit(''' -main(p) { - ++(p is String); -} -'''); - await assertNoAssistAt('++(', DartAssistKind.CONVERT_INTO_IS_NOT); - } - - test_convertToIsNot_OK_childOfIs_left() async { - await resolveTestUnit(''' -main(p) { - !(p is String); -} -'''); - await assertHasAssistAt('p is', DartAssistKind.CONVERT_INTO_IS_NOT, ''' -main(p) { - p is! String; -} -'''); - } - - test_convertToIsNot_OK_childOfIs_right() async { - await resolveTestUnit(''' -main(p) { - !(p is String); -} -'''); - await assertHasAssistAt('String)', DartAssistKind.CONVERT_INTO_IS_NOT, ''' -main(p) { - p is! String; -} -'''); - } - - test_convertToIsNot_OK_is() async { - await resolveTestUnit(''' -main(p) { - !(p is String); -} -'''); - await assertHasAssistAt('is String', DartAssistKind.CONVERT_INTO_IS_NOT, ''' -main(p) { - p is! String; -} -'''); - } - - test_convertToIsNot_OK_is_higherPrecedencePrefix() async { - await resolveTestUnit(''' -main(p) { - !!(p is String); -} -'''); - await assertHasAssistAt('is String', DartAssistKind.CONVERT_INTO_IS_NOT, ''' -main(p) { - !(p is! String); -} -'''); - } - - test_convertToIsNot_OK_is_not_higherPrecedencePrefix() async { - await resolveTestUnit(''' -main(p) { - !!(p is String); -} -'''); - await assertHasAssistAt('!(p', DartAssistKind.CONVERT_INTO_IS_NOT, ''' -main(p) { - !(p is! String); -} -'''); - } - - test_convertToIsNot_OK_not() async { - await resolveTestUnit(''' -main(p) { - !(p is String); -} -'''); - await assertHasAssistAt('!(p', DartAssistKind.CONVERT_INTO_IS_NOT, ''' -main(p) { - p is! String; -} -'''); - } - - test_convertToIsNot_OK_parentheses() async { - await resolveTestUnit(''' -main(p) { - !(p is String); -} -'''); - await assertHasAssistAt('(p is', DartAssistKind.CONVERT_INTO_IS_NOT, ''' -main(p) { - p is! String; -} -'''); - } - - test_convertToIsNotEmpty_BAD_noBang() async { - verifyNoTestUnitErrors = false; - await resolveTestUnit(''' -main(String str) { - ~str.isEmpty; -} -'''); - await assertNoAssistAt( - 'isEmpty;', DartAssistKind.CONVERT_INTO_IS_NOT_EMPTY); - } - - test_convertToIsNotEmpty_BAD_noIsNotEmpty() async { - await resolveTestUnit(''' -class A { - bool get isEmpty => false; -} -main(A a) { - !a.isEmpty; -} -'''); - await assertNoAssistAt( - 'isEmpty;', DartAssistKind.CONVERT_INTO_IS_NOT_EMPTY); - } - - test_convertToIsNotEmpty_BAD_notInPrefixExpression() async { - await resolveTestUnit(''' -main(String str) { - str.isEmpty; -} -'''); - await assertNoAssistAt( - 'isEmpty;', DartAssistKind.CONVERT_INTO_IS_NOT_EMPTY); - } - - test_convertToIsNotEmpty_BAD_notIsEmpty() async { - await resolveTestUnit(''' -main(int p) { - !p.isEven; -} -'''); - await assertNoAssistAt('isEven;', DartAssistKind.CONVERT_INTO_IS_NOT_EMPTY); - } - - test_convertToIsNotEmpty_OK_on_isEmpty() async { - await resolveTestUnit(''' -main(String str) { - !str.isEmpty; -} -'''); - await assertHasAssistAt( - 'isEmpty', DartAssistKind.CONVERT_INTO_IS_NOT_EMPTY, ''' -main(String str) { - str.isNotEmpty; -} -'''); - } - - test_convertToIsNotEmpty_OK_on_str() async { - await resolveTestUnit(''' -main(String str) { - !str.isEmpty; -} -'''); - await assertHasAssistAt( - 'str.', DartAssistKind.CONVERT_INTO_IS_NOT_EMPTY, ''' -main(String str) { - str.isNotEmpty; -} -'''); - } - - test_convertToIsNotEmpty_OK_propertyAccess() async { - await resolveTestUnit(''' -main(String str) { - !'text'.isEmpty; -} -'''); - await assertHasAssistAt( - 'isEmpty', DartAssistKind.CONVERT_INTO_IS_NOT_EMPTY, ''' -main(String str) { - 'text'.isNotEmpty; -} -'''); - } - - test_convertToNormalParameter_OK_dynamic() async { - await resolveTestUnit(''' -class A { - var test; - A(this.test) { - } -} -'''); - await assertHasAssistAt( - 'test)', DartAssistKind.CONVERT_TO_NORMAL_PARAMETER, ''' -class A { - var test; - A(test) : test = test { - } -} -'''); - } - - test_convertToNormalParameter_OK_firstInitializer() async { - await resolveTestUnit(''' -class A { - int test; - A(this.test) { - } -} -'''); - await assertHasAssistAt( - 'test)', DartAssistKind.CONVERT_TO_NORMAL_PARAMETER, ''' -class A { - int test; - A(int test) : test = test { - } -} -'''); - } - - test_convertToNormalParameter_OK_secondInitializer() async { - await resolveTestUnit(''' -class A { - double aaa; - int bbb; - A(this.bbb) : aaa = 1.0; -} -'''); - await assertHasAssistAt( - 'bbb)', DartAssistKind.CONVERT_TO_NORMAL_PARAMETER, ''' -class A { - double aaa; - int bbb; - A(int bbb) : aaa = 1.0, bbb = bbb; -} -'''); - } - - test_convertToSingleQuotedString_BAD_one_embeddedTarget() async { - await resolveTestUnit(''' -main() { - print("a'b'c"); -} -'''); - await assertNoAssistAt( - '"a', DartAssistKind.CONVERT_TO_SINGLE_QUOTED_STRING); - } - - test_convertToSingleQuotedString_BAD_one_enclosingTarget() async { - await resolveTestUnit(''' -main() { - print('abc'); -} -'''); - await assertNoAssistAt( - "'ab", DartAssistKind.CONVERT_TO_SINGLE_QUOTED_STRING); - } - - test_convertToSingleQuotedString_BAD_three_embeddedTarget() async { - await resolveTestUnit(''' -main() { - print("""a''\'bc"""); -} -'''); - await assertNoAssistAt( - '"a', DartAssistKind.CONVERT_TO_SINGLE_QUOTED_STRING); - } - - test_convertToSingleQuotedString_BAD_three_enclosingTarget() async { - await resolveTestUnit(""" -main() { - print('''abc'''); -} -"""); - await assertNoAssistAt( - "'ab", DartAssistKind.CONVERT_TO_SINGLE_QUOTED_STRING); - } - - test_convertToSingleQuotedString_OK_one_interpolation() async { - await resolveTestUnit(r''' -main() { - var b = 'b'; - var c = 'c'; - print("a $b-${c} d"); -} -'''); - await assertHasAssistAt( - r'"a $b', DartAssistKind.CONVERT_TO_SINGLE_QUOTED_STRING, r''' -main() { - var b = 'b'; - var c = 'c'; - print('a $b-${c} d'); -} -'''); - } - - test_convertToSingleQuotedString_OK_one_raw() async { - await resolveTestUnit(''' -main() { - print(r"abc"); -} -'''); - await assertHasAssistAt( - '"ab', DartAssistKind.CONVERT_TO_SINGLE_QUOTED_STRING, ''' -main() { - print(r'abc'); -} -'''); - } - - test_convertToSingleQuotedString_OK_one_simple() async { - await resolveTestUnit(''' -main() { - print("abc"); -} -'''); - await assertHasAssistAt( - '"ab', DartAssistKind.CONVERT_TO_SINGLE_QUOTED_STRING, ''' -main() { - print('abc'); -} -'''); - } - - test_convertToSingleQuotedString_OK_three_interpolation() async { - await resolveTestUnit(r''' -main() { - var b = 'b'; - var c = 'c'; - print("""a $b-${c} d"""); -} -'''); - await assertHasAssistAt( - r'"a $b', DartAssistKind.CONVERT_TO_SINGLE_QUOTED_STRING, r""" -main() { - var b = 'b'; - var c = 'c'; - print('''a $b-${c} d'''); -} -"""); - } - - test_convertToSingleQuotedString_OK_three_raw() async { - await resolveTestUnit(''' -main() { - print(r"""abc"""); -} -'''); - await assertHasAssistAt( - '"ab', DartAssistKind.CONVERT_TO_SINGLE_QUOTED_STRING, """ -main() { - print(r'''abc'''); -} -"""); - } - - test_convertToSingleQuotedString_OK_three_simple() async { - await resolveTestUnit(''' -main() { - print("""abc"""); -} -'''); - await assertHasAssistAt( - '"ab', DartAssistKind.CONVERT_TO_SINGLE_QUOTED_STRING, """ -main() { - print('''abc'''); -} -"""); - } - - test_encapsulateField_BAD_alreadyPrivate() async { - await resolveTestUnit(''' -class A { - int _test = 42; -} -main(A a) { - print(a._test); -} -'''); - await assertNoAssistAt('_test =', DartAssistKind.ENCAPSULATE_FIELD); - } - - test_encapsulateField_BAD_final() async { - await resolveTestUnit(''' -class A { - final int test = 42; -} -'''); - await assertNoAssistAt('test =', DartAssistKind.ENCAPSULATE_FIELD); - } - - test_encapsulateField_BAD_multipleFields() async { - await resolveTestUnit(''' -class A { - int aaa, bbb, ccc; -} -main(A a) { - print(a.bbb); -} -'''); - await assertNoAssistAt('bbb, ', DartAssistKind.ENCAPSULATE_FIELD); - } - - test_encapsulateField_BAD_notOnName() async { - await resolveTestUnit(''' -class A { - int test = 1 + 2 + 3; -} -'''); - await assertNoAssistAt('+ 2', DartAssistKind.ENCAPSULATE_FIELD); - } - - test_encapsulateField_BAD_parseError() async { - verifyNoTestUnitErrors = false; - await resolveTestUnit(''' -class A { - int; // marker -} -main(A a) { - print(a.test); -} -'''); - await assertNoAssistAt('; // marker', DartAssistKind.ENCAPSULATE_FIELD); - } - - test_encapsulateField_BAD_static() async { - await resolveTestUnit(''' -class A { - static int test = 42; -} -'''); - await assertNoAssistAt('test =', DartAssistKind.ENCAPSULATE_FIELD); - } - - test_encapsulateField_OK_documentation() async { - await resolveTestUnit(''' -class A { - /// AAA - /// BBB - int test; -} -'''); - await assertHasAssistAt('test;', DartAssistKind.ENCAPSULATE_FIELD, ''' -class A { - /// AAA - /// BBB - int _test; - - /// AAA - /// BBB - int get test => _test; - - /// AAA - /// BBB - set test(int test) { - _test = test; - } -} -'''); - } - - test_encapsulateField_OK_hasType() async { - await resolveTestUnit(''' -class A { - int test = 42; - A(this.test); -} -main(A a) { - print(a.test); -} -'''); - await assertHasAssistAt('test = 42', DartAssistKind.ENCAPSULATE_FIELD, ''' -class A { - int _test = 42; - - int get test => _test; - - set test(int test) { - _test = test; - } - A(this._test); -} -main(A a) { - print(a.test); -} -'''); - } - - test_encapsulateField_OK_noType() async { - await resolveTestUnit(''' -class A { - var test = 42; -} -main(A a) { - print(a.test); -} -'''); - await assertHasAssistAt('test = 42', DartAssistKind.ENCAPSULATE_FIELD, ''' -class A { - var _test = 42; - - get test => _test; - - set test(test) { - _test = test; - } -} -main(A a) { - print(a.test); -} -'''); - } - - test_exchangeBinaryExpressionArguments_BAD_extraLength() async { - await resolveTestUnit(''' -main() { - 111 + 222; -} -'''); - length = 3; - await assertNoAssistAt('+ 222', DartAssistKind.EXCHANGE_OPERANDS); - } - - test_exchangeBinaryExpressionArguments_BAD_onOperand() async { - await resolveTestUnit(''' -main() { - 111 + 222; -} -'''); - length = 3; - await assertNoAssistAt('11 +', DartAssistKind.EXCHANGE_OPERANDS); - } - - test_exchangeBinaryExpressionArguments_BAD_selectionWithBinary() async { - await resolveTestUnit(''' -main() { - 1 + 2 + 3; -} -'''); - length = '1 + 2 + 3'.length; - await assertNoAssistAt('1 + 2 + 3', DartAssistKind.EXCHANGE_OPERANDS); - } - - test_exchangeBinaryExpressionArguments_OK_compare() async { - const initialOperators = const ['<', '<=', '>', '>=']; - const resultOperators = const ['>', '>=', '<', '<=']; - for (int i = 0; i <= 0; i++) { - String initialOperator = initialOperators[i]; - String resultOperator = resultOperators[i]; - await resolveTestUnit(''' -bool main(int a, int b) { - return a $initialOperator b; -} -'''); - await assertHasAssistAt( - initialOperator, DartAssistKind.EXCHANGE_OPERANDS, ''' -bool main(int a, int b) { - return b $resultOperator a; -} -'''); - } - } - - test_exchangeBinaryExpressionArguments_OK_extended_mixOperator_1() async { - await resolveTestUnit(''' -main() { - 1 * 2 * 3 + 4; -} -'''); - await assertHasAssistAt('* 2', DartAssistKind.EXCHANGE_OPERANDS, ''' -main() { - 2 * 3 * 1 + 4; -} -'''); - } - - test_exchangeBinaryExpressionArguments_OK_extended_mixOperator_2() async { - await resolveTestUnit(''' -main() { - 1 + 2 - 3 + 4; -} -'''); - await assertHasAssistAt('+ 2', DartAssistKind.EXCHANGE_OPERANDS, ''' -main() { - 2 + 1 - 3 + 4; -} -'''); - } - - test_exchangeBinaryExpressionArguments_OK_extended_sameOperator_afterFirst() async { - await resolveTestUnit(''' -main() { - 1 + 2 + 3; -} -'''); - await assertHasAssistAt('+ 2', DartAssistKind.EXCHANGE_OPERANDS, ''' -main() { - 2 + 3 + 1; -} -'''); - } - - test_exchangeBinaryExpressionArguments_OK_extended_sameOperator_afterSecond() async { - await resolveTestUnit(''' -main() { - 1 + 2 + 3; -} -'''); - await assertHasAssistAt('+ 3', DartAssistKind.EXCHANGE_OPERANDS, ''' -main() { - 3 + 1 + 2; -} -'''); - } - - test_exchangeBinaryExpressionArguments_OK_simple_afterOperator() async { - await resolveTestUnit(''' -main() { - 1 + 2; -} -'''); - await assertHasAssistAt(' 2', DartAssistKind.EXCHANGE_OPERANDS, ''' -main() { - 2 + 1; -} -'''); - } - - test_exchangeBinaryExpressionArguments_OK_simple_beforeOperator() async { - await resolveTestUnit(''' -main() { - 1 + 2; -} -'''); - await assertHasAssistAt('+ 2', DartAssistKind.EXCHANGE_OPERANDS, ''' -main() { - 2 + 1; -} -'''); - } - - test_exchangeBinaryExpressionArguments_OK_simple_fullSelection() async { - await resolveTestUnit(''' -main() { - 1 + 2; -} -'''); - length = '1 + 2'.length; - await assertHasAssistAt('1 + 2', DartAssistKind.EXCHANGE_OPERANDS, ''' -main() { - 2 + 1; -} -'''); - } - - test_exchangeBinaryExpressionArguments_OK_simple_withLength() async { - await resolveTestUnit(''' -main() { - 1 + 2; -} -'''); - length = 2; - await assertHasAssistAt('+ 2', DartAssistKind.EXCHANGE_OPERANDS, ''' -main() { - 2 + 1; -} -'''); - } - - test_flutterConvertToChildren_BAD_childUnresolved() async { - addFlutterPackage(); - verifyNoTestUnitErrors = false; - await resolveTestUnit(''' -import 'package:flutter/material.dart'; -build() { - return new Row( - /*caret*/child: new Container() - ); -} -'''); - _setCaretLocation(); - await assertNoAssist(DartAssistKind.FLUTTER_CONVERT_TO_CHILDREN); - } - - test_flutterConvertToChildren_BAD_notOnChild() async { - addFlutterPackage(); - await resolveTestUnit(''' -import 'package:flutter/material.dart'; -build() { - return new Scaffold( - body: /*caret*/new Center( - child: new Container(), - ), - ); -} -'''); - _setCaretLocation(); - await assertNoAssist(DartAssistKind.FLUTTER_CONVERT_TO_CHILDREN); - } - - test_flutterConvertToChildren_OK_multiLine() async { - addFlutterPackage(); - await resolveTestUnit(''' -import 'package:flutter/material.dart'; -build() { - return new Scaffold( -// start - body: new Center( - /*caret*/child: new Container( - width: 200.0, - height: 300.0, - ), - key: null, - ), -// end - ); -} -'''); - _setCaretLocation(); - await assertHasAssist(DartAssistKind.FLUTTER_CONVERT_TO_CHILDREN, ''' -import 'package:flutter/material.dart'; -build() { - return new Scaffold( -// start - body: new Center( - /*caret*/children: <Widget>[ - new Container( - width: 200.0, - height: 300.0, - ), - ], - key: null, - ), -// end - ); -} -'''); - } - - test_flutterConvertToChildren_OK_newlineChild() async { - // This case could occur with deeply nested constructors, common in Flutter. - addFlutterPackage(); - await resolveTestUnit(''' -import 'package:flutter/material.dart'; -build() { - return new Scaffold( -// start - body: new Center( - /*caret*/child: - new Container( - width: 200.0, - height: 300.0, - ), - key: null, - ), -// end - ); -} -'''); - _setCaretLocation(); - await assertHasAssist(DartAssistKind.FLUTTER_CONVERT_TO_CHILDREN, ''' -import 'package:flutter/material.dart'; -build() { - return new Scaffold( -// start - body: new Center( - /*caret*/children: <Widget>[ - new Container( - width: 200.0, - height: 300.0, - ), - ], - key: null, - ), -// end - ); -} -'''); - } - - test_flutterConvertToChildren_OK_singleLine() async { - addFlutterPackage(); - await resolveTestUnit(''' -import 'package:flutter/material.dart'; -build() { - return new Scaffold( -// start - body: new Center( - /*caret*/child: new GestureDetector(), - key: null, - ), -// end - ); -} -'''); - _setCaretLocation(); - await assertHasAssist(DartAssistKind.FLUTTER_CONVERT_TO_CHILDREN, ''' -import 'package:flutter/material.dart'; -build() { - return new Scaffold( -// start - body: new Center( - /*caret*/children: <Widget>[new GestureDetector()], - key: null, - ), -// end - ); -} -'''); - } - - test_flutterConvertToStatefulWidget_BAD_notClass() async { - addFlutterPackage(); - await resolveTestUnit(''' -import 'package:flutter/material.dart'; -/*caret*/main() {} -'''); - _setCaretLocation(); - assertNoAssist(DartAssistKind.FLUTTER_CONVERT_TO_STATEFUL_WIDGET); - } - - test_flutterConvertToStatefulWidget_BAD_notStatelessWidget() async { - addFlutterPackage(); - await resolveTestUnit(''' -import 'package:flutter/material.dart'; -class /*caret*/MyWidget extends Text { - MyWidget() : super(''); -} -'''); - _setCaretLocation(); - assertNoAssist(DartAssistKind.FLUTTER_CONVERT_TO_STATEFUL_WIDGET); - } - - test_flutterConvertToStatefulWidget_BAD_notWidget() async { - addFlutterPackage(); - await resolveTestUnit(''' -import 'package:flutter/material.dart'; -class /*caret*/MyWidget {} -'''); - _setCaretLocation(); - assertNoAssist(DartAssistKind.FLUTTER_CONVERT_TO_STATEFUL_WIDGET); - } - - test_flutterConvertToStatefulWidget_OK() async { - addFlutterPackage(); - await resolveTestUnit(r''' -import 'package:flutter/material.dart'; - -class /*caret*/MyWidget extends StatelessWidget { - final String aaa; - final String bbb; - - const MyWidget(this.aaa, this.bbb); - - @override - Widget build(BuildContext context) { - return new Row( - children: [ - new Text(aaa), - new Text(bbb), - new Text('$aaa'), - new Text('${bbb}'), - ], - ); - } -} -'''); - _setCaretLocation(); - await assertHasAssist( - DartAssistKind.FLUTTER_CONVERT_TO_STATEFUL_WIDGET, r''' -import 'package:flutter/material.dart'; - -class /*caret*/MyWidget extends StatefulWidget { - final String aaa; - final String bbb; - - const MyWidget(this.aaa, this.bbb); - - @override - MyWidgetState createState() { - return new MyWidgetState(); - } -} - -class MyWidgetState extends State<MyWidget> { - @override - Widget build(BuildContext context) { - return new Row( - children: [ - new Text(widget.aaa), - new Text(widget.bbb), - new Text('${widget.aaa}'), - new Text('${widget.bbb}'), - ], - ); - } -} -'''); - } - - test_flutterConvertToStatefulWidget_OK_empty() async { - addFlutterPackage(); - await resolveTestUnit(r''' -import 'package:flutter/material.dart'; - -class /*caret*/MyWidget extends StatelessWidget { - @override - Widget build(BuildContext context) { - return new Container(); - } -} -'''); - _setCaretLocation(); - await assertHasAssist( - DartAssistKind.FLUTTER_CONVERT_TO_STATEFUL_WIDGET, r''' -import 'package:flutter/material.dart'; - -class /*caret*/MyWidget extends StatefulWidget { - @override - MyWidgetState createState() { - return new MyWidgetState(); - } -} - -class MyWidgetState extends State<MyWidget> { - @override - Widget build(BuildContext context) { - return new Container(); - } -} -'''); - } - - test_flutterConvertToStatefulWidget_OK_fields() async { - addFlutterPackage(); - await resolveTestUnit(r''' -import 'package:flutter/material.dart'; - -class /*caret*/MyWidget extends StatelessWidget { - static String staticField1; - final String instanceField1; - final String instanceField2; - String instanceField3; - static String staticField2; - String instanceField4; - String instanceField5; - static String staticField3; - - MyWidget(this.instanceField1) : instanceField2 = '' { - instanceField3 = ''; - } - - @override - Widget build(BuildContext context) { - instanceField4 = instanceField1; - return new Row( - children: [ - new Text(instanceField1), - new Text(instanceField2), - new Text(instanceField3), - new Text(instanceField4), - new Text(instanceField5), - new Text(staticField1), - new Text(staticField2), - new Text(staticField3), - ], - ); - } -} -'''); - _setCaretLocation(); - await assertHasAssist( - DartAssistKind.FLUTTER_CONVERT_TO_STATEFUL_WIDGET, r''' -import 'package:flutter/material.dart'; - -class /*caret*/MyWidget extends StatefulWidget { - static String staticField1; - final String instanceField1; - final String instanceField2; - String instanceField3; - static String staticField2; - static String staticField3; - - MyWidget(this.instanceField1) : instanceField2 = '' { - instanceField3 = ''; - } - - @override - MyWidgetState createState() { - return new MyWidgetState(); - } -} - -class MyWidgetState extends State<MyWidget> { - String instanceField4; - - String instanceField5; - - @override - Widget build(BuildContext context) { - instanceField4 = widget.instanceField1; - return new Row( - children: [ - new Text(widget.instanceField1), - new Text(widget.instanceField2), - new Text(widget.instanceField3), - new Text(instanceField4), - new Text(instanceField5), - new Text(MyWidget.staticField1), - new Text(MyWidget.staticField2), - new Text(MyWidget.staticField3), - ], - ); - } -} -'''); - } - - test_flutterConvertToStatefulWidget_OK_getters() async { - addFlutterPackage(); - await resolveTestUnit(r''' -import 'package:flutter/material.dart'; - -class /*caret*/MyWidget extends StatelessWidget { - @override - Widget build(BuildContext context) { - return new Row( - children: [ - new Text(staticGetter1), - new Text(staticGetter2), - new Text(instanceGetter1), - new Text(instanceGetter2), - ], - ); - } - - static String get staticGetter1 => ''; - - String get instanceGetter1 => ''; - - static String get staticGetter2 => ''; - - String get instanceGetter2 => ''; -} -'''); - _setCaretLocation(); - await assertHasAssist( - DartAssistKind.FLUTTER_CONVERT_TO_STATEFUL_WIDGET, r''' -import 'package:flutter/material.dart'; - -class /*caret*/MyWidget extends StatefulWidget { - @override - MyWidgetState createState() { - return new MyWidgetState(); - } - - static String get staticGetter1 => ''; - - static String get staticGetter2 => ''; -} - -class MyWidgetState extends State<MyWidget> { - @override - Widget build(BuildContext context) { - return new Row( - children: [ - new Text(MyWidget.staticGetter1), - new Text(MyWidget.staticGetter2), - new Text(instanceGetter1), - new Text(instanceGetter2), - ], - ); - } - - String get instanceGetter1 => ''; - - String get instanceGetter2 => ''; -} -'''); - } - - test_flutterConvertToStatefulWidget_OK_methods() async { - addFlutterPackage(); - await resolveTestUnit(r''' -import 'package:flutter/material.dart'; - -class /*caret*/MyWidget extends StatelessWidget { - static String staticField; - final String instanceField1; - String instanceField2; - - MyWidget(this.instanceField1); - - @override - Widget build(BuildContext context) { - return new Row( - children: [ - new Text(instanceField1), - new Text(instanceField2), - new Text(staticField), - ], - ); - } - - void instanceMethod1() { - instanceMethod1(); - instanceMethod2(); - staticMethod1(); - } - - static void staticMethod1() { - print('static 1'); - } - - void instanceMethod2() { - print('instance 2'); - } - - static void staticMethod2() { - print('static 2'); - } -} -'''); - _setCaretLocation(); - await assertHasAssist( - DartAssistKind.FLUTTER_CONVERT_TO_STATEFUL_WIDGET, r''' -import 'package:flutter/material.dart'; - -class /*caret*/MyWidget extends StatefulWidget { - static String staticField; - final String instanceField1; - - MyWidget(this.instanceField1); - - @override - MyWidgetState createState() { - return new MyWidgetState(); - } - - static void staticMethod1() { - print('static 1'); - } - - static void staticMethod2() { - print('static 2'); - } -} - -class MyWidgetState extends State<MyWidget> { - String instanceField2; - - @override - Widget build(BuildContext context) { - return new Row( - children: [ - new Text(widget.instanceField1), - new Text(instanceField2), - new Text(MyWidget.staticField), - ], - ); - } - - void instanceMethod1() { - instanceMethod1(); - instanceMethod2(); - MyWidget.staticMethod1(); - } - - void instanceMethod2() { - print('instance 2'); - } -} -'''); - } - - test_flutterConvertToStatefulWidget_OK_tail() async { - addFlutterPackage(); - await resolveTestUnit(r''' -import 'package:flutter/material.dart'; - -class /*caret*/MyWidget extends StatelessWidget { - @override - Widget build(BuildContext context) { - return new Container(); - } -} -'''); - _setCaretLocation(); - await assertHasAssist( - DartAssistKind.FLUTTER_CONVERT_TO_STATEFUL_WIDGET, r''' -import 'package:flutter/material.dart'; - -class /*caret*/MyWidget extends StatefulWidget { - @override - MyWidgetState createState() { - return new MyWidgetState(); - } -} - -class MyWidgetState extends State<MyWidget> { - @override - Widget build(BuildContext context) { - return new Container(); - } -} -'''); - } - - test_flutterMoveWidgetDown_BAD_last() async { - addFlutterPackage(); - await resolveTestUnit(''' -import 'package:flutter/material.dart'; -main() { - new Column( - children: <Widget>[ - new Text('aaa'), - new Text('bbb'), - /*caret*/new Text('ccc'), - ], - ); -} -'''); - _setCaretLocation(); - await assertNoAssist(DartAssistKind.FLUTTER_MOVE_DOWN); - } - - test_flutterMoveWidgetDown_BAD_notInList() async { - addFlutterPackage(); - await resolveTestUnit(''' -import 'package:flutter/material.dart'; -main() { - new Center( - child: /*caret*/new Text('aaa'), - ); -} -'''); - _setCaretLocation(); - await assertNoAssist(DartAssistKind.FLUTTER_MOVE_DOWN); - } - - test_flutterMoveWidgetDown_OK() async { - addFlutterPackage(); - await resolveTestUnit(''' -import 'package:flutter/material.dart'; -main() { - new Column( - children: <Widget>[ - new Text('aaa'), - /*caret*/new Text('bbbbbb'), - new Text('ccccccccc'), - ], - ); -} -'''); - _setCaretLocation(); - await assertHasAssist(DartAssistKind.FLUTTER_MOVE_DOWN, ''' -import 'package:flutter/material.dart'; -main() { - new Column( - children: <Widget>[ - new Text('aaa'), - /*caret*/new Text('ccccccccc'), - new Text('bbbbbb'), - ], - ); -} -'''); - _assertExitPosition(before: "new Text('bbbbbb')"); - } - - test_flutterMoveWidgetUp_BAD_first() async { - addFlutterPackage(); - await resolveTestUnit(''' -import 'package:flutter/material.dart'; -main() { - new Column( - children: <Widget>[ - /*caret*/new Text('aaa'), - new Text('bbb'), - new Text('ccc'), - ], - ); -} -'''); - _setCaretLocation(); - await assertNoAssist(DartAssistKind.FLUTTER_MOVE_UP); - } - - test_flutterMoveWidgetUp_BAD_notInList() async { - addFlutterPackage(); - await resolveTestUnit(''' -import 'package:flutter/material.dart'; -main() { - new Center( - child: /*caret*/new Text('aaa'), - ); -} -'''); - _setCaretLocation(); - await assertNoAssist(DartAssistKind.FLUTTER_MOVE_UP); - } - - test_flutterMoveWidgetUp_OK() async { - addFlutterPackage(); - await resolveTestUnit(''' -import 'package:flutter/material.dart'; -main() { - new Column( - children: <Widget>[ - new Text('aaa'), - /*caret*/new Text('bbbbbb'), - new Text('ccccccccc'), - ], - ); -} -'''); - _setCaretLocation(); - await assertHasAssist(DartAssistKind.FLUTTER_MOVE_UP, ''' -import 'package:flutter/material.dart'; -main() { - new Column( - children: <Widget>[ - new Text('bbbbbb'), - /*caret*/new Text('aaa'), - new Text('ccccccccc'), - ], - ); -} -'''); - _assertExitPosition(before: "new Text('bbbbbb')"); - } - - test_flutterRemoveWidget_BAD_childrenMultipleIntoChild() async { - addFlutterPackage(); - await resolveTestUnit(''' -import 'package:flutter/material.dart'; -main() { - new Center( - child: new /*caret*/Row( - children: [ - new Text('aaa'), - new Text('bbb'), - ], - ), - ); -} -'''); - _setCaretLocation(); - await assertNoAssist(DartAssistKind.FLUTTER_REMOVE_WIDGET); - } - - test_flutterRemoveWidget_OK_childIntoChild_multiLine() async { - addFlutterPackage(); - await resolveTestUnit(''' -import 'package:flutter/material.dart'; -main() { - new Column( - children: <Widget>[ - new Center( - child: new /*caret*/Padding( - padding: const EdgeInsets.all(8.0), - child: new Center( - heightFactor: 0.5, - child: new Text('foo'), - ), - ), - ), - ], - ); -} -'''); - _setCaretLocation(); - await assertHasAssist(DartAssistKind.FLUTTER_REMOVE_WIDGET, ''' -import 'package:flutter/material.dart'; -main() { - new Column( - children: <Widget>[ - new Center( - child: new Center( - heightFactor: 0.5, - child: new Text('foo'), - ), - ), - ], - ); -} -'''); - } - - test_flutterRemoveWidget_OK_childIntoChild_singleLine() async { - addFlutterPackage(); - await resolveTestUnit(''' -import 'package:flutter/material.dart'; -main() { - new Padding( - padding: const EdgeInsets.all(8.0), - child: new /*caret*/Center( - heightFactor: 0.5, - child: new Text('foo'), - ), - ); -} -'''); - _setCaretLocation(); - await assertHasAssist(DartAssistKind.FLUTTER_REMOVE_WIDGET, ''' -import 'package:flutter/material.dart'; -main() { - new Padding( - padding: const EdgeInsets.all(8.0), - child: new Text('foo'), - ); -} -'''); - } - - test_flutterRemoveWidget_OK_childIntoChildren() async { - addFlutterPackage(); - await resolveTestUnit(''' -import 'package:flutter/material.dart'; -main() { - new Column( - children: <Widget>[ - new Text('foo'), - new /*caret*/Center( - heightFactor: 0.5, - child: new Padding( - padding: const EdgeInsets.all(8.0), - child: new Text('bar'), - ), - ), - new Text('baz'), - ], - ); -} -'''); - _setCaretLocation(); - await assertHasAssist(DartAssistKind.FLUTTER_REMOVE_WIDGET, ''' -import 'package:flutter/material.dart'; -main() { - new Column( - children: <Widget>[ - new Text('foo'), - new Padding( - padding: const EdgeInsets.all(8.0), - child: new Text('bar'), - ), - new Text('baz'), - ], - ); -} -'''); - } - - test_flutterRemoveWidget_OK_childrenOneIntoChild() async { - addFlutterPackage(); - await resolveTestUnit(''' -import 'package:flutter/material.dart'; -main() { - new Center( - child: /*caret*/new Column( - children: [ - new Text('foo'), - ], - ), - ); -} -'''); - _setCaretLocation(); - await assertHasAssist(DartAssistKind.FLUTTER_REMOVE_WIDGET, ''' -import 'package:flutter/material.dart'; -main() { - new Center( - child: /*caret*/new Text('foo'), - ); -} -'''); - } - - test_flutterRemoveWidget_OK_childrenOneIntoReturn() async { - addFlutterPackage(); - await resolveTestUnit(''' -import 'package:flutter/material.dart'; -main() { - return /*caret*/new Column( - children: [ - new Text('foo'), - ], - ); -} -'''); - _setCaretLocation(); - await assertHasAssist(DartAssistKind.FLUTTER_REMOVE_WIDGET, ''' -import 'package:flutter/material.dart'; -main() { - return /*caret*/new Text('foo'); -} -'''); - } - - test_flutterRemoveWidget_OK_intoChildren() async { - addFlutterPackage(); - await resolveTestUnit(''' -import 'package:flutter/material.dart'; -main() { - new Column( - children: <Widget>[ - new Text('aaa'), - new /*caret*/Column( - children: [ - new Row( - children: [ - new Text('bbb'), - new Text('ccc'), - ], - ), - new Row( - children: [ - new Text('ddd'), - new Text('eee'), - ], - ), - ], - ), - new Text('fff'), - ], - ); -} -'''); - _setCaretLocation(); - await assertHasAssist(DartAssistKind.FLUTTER_REMOVE_WIDGET, ''' -import 'package:flutter/material.dart'; -main() { - new Column( - children: <Widget>[ - new Text('aaa'), - new Row( - children: [ - new Text('bbb'), - new Text('ccc'), - ], - ), - new Row( - children: [ - new Text('ddd'), - new Text('eee'), - ], - ), - new Text('fff'), - ], - ); -} -'''); - } - - test_flutterSwapWithChild_OK() async { - addFlutterPackage(); - await resolveTestUnit(''' -import 'package:flutter/material.dart'; -build() { - return new Scaffold( -// start - body: new /*caret*/GestureDetector( - onTap: () => startResize(), - child: new Center( - child: new Container( - width: 200.0, - height: 300.0, - ), - key: null, - ), - ), -// end - ); -} -startResize() {} -'''); - _setCaretLocation(); - await assertHasAssist(DartAssistKind.FLUTTER_SWAP_WITH_CHILD, ''' -import 'package:flutter/material.dart'; -build() { - return new Scaffold( -// start - body: new Center( - key: null, - child: new /*caret*/GestureDetector( - onTap: () => startResize(), - child: new Container( - width: 200.0, - height: 300.0, - ), - ), - ), -// end - ); -} -startResize() {} -'''); - } - - test_flutterSwapWithChild_OK_notFormatted() async { - addFlutterPackage(); - await resolveTestUnit(''' -import 'package:flutter/material.dart'; - -class Foo extends StatefulWidget { - @override - _State createState() => new _State(); -} - -class _State extends State<Foo> { - @override - Widget build(BuildContext context) { - return new /*caret*/Expanded( - flex: 2, - child: new GestureDetector( - child: new Text( - 'foo', - ), onTap: () { - print(42); - }, - ), - ); - } -}'''); - _setCaretLocation(); - await assertHasAssist(DartAssistKind.FLUTTER_SWAP_WITH_CHILD, ''' -import 'package:flutter/material.dart'; - -class Foo extends StatefulWidget { - @override - _State createState() => new _State(); -} - -class _State extends State<Foo> { - @override - Widget build(BuildContext context) { - return new GestureDetector( - onTap: () { - print(42); - }, - child: new /*caret*/Expanded( - flex: 2, - child: new Text( - 'foo', - ), - ), - ); - } -}'''); - } - - test_flutterSwapWithParent_OK() async { - addFlutterPackage(); - await resolveTestUnit(''' -import 'package:flutter/material.dart'; -build() { - return new Scaffold( -// start - body: new Center( - child: new /*caret*/GestureDetector( - onTap: () => startResize(), - child: new Container( - width: 200.0, - height: 300.0, - ), - ), - key: null, - ), -// end - ); -} -startResize() {} -'''); - _setCaretLocation(); - await assertHasAssist(DartAssistKind.FLUTTER_SWAP_WITH_PARENT, ''' -import 'package:flutter/material.dart'; -build() { - return new Scaffold( -// start - body: new /*caret*/GestureDetector( - onTap: () => startResize(), - child: new Center( - key: null, - child: new Container( - width: 200.0, - height: 300.0, - ), - ), - ), -// end - ); -} -startResize() {} -'''); - } - - test_flutterSwapWithParent_OK_notFormatted() async { - addFlutterPackage(); - await resolveTestUnit(''' -import 'package:flutter/material.dart'; - -class Foo extends StatefulWidget { - @override - _State createState() => new _State(); -} - -class _State extends State<Foo> { - @override - Widget build(BuildContext context) { - return new GestureDetector( - child: new /*caret*/Expanded( - child: new Text( - 'foo', - ), - flex: 2, - ), onTap: () { - print(42); - }, - ); - } -}'''); - _setCaretLocation(); - await assertHasAssist(DartAssistKind.FLUTTER_SWAP_WITH_PARENT, ''' -import 'package:flutter/material.dart'; - -class Foo extends StatefulWidget { - @override - _State createState() => new _State(); -} - -class _State extends State<Foo> { - @override - Widget build(BuildContext context) { - return new /*caret*/Expanded( - flex: 2, - child: new GestureDetector( - onTap: () { - print(42); - }, - child: new Text( - 'foo', - ), - ), - ); - } -}'''); - } - - test_flutterSwapWithParent_OK_outerIsInChildren() async { - addFlutterPackage(); - await resolveTestUnit(''' -import 'package:flutter/material.dart'; -main() { - new Column( - children: [ - new Column( - children: [ - new Padding( - padding: new EdgeInsets.all(16.0), - child: new /*caret*/Center( - child: new Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: <Widget>[], - ), - ), - ), - ], - ), - ], - ); -} -'''); - _setCaretLocation(); - await assertHasAssist(DartAssistKind.FLUTTER_SWAP_WITH_PARENT, ''' -import 'package:flutter/material.dart'; -main() { - new Column( - children: [ - new Column( - children: [ - new /*caret*/Center( - child: new Padding( - padding: new EdgeInsets.all(16.0), - child: new Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: <Widget>[], - ), - ), - ), - ], - ), - ], - ); -} -'''); - } - - test_flutterWrapCenter_BAD_onCenter() async { - addFlutterPackage(); - await resolveTestUnit(''' -import 'package:flutter/widgets.dart'; -class FakeFlutter { - main() { - return /*caret*/new Center(); - } -} -'''); - _setCaretLocation(); - await assertNoAssist(DartAssistKind.FLUTTER_WRAP_CENTER); - } - - test_flutterWrapCenter_OK() async { - addFlutterPackage(); - await resolveTestUnit(''' -import 'package:flutter/widgets.dart'; -class FakeFlutter { - main() { - return /*caret*/new Container(); - } -} -'''); - _setCaretLocation(); - if (omitNew) { - await assertHasAssist(DartAssistKind.FLUTTER_WRAP_CENTER, ''' -import 'package:flutter/widgets.dart'; -class FakeFlutter { - main() { - return /*caret*/Center(child: new Container()); - } -} -'''); - } else { - await assertHasAssist(DartAssistKind.FLUTTER_WRAP_CENTER, ''' -import 'package:flutter/widgets.dart'; -class FakeFlutter { - main() { - return /*caret*/new Center(child: new Container()); - } -} -'''); - } - } - - test_flutterWrapCenter_OK_implicitNew() async { - configurePreviewDart2(); - addFlutterPackage(); - await resolveTestUnit(''' -import 'package:flutter/widgets.dart'; -class FakeFlutter { - main() { - return /*caret*/Container(); - } -} -'''); - _setCaretLocation(); - await assertHasAssist(DartAssistKind.FLUTTER_WRAP_CENTER, ''' -import 'package:flutter/widgets.dart'; -class FakeFlutter { - main() { - return /*caret*/Center(child: Container()); - } -} -'''); - } - - test_flutterWrapCenter_OK_namedConstructor() async { - addFlutterPackage(); - await resolveTestUnit(''' -import 'package:flutter/widgets.dart'; - -class MyWidget extends StatelessWidget { - MyWidget.named(); - - Widget build(BuildContext context) => null; -} - -main() { - return MyWidget./*caret*/named(); -} -'''); - _setCaretLocation(); - if (omitNew) { - await assertHasAssist(DartAssistKind.FLUTTER_WRAP_CENTER, ''' -import 'package:flutter/widgets.dart'; - -class MyWidget extends StatelessWidget { - MyWidget.named(); - - Widget build(BuildContext context) => null; -} - -main() { - return Center(child: MyWidget./*caret*/named()); -} -'''); - } else { - await assertHasAssist(DartAssistKind.FLUTTER_WRAP_CENTER, ''' -import 'package:flutter/widgets.dart'; - -class MyWidget extends StatelessWidget { - MyWidget.named(); - - Widget build(BuildContext context) => null; -} - -main() { - return new Center(child: MyWidget./*caret*/named()); -} -'''); - } - } - - test_flutterWrapColumn_OK_coveredByWidget() async { - addFlutterPackage(); - await resolveTestUnit(''' -import 'package:flutter/widgets.dart'; - -class FakeFlutter { - main() { - return new Container( - child: new /*caret*/Text('aaa'), - ); - } -} -'''); - _setCaretLocation(); - if (omitNew) { - await assertHasAssist(DartAssistKind.FLUTTER_WRAP_COLUMN, ''' -import 'package:flutter/widgets.dart'; - -class FakeFlutter { - main() { - return new Container( - child: Column( - children: <Widget>[ - new /*caret*/Text('aaa'), - ], - ), - ); - } -} -'''); - } else { - await assertHasAssist(DartAssistKind.FLUTTER_WRAP_COLUMN, ''' -import 'package:flutter/widgets.dart'; - -class FakeFlutter { - main() { - return new Container( - child: new Column( - children: <Widget>[ - new /*caret*/Text('aaa'), - ], - ), - ); - } -} -'''); - } - } - - test_flutterWrapColumn_OK_coversWidgets() async { - addFlutterPackage(); - await resolveTestUnit(''' -import 'package:flutter/widgets.dart'; - -class FakeFlutter { - main() { - return new Row(children: [ - new Text('aaa'), -// start - new Text('bbb'), - new Text('ccc'), -// end - new Text('ddd'), - ]); - } -} -'''); - _setStartEndSelection(); - if (omitNew) { - await assertHasAssist(DartAssistKind.FLUTTER_WRAP_COLUMN, ''' -import 'package:flutter/widgets.dart'; - -class FakeFlutter { - main() { - return new Row(children: [ - new Text('aaa'), -// start - Column( - children: <Widget>[ - new Text('bbb'), - new Text('ccc'), - ], - ), -// end - new Text('ddd'), - ]); - } -} -'''); - } else { - await assertHasAssist(DartAssistKind.FLUTTER_WRAP_COLUMN, ''' -import 'package:flutter/widgets.dart'; - -class FakeFlutter { - main() { - return new Row(children: [ - new Text('aaa'), -// start - new Column( - children: <Widget>[ - new Text('bbb'), - new Text('ccc'), - ], - ), -// end - new Text('ddd'), - ]); - } -} -'''); - } - } - - test_flutterWrapColumn_OK_implicitNew() async { - configurePreviewDart2(); - addFlutterPackage(); - await resolveTestUnit(''' -import 'package:flutter/widgets.dart'; - -main() { - return Container( - child: /*caret*/Text('aaa'), - ); -} -'''); - _setCaretLocation(); - await assertHasAssist(DartAssistKind.FLUTTER_WRAP_COLUMN, ''' -import 'package:flutter/widgets.dart'; - -main() { - return Container( - child: /*caret*/Column( - children: <Widget>[ - Text('aaa'), - ], - ), - ); -} -'''); - } - - test_flutterWrapContainer_BAD_onContainer() async { - addFlutterPackage(); - await resolveTestUnit(''' -import 'package:flutter/widgets.dart'; -main() { - return /*caret*/new Container(); -} -'''); - _setCaretLocation(); - await assertNoAssist(DartAssistKind.FLUTTER_WRAP_CONTAINER); - } - - test_flutterWrapContainer_OK() async { - addFlutterPackage(); - await resolveTestUnit(''' -import 'package:flutter/widgets.dart'; -main() { - /*caret*/new Text('a'); -} -'''); - _setCaretLocation(); - if (omitNew) { - await assertHasAssist(DartAssistKind.FLUTTER_WRAP_CONTAINER, ''' -import 'package:flutter/widgets.dart'; -main() { - /*caret*/Container(child: new Text('a')); -} -'''); - } else { - await assertHasAssist(DartAssistKind.FLUTTER_WRAP_CONTAINER, ''' -import 'package:flutter/widgets.dart'; -main() { - /*caret*/new Center(child: new Text('a')); -} -'''); - } - } - - test_flutterWrapPadding_BAD_onPadding() async { - addFlutterPackage(); - await resolveTestUnit(''' -import 'package:flutter/widgets.dart'; -class FakeFlutter { - main() { - return /*caret*/new Padding(); - } -} -'''); - _setCaretLocation(); - await assertNoAssist(DartAssistKind.FLUTTER_WRAP_PADDING); - } - - test_flutterWrapPadding_OK() async { - addFlutterPackage(); - await resolveTestUnit(''' -import 'package:flutter/widgets.dart'; -class FakeFlutter { - main() { - return /*caret*/new Container(); - } -} -'''); - _setCaretLocation(); - if (omitNew) { - await assertHasAssist(DartAssistKind.FLUTTER_WRAP_PADDING, ''' -import 'package:flutter/widgets.dart'; -class FakeFlutter { - main() { - return /*caret*/Padding( - padding: const EdgeInsets.all(8.0), - child: new Container(), - ); - } -} -'''); - } else { - await assertHasAssist(DartAssistKind.FLUTTER_WRAP_PADDING, ''' -import 'package:flutter/widgets.dart'; -class FakeFlutter { - main() { - return /*caret*/new Padding( - padding: const EdgeInsets.all(8.0), - child: new Container(), - ); - } -} -'''); - } - } - - test_flutterWrapRow_OK() async { - addFlutterPackage(); - await resolveTestUnit(''' -import 'package:flutter/widgets.dart'; - -class FakeFlutter { - main() { - return new Column(children: [ - new Text('aaa'), -// start - new Text('bbb'), - new Text('ccc'), -// end - new Text('ddd'), - ]); - } -} -'''); - _setStartEndSelection(); - if (omitNew) { - await assertHasAssist(DartAssistKind.FLUTTER_WRAP_ROW, ''' -import 'package:flutter/widgets.dart'; - -class FakeFlutter { - main() { - return new Column(children: [ - new Text('aaa'), -// start - Row( - children: <Widget>[ - new Text('bbb'), - new Text('ccc'), - ], - ), -// end - new Text('ddd'), - ]); - } -} -'''); - } else { - await assertHasAssist(DartAssistKind.FLUTTER_WRAP_ROW, ''' -import 'package:flutter/widgets.dart'; - -class FakeFlutter { - main() { - return new Column(children: [ - new Text('aaa'), -// start - new Row( - children: <Widget>[ - new Text('bbb'), - new Text('ccc'), - ], - ), -// end - new Text('ddd'), - ]); - } -} -'''); - } - } - - test_flutterWrapWidget_BAD_minimal() async { - addFlutterPackage(); - await resolveTestUnit(''' -/*caret*/x(){} -'''); - _setCaretLocation(); - await assertNoAssist(DartAssistKind.FLUTTER_WRAP_GENERIC); - } - - test_flutterWrapWidget_BAD_multiLine() async { - verifyNoTestUnitErrors = false; - addFlutterPackage(); - await resolveTestUnit(''' -import 'package:flutter/widgets.dart'; -build() { - return new Container( - child: new Row( - children: [/*caret*/ -// start - new Transform(), - new Object(), - new AspectRatio(), -// end - ], - ), - ); -} -'''); - _setCaretLocation(); - await assertNoAssist(DartAssistKind.FLUTTER_WRAP_GENERIC); - } - - test_flutterWrapWidget_BAD_singleLine() async { - addFlutterPackage(); - await resolveTestUnit(''' -import 'package:flutter/widgets.dart'; -class FakeFlutter { - main() { - var obj; -// start - return new Row(children: [/*caret*/ new Container()]); -// end - } -} -'''); - _setCaretLocation(); - await assertNoAssist(DartAssistKind.FLUTTER_WRAP_GENERIC); - } - - test_flutterWrapWidget_OK_multiLine() async { - addFlutterPackage(); - await resolveTestUnit(''' -import 'package:flutter/widgets.dart'; -build() { - return new Container( - child: new Row( -// start - children: [/*caret*/ - new Text('111'), - new Text('222'), - new Container(), - ], -// end - ), - ); -} -'''); - _setCaretLocation(); - await assertHasAssist(DartAssistKind.FLUTTER_WRAP_GENERIC, ''' -import 'package:flutter/widgets.dart'; -build() { - return new Container( - child: new Row( -// start - children: [ - new widget( - children: [/*caret*/ - new Text('111'), - new Text('222'), - new Container(), - ], - ), - ], -// end - ), - ); -} -'''); - } - - test_flutterWrapWidget_OK_multiLines() async { - addFlutterPackage(); - await resolveTestUnit(''' -import 'package:flutter/widgets.dart'; -class FakeFlutter { - main() { - return new Container( -// start - child: new /*caret*/DefaultTextStyle( - child: new Row( - children: <Widget>[ - new Container( - ), - ], - ), - ), -// end - ); - } -} -'''); - _setCaretLocation(); - if (omitNew) { - await assertHasAssist(DartAssistKind.FLUTTER_WRAP_GENERIC, ''' -import 'package:flutter/widgets.dart'; -class FakeFlutter { - main() { - return new Container( -// start - child: widget( - child: new /*caret*/DefaultTextStyle( - child: new Row( - children: <Widget>[ - new Container( - ), - ], - ), - ), - ), -// end - ); - } -} -'''); - } else { - await assertHasAssist(DartAssistKind.FLUTTER_WRAP_GENERIC, ''' -import 'package:flutter/widgets.dart'; -class FakeFlutter { - main() { - return new Container( -// start - child: new widget( - child: new /*caret*/DefaultTextStyle( - child: new Row( - children: <Widget>[ - new Container( - ), - ], - ), - ), - ), -// end - ); - } -} -'''); - } - } - - test_flutterWrapWidget_OK_multiLines_eol2() async { - addFlutterPackage(); - await resolveTestUnit(''' -import 'package:flutter/widgets.dart'; -class FakeFlutter {\r - main() {\r - return new Container(\r -// start\r - child: new /*caret*/DefaultTextStyle(\r - child: new Row(\r - children: <Widget>[\r - new Container(\r - ),\r - ],\r - ),\r - ),\r -// end\r - );\r - }\r -}\r -'''); - _setCaretLocation(); - if (omitNew) { - await assertHasAssist(DartAssistKind.FLUTTER_WRAP_GENERIC, ''' -import 'package:flutter/widgets.dart'; -class FakeFlutter {\r - main() {\r - return new Container(\r -// start\r - child: widget(\r - child: new /*caret*/DefaultTextStyle(\r - child: new Row(\r - children: <Widget>[\r - new Container(\r - ),\r - ],\r - ),\r - ),\r - ),\r -// end\r - );\r - }\r -}\r -'''); - } else { - await assertHasAssist(DartAssistKind.FLUTTER_WRAP_GENERIC, ''' -import 'package:flutter/widgets.dart'; -class FakeFlutter {\r - main() {\r - return new Container(\r -// start\r - child: new widget(\r - child: new /*caret*/DefaultTextStyle(\r - child: new Row(\r - children: <Widget>[\r - new Container(\r - ),\r - ],\r - ),\r - ),\r - ),\r -// end\r - );\r - }\r -}\r -'''); - } - } - - test_flutterWrapWidget_OK_prefixedIdentifier_identifier() async { - addFlutterPackage(); - await resolveTestUnit(''' -import 'package:flutter/widgets.dart'; - -abstract class Foo extends Widget { - Widget bar; -} - -main(Foo foo) { - return foo./*caret*/bar; -} -'''); - _setCaretLocation(); - await assertHasAssist(DartAssistKind.FLUTTER_WRAP_GENERIC, ''' -import 'package:flutter/widgets.dart'; - -abstract class Foo extends Widget { - Widget bar; -} - -main(Foo foo) { - return widget(child: foo./*caret*/bar); -} -'''); - } - - test_flutterWrapWidget_OK_prefixedIdentifier_prefix() async { - addFlutterPackage(); - await resolveTestUnit(''' -import 'package:flutter/widgets.dart'; - -abstract class Foo extends Widget { - Widget bar; -} - -main(Foo foo) { - return /*caret*/foo.bar; -} -'''); - _setCaretLocation(); - await assertHasAssist(DartAssistKind.FLUTTER_WRAP_GENERIC, ''' -import 'package:flutter/widgets.dart'; - -abstract class Foo extends Widget { - Widget bar; -} - -main(Foo foo) { - return /*caret*/widget(child: foo.bar); -} -'''); - } - - test_flutterWrapWidget_OK_singleLine1() async { - addFlutterPackage(); - await resolveTestUnit(''' -import 'package:flutter/widgets.dart'; -class FakeFlutter { - main() { -// start - return /*caret*/new Container(); -// end - } -} -'''); - _setCaretLocation(); - if (omitNew) { - await assertHasAssist(DartAssistKind.FLUTTER_WRAP_GENERIC, ''' -import 'package:flutter/widgets.dart'; -class FakeFlutter { - main() { -// start - return /*caret*/widget(child: new Container()); -// end - } -} -'''); - } else { - await assertHasAssist(DartAssistKind.FLUTTER_WRAP_GENERIC, ''' -import 'package:flutter/widgets.dart'; -class FakeFlutter { - main() { -// start - return /*caret*/new widget(child: new Container()); -// end - } -} -'''); - } - } - - test_flutterWrapWidget_OK_singleLine2() async { - addFlutterPackage(); - await resolveTestUnit(''' -import 'package:flutter/widgets.dart'; -class FakeFlutter { - main() { - return new ClipRect./*caret*/rect(); - } -} -'''); - _setCaretLocation(); - if (omitNew) { - await assertHasAssist(DartAssistKind.FLUTTER_WRAP_GENERIC, ''' -import 'package:flutter/widgets.dart'; -class FakeFlutter { - main() { - return widget(child: new ClipRect./*caret*/rect()); - } -} -'''); - } else { - await assertHasAssist(DartAssistKind.FLUTTER_WRAP_GENERIC, ''' -import 'package:flutter/widgets.dart'; -class FakeFlutter { - main() { - return new widget(child: new ClipRect./*caret*/rect()); - } -} -'''); - } - } - - test_flutterWrapWidget_OK_variable() async { - addFlutterPackage(); - await resolveTestUnit(''' -import 'package:flutter/widgets.dart'; -class FakeFlutter { - main() { - var container = new Container(); - return /*caret*/container; - } -} -'''); - _setCaretLocation(); - if (omitNew) { - await assertHasAssist(DartAssistKind.FLUTTER_WRAP_GENERIC, ''' -import 'package:flutter/widgets.dart'; -class FakeFlutter { - main() { - var container = new Container(); - return /*caret*/widget(child: container); - } -} -'''); - } else { - await assertHasAssist(DartAssistKind.FLUTTER_WRAP_GENERIC, ''' -import 'package:flutter/widgets.dart'; -class FakeFlutter { - main() { - var container = new Container(); - return /*caret*/new widget(child: container); - } -} -'''); - } - } - - test_importAddShow_BAD_hasShow() async { - await resolveTestUnit(''' -import 'dart:math' show PI; -main() { - PI; -} -'''); - await assertNoAssistAt('import ', DartAssistKind.IMPORT_ADD_SHOW); - } - - test_importAddShow_BAD_unresolvedUri() async { - verifyNoTestUnitErrors = false; - await resolveTestUnit(''' -import '/no/such/lib.dart'; -'''); - await assertNoAssistAt('import ', DartAssistKind.IMPORT_ADD_SHOW); - } - - test_importAddShow_BAD_unused() async { - await resolveTestUnit(''' -import 'dart:math'; -'''); - await assertNoAssistAt('import ', DartAssistKind.IMPORT_ADD_SHOW); - } - - test_importAddShow_OK_hasUnresolvedIdentifier() async { - await resolveTestUnit(''' -import 'dart:math'; -main(x) { - PI; - return x.foo(); -} -'''); - await assertHasAssistAt('import ', DartAssistKind.IMPORT_ADD_SHOW, ''' -import 'dart:math' show PI; -main(x) { - PI; - return x.foo(); -} -'''); - } - - test_importAddShow_OK_onDirective() async { - await resolveTestUnit(''' -import 'dart:math'; -main() { - PI; - E; - max(1, 2); -} -'''); - await assertHasAssistAt('import ', DartAssistKind.IMPORT_ADD_SHOW, ''' -import 'dart:math' show E, PI, max; -main() { - PI; - E; - max(1, 2); -} -'''); - } - - test_importAddShow_OK_onUri() async { - await resolveTestUnit(''' -import 'dart:math'; -main() { - PI; - E; - max(1, 2); -} -'''); - await assertHasAssistAt('art:math', DartAssistKind.IMPORT_ADD_SHOW, ''' -import 'dart:math' show E, PI, max; -main() { - PI; - E; - max(1, 2); -} -'''); - } - - test_introduceLocalTestedType_BAD_notBlock() async { - await resolveTestUnit(''' -main(p) { - if (p is String) - print('not a block'); -} -'''); - await assertNoAssistAt('if (p', DartAssistKind.INTRODUCE_LOCAL_CAST_TYPE); - } - - test_introduceLocalTestedType_BAD_notIsExpression() async { - await resolveTestUnit(''' -main(p) { - if (p == null) { - } -} -'''); - await assertNoAssistAt('if (p', DartAssistKind.INTRODUCE_LOCAL_CAST_TYPE); - } - - test_introduceLocalTestedType_BAD_notStatement() async { - await resolveTestUnit(''' -class C { - bool b; - C(v) : b = v is int; -}'''); - await assertNoAssistAt('is int', DartAssistKind.INTRODUCE_LOCAL_CAST_TYPE); - } - - test_introduceLocalTestedType_OK_if_is() async { - await resolveTestUnit(''' -class MyTypeName {} -main(p) { - if (p is MyTypeName) { - } - p = null; -} -'''); - String expected = ''' -class MyTypeName {} -main(p) { - if (p is MyTypeName) { - MyTypeName myTypeName = p; - } - p = null; -} -'''; - await assertHasAssistAt( - 'is MyType', DartAssistKind.INTRODUCE_LOCAL_CAST_TYPE, expected); - _assertLinkedGroup( - change.linkedEditGroups[0], - ['myTypeName = '], - expectedSuggestions(LinkedEditSuggestionKind.VARIABLE, - ['myTypeName', 'typeName', 'name'])); - // another good location - await assertHasAssistAt( - 'if (p', DartAssistKind.INTRODUCE_LOCAL_CAST_TYPE, expected); - } - - test_introduceLocalTestedType_OK_if_isNot() async { - await resolveTestUnit(''' -class MyTypeName {} -main(p) { - if (p is! MyTypeName) { - return; - } -} -'''); - String expected = ''' -class MyTypeName {} -main(p) { - if (p is! MyTypeName) { - return; - } - MyTypeName myTypeName = p; -} -'''; - await assertHasAssistAt( - 'is! MyType', DartAssistKind.INTRODUCE_LOCAL_CAST_TYPE, expected); - _assertLinkedGroup( - change.linkedEditGroups[0], - ['myTypeName = '], - expectedSuggestions(LinkedEditSuggestionKind.VARIABLE, - ['myTypeName', 'typeName', 'name'])); - // another good location - await assertHasAssistAt( - 'if (p', DartAssistKind.INTRODUCE_LOCAL_CAST_TYPE, expected); - } - - test_introduceLocalTestedType_OK_while() async { - await resolveTestUnit(''' -main(p) { - while (p is String) { - } - p = null; -} -'''); - String expected = ''' -main(p) { - while (p is String) { - String s = p; - } - p = null; -} -'''; - await assertHasAssistAt( - 'is String', DartAssistKind.INTRODUCE_LOCAL_CAST_TYPE, expected); - await assertHasAssistAt( - 'while (p', DartAssistKind.INTRODUCE_LOCAL_CAST_TYPE, expected); - } - - test_invalidSelection() async { - await resolveTestUnit(''); - offset = -1; - length = 0; - List<Assist> assists = await _computeAssists(); - expect(assists, isEmpty); - } - - test_invertIfStatement_blocks() async { - await resolveTestUnit(''' -main() { - if (true) { - 0; - } else { - 1; - } -} -'''); - await assertHasAssistAt('if (', DartAssistKind.INVERT_IF_STATEMENT, ''' -main() { - if (false) { - 1; - } else { - 0; - } -} -'''); - } - - test_invertIfStatement_statements() async { - await resolveTestUnit(''' -main() { - if (true) - 0; - else - 1; -} -'''); - await assertHasAssistAt('if (', DartAssistKind.INVERT_IF_STATEMENT, ''' -main() { - if (false) - 1; - else - 0; -} -'''); - } - - test_joinIfStatementInner_BAD_innerNotIf() async { - await resolveTestUnit(''' -main() { - if (1 == 1) { - print(0); - } -} -'''); - await assertNoAssistAt('if (1 ==', DartAssistKind.JOIN_IF_WITH_INNER); - } - - test_joinIfStatementInner_BAD_innerWithElse() async { - await resolveTestUnit(''' -main() { - if (1 == 1) { - if (2 == 2) { - print(0); - } else { - print(1); - } - } -} -'''); - await assertNoAssistAt('if (1 ==', DartAssistKind.JOIN_IF_WITH_INNER); - } - - test_joinIfStatementInner_BAD_statementAfterInner() async { - await resolveTestUnit(''' -main() { - if (1 == 1) { - if (2 == 2) { - print(2); - } - print(1); - } -} -'''); - await assertNoAssistAt('if (1 ==', DartAssistKind.JOIN_IF_WITH_INNER); - } - - test_joinIfStatementInner_BAD_statementBeforeInner() async { - await resolveTestUnit(''' -main() { - if (1 == 1) { - print(1); - if (2 == 2) { - print(2); - } - } -} -'''); - await assertNoAssistAt('if (1 ==', DartAssistKind.JOIN_IF_WITH_INNER); - } - - test_joinIfStatementInner_BAD_targetNotIf() async { - await resolveTestUnit(''' -main() { - print(0); -} -'''); - await assertNoAssistAt('print', DartAssistKind.JOIN_IF_WITH_INNER); - } - - test_joinIfStatementInner_BAD_targetWithElse() async { - await resolveTestUnit(''' -main() { - if (1 == 1) { - if (2 == 2) { - print(0); - } - } else { - print(1); - } -} -'''); - await assertNoAssistAt('if (1 ==', DartAssistKind.JOIN_IF_WITH_INNER); - } - - test_joinIfStatementInner_OK_conditionAndOr() async { - await resolveTestUnit(''' -main() { - if (1 == 1) { - if (2 == 2 || 3 == 3) { - print(0); - } - } -} -'''); - await assertHasAssistAt('if (1 ==', DartAssistKind.JOIN_IF_WITH_INNER, ''' -main() { - if (1 == 1 && (2 == 2 || 3 == 3)) { - print(0); - } -} -'''); - } - - test_joinIfStatementInner_OK_conditionInvocation() async { - await resolveTestUnit(''' -main() { - if (isCheck()) { - if (2 == 2) { - print(0); - } - } -} -bool isCheck() => false; -'''); - await assertHasAssistAt( - 'if (isCheck', DartAssistKind.JOIN_IF_WITH_INNER, ''' -main() { - if (isCheck() && 2 == 2) { - print(0); - } -} -bool isCheck() => false; -'''); - } - - test_joinIfStatementInner_OK_conditionOrAnd() async { - await resolveTestUnit(''' -main() { - if (1 == 1 || 2 == 2) { - if (3 == 3) { - print(0); - } - } -} -'''); - await assertHasAssistAt('if (1 ==', DartAssistKind.JOIN_IF_WITH_INNER, ''' -main() { - if ((1 == 1 || 2 == 2) && 3 == 3) { - print(0); - } -} -'''); - } - - test_joinIfStatementInner_OK_onCondition() async { - await resolveTestUnit(''' -main() { - if (1 == 1) { - if (2 == 2) { - print(0); - } - } -} -'''); - await assertHasAssistAt('1 ==', DartAssistKind.JOIN_IF_WITH_INNER, ''' -main() { - if (1 == 1 && 2 == 2) { - print(0); - } -} -'''); - } - - test_joinIfStatementInner_OK_simpleConditions_block_block() async { - await resolveTestUnit(''' -main() { - if (1 == 1) { - if (2 == 2) { - print(0); - } - } -} -'''); - await assertHasAssistAt('if (1 ==', DartAssistKind.JOIN_IF_WITH_INNER, ''' -main() { - if (1 == 1 && 2 == 2) { - print(0); - } -} -'''); - } - - test_joinIfStatementInner_OK_simpleConditions_block_single() async { - await resolveTestUnit(''' -main() { - if (1 == 1) { - if (2 == 2) - print(0); - } -} -'''); - await assertHasAssistAt('if (1 ==', DartAssistKind.JOIN_IF_WITH_INNER, ''' -main() { - if (1 == 1 && 2 == 2) { - print(0); - } -} -'''); - } - - test_joinIfStatementInner_OK_simpleConditions_single_blockMulti() async { - await resolveTestUnit(''' -main() { - if (1 == 1) { - if (2 == 2) { - print(1); - print(2); - print(3); - } - } -} -'''); - await assertHasAssistAt('if (1 ==', DartAssistKind.JOIN_IF_WITH_INNER, ''' -main() { - if (1 == 1 && 2 == 2) { - print(1); - print(2); - print(3); - } -} -'''); - } - - test_joinIfStatementInner_OK_simpleConditions_single_blockOne() async { - await resolveTestUnit(''' -main() { - if (1 == 1) - if (2 == 2) { - print(0); - } -} -'''); - await assertHasAssistAt('if (1 ==', DartAssistKind.JOIN_IF_WITH_INNER, ''' -main() { - if (1 == 1 && 2 == 2) { - print(0); - } -} -'''); - } - - test_joinIfStatementOuter_BAD_outerNotIf() async { - await resolveTestUnit(''' -main() { - if (1 == 1) { - print(0); - } -} -'''); - await assertNoAssistAt('if (1 == 1', DartAssistKind.JOIN_IF_WITH_OUTER); - } - - test_joinIfStatementOuter_BAD_outerWithElse() async { - await resolveTestUnit(''' -main() { - if (1 == 1) { - if (2 == 2) { - print(0); - } - } else { - print(1); - } -} -'''); - await assertNoAssistAt('if (2 == 2', DartAssistKind.JOIN_IF_WITH_OUTER); - } - - test_joinIfStatementOuter_BAD_statementAfterInner() async { - await resolveTestUnit(''' -main() { - if (1 == 1) { - if (2 == 2) { - print(2); - } - print(1); - } -} -'''); - await assertNoAssistAt('if (2 == 2', DartAssistKind.JOIN_IF_WITH_OUTER); - } - - test_joinIfStatementOuter_BAD_statementBeforeInner() async { - await resolveTestUnit(''' -main() { - if (1 == 1) { - print(1); - if (2 == 2) { - print(2); - } - } -} -'''); - await assertNoAssistAt('if (2 == 2', DartAssistKind.JOIN_IF_WITH_OUTER); - } - - test_joinIfStatementOuter_BAD_targetNotIf() async { - await resolveTestUnit(''' -main() { - print(0); -} -'''); - await assertNoAssistAt('print', DartAssistKind.JOIN_IF_WITH_OUTER); - } - - test_joinIfStatementOuter_BAD_targetWithElse() async { - await resolveTestUnit(''' -main() { - if (1 == 1) { - if (2 == 2) { - print(0); - } else { - print(1); - } - } -} -'''); - await assertNoAssistAt('if (2 == 2', DartAssistKind.JOIN_IF_WITH_OUTER); - } - - test_joinIfStatementOuter_OK_conditionAndOr() async { - await resolveTestUnit(''' -main() { - if (1 == 1) { - if (2 == 2 || 3 == 3) { - print(0); - } - } -} -'''); - await assertHasAssistAt('if (2 ==', DartAssistKind.JOIN_IF_WITH_OUTER, ''' -main() { - if (1 == 1 && (2 == 2 || 3 == 3)) { - print(0); - } -} -'''); - } - - test_joinIfStatementOuter_OK_conditionInvocation() async { - await resolveTestUnit(''' -main() { - if (1 == 1) { - if (isCheck()) { - print(0); - } - } -} -bool isCheck() => false; -'''); - await assertHasAssistAt( - 'if (isCheck', DartAssistKind.JOIN_IF_WITH_OUTER, ''' -main() { - if (1 == 1 && isCheck()) { - print(0); - } -} -bool isCheck() => false; -'''); - } - - test_joinIfStatementOuter_OK_conditionOrAnd() async { - await resolveTestUnit(''' -main() { - if (1 == 1 || 2 == 2) { - if (3 == 3) { - print(0); - } - } -} -'''); - await assertHasAssistAt('if (3 == 3', DartAssistKind.JOIN_IF_WITH_OUTER, ''' -main() { - if ((1 == 1 || 2 == 2) && 3 == 3) { - print(0); - } -} -'''); - } - - test_joinIfStatementOuter_OK_onCondition() async { - await resolveTestUnit(''' -main() { - if (1 == 1) { - if (2 == 2) { - print(0); - } - } -} -'''); - await assertHasAssistAt('if (2 == 2', DartAssistKind.JOIN_IF_WITH_OUTER, ''' -main() { - if (1 == 1 && 2 == 2) { - print(0); - } -} -'''); - } - - test_joinIfStatementOuter_OK_simpleConditions_block_block() async { - await resolveTestUnit(''' -main() { - if (1 == 1) { - if (2 == 2) { - print(0); - } - } -} -'''); - await assertHasAssistAt('if (2 == 2', DartAssistKind.JOIN_IF_WITH_OUTER, ''' -main() { - if (1 == 1 && 2 == 2) { - print(0); - } -} -'''); - } - - test_joinIfStatementOuter_OK_simpleConditions_block_single() async { - await resolveTestUnit(''' -main() { - if (1 == 1) { - if (2 == 2) - print(0); - } -} -'''); - await assertHasAssistAt('if (2 == 2', DartAssistKind.JOIN_IF_WITH_OUTER, ''' -main() { - if (1 == 1 && 2 == 2) { - print(0); - } -} -'''); - } - - test_joinIfStatementOuter_OK_simpleConditions_single_blockMulti() async { - await resolveTestUnit(''' -main() { - if (1 == 1) { - if (2 == 2) { - print(1); - print(2); - print(3); - } - } -} -'''); - await assertHasAssistAt('if (2 == 2', DartAssistKind.JOIN_IF_WITH_OUTER, ''' -main() { - if (1 == 1 && 2 == 2) { - print(1); - print(2); - print(3); - } -} -'''); - } - - test_joinIfStatementOuter_OK_simpleConditions_single_blockOne() async { - await resolveTestUnit(''' -main() { - if (1 == 1) - if (2 == 2) { - print(0); - } -} -'''); - await assertHasAssistAt('if (2 == 2', DartAssistKind.JOIN_IF_WITH_OUTER, ''' -main() { - if (1 == 1 && 2 == 2) { - print(0); - } -} -'''); - } - - test_joinVariableDeclaration_onAssignment_BAD_hasInitializer() async { - await resolveTestUnit(''' -main() { - var v = 1; - v = 2; -} -'''); - await assertNoAssistAt('v = 2', DartAssistKind.JOIN_VARIABLE_DECLARATION); - } - - test_joinVariableDeclaration_onAssignment_BAD_notAdjacent() async { - await resolveTestUnit(''' -main() { - var v; - var bar; - v = 1; -} -'''); - await assertNoAssistAt('v = 1', DartAssistKind.JOIN_VARIABLE_DECLARATION); - } - - test_joinVariableDeclaration_onAssignment_BAD_notAssignment() async { - await resolveTestUnit(''' -main() { - var v; - v += 1; -} -'''); - await assertNoAssistAt('v += 1', DartAssistKind.JOIN_VARIABLE_DECLARATION); - } - - test_joinVariableDeclaration_onAssignment_BAD_notDeclaration() async { - await resolveTestUnit(''' -main(var v) { - v = 1; -} -'''); - await assertNoAssistAt('v = 1', DartAssistKind.JOIN_VARIABLE_DECLARATION); - } - - test_joinVariableDeclaration_onAssignment_BAD_notLeftArgument() async { - await resolveTestUnit(''' -main() { - var v; - 1 + v; // marker -} -'''); - await assertNoAssistAt( - 'v; // marker', DartAssistKind.JOIN_VARIABLE_DECLARATION); - } - - test_joinVariableDeclaration_onAssignment_BAD_notOneVariable() async { - await resolveTestUnit(''' -main() { - var v, v2; - v = 1; -} -'''); - await assertNoAssistAt('v = 1', DartAssistKind.JOIN_VARIABLE_DECLARATION); - } - - test_joinVariableDeclaration_onAssignment_BAD_notResolved() async { - verifyNoTestUnitErrors = false; - await resolveTestUnit(''' -main() { - var v; - x = 1; -} -'''); - await assertNoAssistAt('x = 1', DartAssistKind.JOIN_VARIABLE_DECLARATION); - } - - test_joinVariableDeclaration_onAssignment_BAD_notSameBlock() async { - await resolveTestUnit(''' -main() { - var v; - { - v = 1; - } -} -'''); - await assertNoAssistAt('v = 1', DartAssistKind.JOIN_VARIABLE_DECLARATION); - } - - test_joinVariableDeclaration_onAssignment_OK() async { - await resolveTestUnit(''' -main() { - var v; - v = 1; -} -'''); - await assertHasAssistAt('v =', DartAssistKind.JOIN_VARIABLE_DECLARATION, ''' -main() { - var v = 1; -} -'''); - } - - test_joinVariableDeclaration_onDeclaration_BAD_hasInitializer() async { - await resolveTestUnit(''' -main() { - var v = 1; - v = 2; -} -'''); - await assertNoAssistAt('v = 1', DartAssistKind.JOIN_VARIABLE_DECLARATION); - } - - test_joinVariableDeclaration_onDeclaration_BAD_lastStatement() async { - await resolveTestUnit(''' -main() { - if (true) - var v; -} -'''); - await assertNoAssistAt('v;', DartAssistKind.JOIN_VARIABLE_DECLARATION); - } - - test_joinVariableDeclaration_onDeclaration_BAD_nextNotAssignmentExpression() async { - await resolveTestUnit(''' -main() { - var v; - 42; -} -'''); - await assertNoAssistAt('v;', DartAssistKind.JOIN_VARIABLE_DECLARATION); - } - - test_joinVariableDeclaration_onDeclaration_BAD_nextNotExpressionStatement() async { - await resolveTestUnit(''' -main() { - var v; - if (true) return; -} -'''); - await assertNoAssistAt('v;', DartAssistKind.JOIN_VARIABLE_DECLARATION); - } - - test_joinVariableDeclaration_onDeclaration_BAD_nextNotPureAssignment() async { - await resolveTestUnit(''' -main() { - var v; - v += 1; -} -'''); - await assertNoAssistAt('v;', DartAssistKind.JOIN_VARIABLE_DECLARATION); - } - - test_joinVariableDeclaration_onDeclaration_BAD_notOneVariable() async { - await resolveTestUnit(''' -main() { - var v, v2; - v = 1; -} -'''); - await assertNoAssistAt('v, ', DartAssistKind.JOIN_VARIABLE_DECLARATION); - } - - test_joinVariableDeclaration_onDeclaration_OK_onName() async { - await resolveTestUnit(''' -main() { - var v; - v = 1; -} -'''); - await assertHasAssistAt('v;', DartAssistKind.JOIN_VARIABLE_DECLARATION, ''' -main() { - var v = 1; -} -'''); - } - - test_joinVariableDeclaration_onDeclaration_OK_onType() async { - await resolveTestUnit(''' -main() { - int v; - v = 1; -} -'''); - await assertHasAssistAt( - 'int v', DartAssistKind.JOIN_VARIABLE_DECLARATION, ''' -main() { - int v = 1; -} -'''); - } - - test_joinVariableDeclaration_onDeclaration_OK_onVar() async { - await resolveTestUnit(''' -main() { - var v; - v = 1; -} -'''); - await assertHasAssistAt( - 'var v', DartAssistKind.JOIN_VARIABLE_DECLARATION, ''' -main() { - var v = 1; -} -'''); - } - - test_removeTypeAnnotation_classField_OK() async { - await resolveTestUnit(''' -class A { - int v = 1; -} -'''); - await assertHasAssistAt('v = ', DartAssistKind.REMOVE_TYPE_ANNOTATION, ''' -class A { - var v = 1; -} -'''); - } - - test_removeTypeAnnotation_classField_OK_final() async { - await resolveTestUnit(''' -class A { - final int v = 1; -} -'''); - await assertHasAssistAt('v = ', DartAssistKind.REMOVE_TYPE_ANNOTATION, ''' -class A { - final v = 1; -} -'''); - } - - test_removeTypeAnnotation_field_BAD_noInitializer() async { - await resolveTestUnit(''' -class A { - int v; -} -'''); - await assertNoAssistAt('v;', DartAssistKind.REMOVE_TYPE_ANNOTATION); - } - - test_removeTypeAnnotation_localVariable_BAD_noInitializer() async { - await resolveTestUnit(''' -main() { - int v; -} -'''); - await assertNoAssistAt('v;', DartAssistKind.REMOVE_TYPE_ANNOTATION); - } - - test_removeTypeAnnotation_localVariable_BAD_onInitializer() async { - await resolveTestUnit(''' -main() { - final int v = 1; -} -'''); - await assertNoAssistAt('1;', DartAssistKind.REMOVE_TYPE_ANNOTATION); - } - - test_removeTypeAnnotation_localVariable_OK() async { - await resolveTestUnit(''' -main() { - int a = 1, b = 2; -} -'''); - await assertHasAssistAt('int ', DartAssistKind.REMOVE_TYPE_ANNOTATION, ''' -main() { - var a = 1, b = 2; -} -'''); - } - - test_removeTypeAnnotation_localVariable_OK_const() async { - await resolveTestUnit(''' -main() { - const int v = 1; -} -'''); - await assertHasAssistAt('int ', DartAssistKind.REMOVE_TYPE_ANNOTATION, ''' -main() { - const v = 1; -} -'''); - } - - test_removeTypeAnnotation_localVariable_OK_final() async { - await resolveTestUnit(''' -main() { - final int v = 1; -} -'''); - await assertHasAssistAt('int ', DartAssistKind.REMOVE_TYPE_ANNOTATION, ''' -main() { - final v = 1; -} -'''); - } - - test_removeTypeAnnotation_topLevelVariable_BAD_noInitializer() async { - verifyNoTestUnitErrors = false; - await resolveTestUnit(''' -int v; -'''); - await assertNoAssistAt('v;', DartAssistKind.REMOVE_TYPE_ANNOTATION); - } - - test_removeTypeAnnotation_topLevelVariable_BAD_syntheticName() async { - verifyNoTestUnitErrors = false; - await resolveTestUnit(''' -MyType -'''); - await assertNoAssistAt('MyType', DartAssistKind.REMOVE_TYPE_ANNOTATION); - } - - test_removeTypeAnnotation_topLevelVariable_OK() async { - await resolveTestUnit(''' -int V = 1; -'''); - await assertHasAssistAt('int ', DartAssistKind.REMOVE_TYPE_ANNOTATION, ''' -var V = 1; -'''); - } - - test_removeTypeAnnotation_topLevelVariable_OK_final() async { - await resolveTestUnit(''' -final int V = 1; -'''); - await assertHasAssistAt('int ', DartAssistKind.REMOVE_TYPE_ANNOTATION, ''' -final V = 1; -'''); - } - - test_replaceConditionalWithIfElse_BAD_noEnclosingStatement() async { - await resolveTestUnit(''' -var v = true ? 111 : 222; -'''); - await assertNoAssistAt( - '? 111', DartAssistKind.REPLACE_CONDITIONAL_WITH_IF_ELSE); - } - - test_replaceConditionalWithIfElse_BAD_notConditional() async { - await resolveTestUnit(''' -main() { - var v = 42; -} -'''); - await assertNoAssistAt( - 'v = 42', DartAssistKind.REPLACE_CONDITIONAL_WITH_IF_ELSE); - } - - test_replaceConditionalWithIfElse_OK_assignment() async { - await resolveTestUnit(''' -main() { - var v; - v = true ? 111 : 222; -} -'''); - // on conditional - await assertHasAssistAt( - '11 :', DartAssistKind.REPLACE_CONDITIONAL_WITH_IF_ELSE, ''' -main() { - var v; - if (true) { - v = 111; - } else { - v = 222; - } -} -'''); - // on variable - await assertHasAssistAt( - 'v =', DartAssistKind.REPLACE_CONDITIONAL_WITH_IF_ELSE, ''' -main() { - var v; - if (true) { - v = 111; - } else { - v = 222; - } -} -'''); - } - - test_replaceConditionalWithIfElse_OK_return() async { - await resolveTestUnit(''' -main() { - return true ? 111 : 222; -} -'''); - await assertHasAssistAt( - 'return ', DartAssistKind.REPLACE_CONDITIONAL_WITH_IF_ELSE, ''' -main() { - if (true) { - return 111; - } else { - return 222; - } -} -'''); - } - - test_replaceConditionalWithIfElse_OK_variableDeclaration() async { - await resolveTestUnit(''' -main() { - int a = 1, vvv = true ? 111 : 222, b = 2; -} -'''); - await assertHasAssistAt( - '11 :', DartAssistKind.REPLACE_CONDITIONAL_WITH_IF_ELSE, ''' -main() { - int a = 1, vvv, b = 2; - if (true) { - vvv = 111; - } else { - vvv = 222; - } -} -'''); - } - - test_replaceIfElseWithConditional_BAD_expressionVsReturn() async { - await resolveTestUnit(''' -main() { - if (true) { - print(42); - } else { - return; - } -} -'''); - await assertNoAssistAt( - 'else', DartAssistKind.REPLACE_IF_ELSE_WITH_CONDITIONAL); - } - - test_replaceIfElseWithConditional_BAD_notIfStatement() async { - await resolveTestUnit(''' -main() { - print(0); -} -'''); - await assertNoAssistAt( - 'print', DartAssistKind.REPLACE_IF_ELSE_WITH_CONDITIONAL); - } - - test_replaceIfElseWithConditional_BAD_notSingleStatement() async { - await resolveTestUnit(''' -main() { - int vvv; - if (true) { - print(0); - vvv = 111; - } else { - print(0); - vvv = 222; - } -} -'''); - await assertNoAssistAt( - 'if (true)', DartAssistKind.REPLACE_IF_ELSE_WITH_CONDITIONAL); - } - - test_replaceIfElseWithConditional_OK_assignment() async { - await resolveTestUnit(''' -main() { - int vvv; - if (true) { - vvv = 111; - } else { - vvv = 222; - } -} -'''); - await assertHasAssistAt( - 'if (true)', DartAssistKind.REPLACE_IF_ELSE_WITH_CONDITIONAL, ''' -main() { - int vvv; - vvv = true ? 111 : 222; -} -'''); - } - - test_replaceIfElseWithConditional_OK_return() async { - await resolveTestUnit(''' -main() { - if (true) { - return 111; - } else { - return 222; - } -} -'''); - await assertHasAssistAt( - 'if (true)', DartAssistKind.REPLACE_IF_ELSE_WITH_CONDITIONAL, ''' -main() { - return true ? 111 : 222; -} -'''); - } - - test_splitAndCondition_BAD_hasElse() async { - await resolveTestUnit(''' -main() { - if (1 == 1 && 2 == 2) { - print(1); - } else { - print(2); - } -} -'''); - await assertNoAssistAt('&& 2', DartAssistKind.SPLIT_AND_CONDITION); - } - - test_splitAndCondition_BAD_notAnd() async { - await resolveTestUnit(''' -main() { - if (1 == 1 || 2 == 2) { - print(0); - } -} -'''); - await assertNoAssistAt('|| 2', DartAssistKind.SPLIT_AND_CONDITION); - } - - test_splitAndCondition_BAD_notPartOfIf() async { - await resolveTestUnit(''' -main() { - print(1 == 1 && 2 == 2); -} -'''); - await assertNoAssistAt('&& 2', DartAssistKind.SPLIT_AND_CONDITION); - } - - test_splitAndCondition_BAD_notTopLevelAnd() async { - await resolveTestUnit(''' -main() { - if (true || (1 == 1 && 2 == 2)) { - print(0); - } - if (true && (3 == 3 && 4 == 4)) { - print(0); - } -} -'''); - await assertNoAssistAt('&& 2', DartAssistKind.SPLIT_AND_CONDITION); - await assertNoAssistAt('&& 4', DartAssistKind.SPLIT_AND_CONDITION); - } - - test_splitAndCondition_OK_innerAndExpression() async { - await resolveTestUnit(''' -main() { - if (1 == 1 && 2 == 2 && 3 == 3) { - print(0); - } -} -'''); - await assertHasAssistAt('&& 2 == 2', DartAssistKind.SPLIT_AND_CONDITION, ''' -main() { - if (1 == 1) { - if (2 == 2 && 3 == 3) { - print(0); - } - } -} -'''); - } - - test_splitAndCondition_OK_thenBlock() async { - await resolveTestUnit(''' -main() { - if (true && false) { - print(0); - if (3 == 3) { - print(1); - } - } -} -'''); - await assertHasAssistAt('&& false', DartAssistKind.SPLIT_AND_CONDITION, ''' -main() { - if (true) { - if (false) { - print(0); - if (3 == 3) { - print(1); - } - } - } -} -'''); - } - - test_splitAndCondition_OK_thenStatement() async { - await resolveTestUnit(''' -main() { - if (true && false) - print(0); -} -'''); - await assertHasAssistAt('&& false', DartAssistKind.SPLIT_AND_CONDITION, ''' -main() { - if (true) - if (false) - print(0); -} -'''); - } - - test_splitAndCondition_wrong() async { - await resolveTestUnit(''' -main() { - if (1 == 1 && 2 == 2) { - print(0); - } - print(3 == 3 && 4 == 4); -} -'''); - // not binary expression - await assertNoAssistAt('main() {', DartAssistKind.SPLIT_AND_CONDITION); - // selection is not empty and includes more than just operator - { - length = 5; - await assertNoAssistAt('&& 2 == 2', DartAssistKind.SPLIT_AND_CONDITION); - } - } - - test_splitVariableDeclaration_BAD_notOneVariable() async { - await resolveTestUnit(''' -main() { - var v = 1, v2; -} -'''); - await assertNoAssistAt('v = 1', DartAssistKind.SPLIT_VARIABLE_DECLARATION); - } - - test_splitVariableDeclaration_OK_onName() async { - await resolveTestUnit(''' -main() { - var v = 1; -} -'''); - await assertHasAssistAt( - 'v =', DartAssistKind.SPLIT_VARIABLE_DECLARATION, ''' -main() { - var v; - v = 1; -} -'''); - } - - test_splitVariableDeclaration_OK_onType() async { - await resolveTestUnit(''' -main() { - int v = 1; -} -'''); - await assertHasAssistAt( - 'int ', DartAssistKind.SPLIT_VARIABLE_DECLARATION, ''' -main() { - int v; - v = 1; -} -'''); - } - - test_splitVariableDeclaration_OK_onVar() async { - await resolveTestUnit(''' -main() { - var v = 1; -} -'''); - await assertHasAssistAt( - 'var ', DartAssistKind.SPLIT_VARIABLE_DECLARATION, ''' -main() { - var v; - v = 1; -} -'''); - } - - test_surroundWith_block() async { - await resolveTestUnit(''' -main() { -// start - print(0); - print(1); -// end -} -'''); - _setStartEndSelection(); - await assertHasAssist(DartAssistKind.SURROUND_WITH_BLOCK, ''' -main() { -// start - { - print(0); - print(1); - } -// end -} -'''); - } - - test_surroundWith_doWhile() async { - await resolveTestUnit(''' -main() { -// start - print(0); - print(1); -// end -} -'''); - _setStartEndSelection(); - await assertHasAssist(DartAssistKind.SURROUND_WITH_DO_WHILE, ''' -main() { -// start - do { - print(0); - print(1); - } while (condition); -// end -} -'''); - _assertLinkedGroup(change.linkedEditGroups[0], ['condition);']); - _assertExitPosition(after: 'condition);'); - } - - test_surroundWith_for() async { - await resolveTestUnit(''' -main() { -// start - print(0); - print(1); -// end -} -'''); - _setStartEndSelection(); - await assertHasAssist(DartAssistKind.SURROUND_WITH_FOR, ''' -main() { -// start - for (var v = init; condition; increment) { - print(0); - print(1); - } -// end -} -'''); - _assertLinkedGroup(change.linkedEditGroups[0], ['v =']); - _assertLinkedGroup(change.linkedEditGroups[1], ['init;']); - _assertLinkedGroup(change.linkedEditGroups[2], ['condition;']); - _assertLinkedGroup(change.linkedEditGroups[3], ['increment']); - _assertExitPosition(after: ' }'); - } - - test_surroundWith_forIn() async { - await resolveTestUnit(''' -main() { -// start - print(0); - print(1); -// end -} -'''); - _setStartEndSelection(); - await assertHasAssist(DartAssistKind.SURROUND_WITH_FOR_IN, ''' -main() { -// start - for (var item in iterable) { - print(0); - print(1); - } -// end -} -'''); - _assertLinkedGroup(change.linkedEditGroups[0], ['item']); - _assertLinkedGroup(change.linkedEditGroups[1], ['iterable']); - _assertExitPosition(after: ' }'); - } - - test_surroundWith_if() async { - await resolveTestUnit(''' -main() { -// start - print(0); - print(1); -// end -} -'''); - _setStartEndSelection(); - await assertHasAssist(DartAssistKind.SURROUND_WITH_IF, ''' -main() { -// start - if (condition) { - print(0); - print(1); - } -// end -} -'''); - _assertLinkedGroup(change.linkedEditGroups[0], ['condition']); - _assertExitPosition(after: ' }'); - } - - test_surroundWith_tryCatch() async { - await resolveTestUnit(''' -main() { -// start - print(0); - print(1); -// end -} -'''); - _setStartEndSelection(); - await assertHasAssist(DartAssistKind.SURROUND_WITH_TRY_CATCH, ''' -main() { -// start - try { - print(0); - print(1); - } on Exception catch (e) { - // TODO - } -// end -} -'''); - _assertLinkedGroup(change.linkedEditGroups[0], ['Exception']); - _assertLinkedGroup(change.linkedEditGroups[1], ['e) {']); - _assertLinkedGroup(change.linkedEditGroups[2], ['// TODO']); - _assertExitPosition(after: '// TODO'); - } - - test_surroundWith_tryFinally() async { - await resolveTestUnit(''' -main() { -// start - print(0); - print(1); -// end -} -'''); - _setStartEndSelection(); - await assertHasAssist(DartAssistKind.SURROUND_WITH_TRY_FINALLY, ''' -main() { -// start - try { - print(0); - print(1); - } finally { - // TODO - } -// end -} -'''); - _assertLinkedGroup(change.linkedEditGroups[0], ['// TODO']); - _assertExitPosition(after: '// TODO'); - } - - test_surroundWith_while() async { - await resolveTestUnit(''' -main() { -// start - print(0); - print(1); -// end -} -'''); - _setStartEndSelection(); - await assertHasAssist(DartAssistKind.SURROUND_WITH_WHILE, ''' -main() { -// start - while (condition) { - print(0); - print(1); - } -// end -} -'''); - _assertLinkedGroup(change.linkedEditGroups[0], ['condition']); - _assertExitPosition(after: ' }'); - } - - void _assertExitPosition({String before, String after}) { - Position exitPosition = change.selection; - expect(exitPosition, isNotNull); - expect(exitPosition.file, testFile); - if (before != null) { - expect(exitPosition.offset, resultCode.indexOf(before)); - } else if (after != null) { - expect(exitPosition.offset, resultCode.indexOf(after) + after.length); - } else { - fail("One of 'before' or 'after' expected."); - } - } - - /** - * Computes assists and verifies that there is an assist of the given kind. - */ - Future<Assist> _assertHasAssist(AssistKind kind) async { - List<Assist> assists = await _computeAssists(); - for (Assist assist in assists) { - if (assist.kind == kind) { - return assist; - } - } - fail('Expected to find assist $kind in\n${assists.join('\n')}'); - } - - void _assertLinkedGroup(LinkedEditGroup group, List<String> expectedStrings, - [List<LinkedEditSuggestion> expectedSuggestions]) { - List<Position> expectedPositions = _findResultPositions(expectedStrings); - expect(group.positions, unorderedEquals(expectedPositions)); - if (expectedSuggestions != null) { - expect(group.suggestions, unorderedEquals(expectedSuggestions)); - } - } - - Future<List<Assist>> _computeAssists() async { - CompilationUnitElement testUnitElement = - resolutionMap.elementDeclaredByCompilationUnit(testUnit); - DartAssistContext assistContext; - assistContext = new _DartAssistContextForValues( - testUnitElement.source, offset, length, driver, testUnit); - AssistProcessor processor = new AssistProcessor(assistContext); - return await processor.compute(); - } - - List<Position> _findResultPositions(List<String> searchStrings) { - List<Position> positions = <Position>[]; - for (String search in searchStrings) { - int offset = resultCode.indexOf(search); - positions.add(new Position(testFile, offset)); - } - return positions; - } - - void _setCaretLocation() { - offset = findOffset('/*caret*/') + '/*caret*/'.length; - length = 0; - } - - void _setStartEndSelection() { - offset = findOffset('// start\n') + '// start\n'.length; - length = findOffset('// end') - offset; - } -} - -class _DartAssistContextForValues implements DartAssistContext { - @override - final Source source; - - @override - final int selectionOffset; - - @override - final int selectionLength; - - @override - final AnalysisDriver analysisDriver; - - @override - final CompilationUnit unit; - - _DartAssistContextForValues(this.source, this.selectionOffset, - this.selectionLength, this.analysisDriver, this.unit); -}
diff --git a/pkg/analysis_server/test/services/correction/fix_test.dart b/pkg/analysis_server/test/services/correction/fix_test.dart deleted file mode 100644 index db6d6b7..0000000 --- a/pkg/analysis_server/test/services/correction/fix_test.dart +++ /dev/null
@@ -1,8840 +0,0 @@ -// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file -// for details. All rights reserved. Use of this source code is governed by a -// BSD-style license that can be found in the LICENSE file. - -import 'dart:async'; - -import 'package:analysis_server/plugin/edit/fix/fix_core.dart'; -import 'package:analysis_server/plugin/edit/fix/fix_dart.dart'; -import 'package:analysis_server/src/services/correction/fix.dart'; -import 'package:analysis_server/src/services/correction/fix_internal.dart'; -import 'package:analyzer/dart/ast/ast.dart'; -import 'package:analyzer/dart/ast/standard_resolution_map.dart'; -import 'package:analyzer/error/error.dart'; -import 'package:analyzer/file_system/file_system.dart'; -import 'package:analyzer/src/dart/analysis/ast_provider_driver.dart'; -import 'package:analyzer/src/dart/analysis/driver.dart'; -import 'package:analyzer/src/dart/element/ast_provider.dart'; -import 'package:analyzer/src/error/codes.dart'; -import 'package:analyzer/src/generated/parser.dart'; -import 'package:analyzer/src/generated/source.dart'; -import 'package:analyzer/src/source/package_map_resolver.dart'; -import 'package:analyzer_plugin/protocol/protocol_common.dart' - hide AnalysisError; -import 'package:analyzer_plugin/utilities/fixes/fixes.dart'; -import 'package:test/test.dart'; -import 'package:test_reflective_loader/test_reflective_loader.dart'; - -import '../../abstract_single_unit.dart'; - -main() { - defineReflectiveSuite(() { - defineReflectiveTests(FixProcessorTest); - defineReflectiveTests(LintFixTest); - }); -} - -typedef bool AnalysisErrorFilter(AnalysisError error); - -/** - * Base class for fix processor tests. - */ -class BaseFixProcessorTest extends AbstractSingleUnitTest { - AnalysisErrorFilter errorFilter = (AnalysisError error) { - return error.errorCode != HintCode.UNUSED_CATCH_CLAUSE && - error.errorCode != HintCode.UNUSED_CATCH_STACK && - error.errorCode != HintCode.UNUSED_ELEMENT && - error.errorCode != HintCode.UNUSED_FIELD && - error.errorCode != HintCode.UNUSED_LOCAL_VARIABLE; - }; - - String myPkgLibPath = '/packages/my_pkg/lib'; - - String flutterPkgLibPath = '/packages/flutter/lib'; - - Fix fix; - - SourceChange change; - String resultCode; - - assert_undefinedFunction_create_returnType_bool(String lineWithTest) async { - await resolveTestUnit(''' -main() { - bool b = true; - $lineWithTest -} -'''); - await assertHasFix(DartFixKind.CREATE_FUNCTION, ''' -main() { - bool b = true; - $lineWithTest -} - -bool test() { -} -'''); - } - - assertHasFix(FixKind kind, String expected, {String target}) async { - AnalysisError error = await _findErrorToFix(); - fix = await _assertHasFix(kind, error); - change = fix.change; - - // apply to "file" - List<SourceFileEdit> fileEdits = change.edits; - expect(fileEdits, hasLength(1)); - - String fileContent = testCode; - if (target != null) { - expect(fileEdits.first.file, convertPath(target)); - fileContent = getFile(target).readAsStringSync(); - } - - resultCode = SourceEdit.applySequence(fileContent, change.edits[0].edits); - // verify - expect(resultCode, expected); - } - - assertHasFixAllFix(ErrorCode errorCode, FixKind kind, String expected, - {String target}) async { - AnalysisError error = await _findErrorToFixOfType(errorCode); - fix = await _assertHasFix(kind, error, hasFixAllFix: true); - change = fix.change; - - // apply to "file" - List<SourceFileEdit> fileEdits = change.edits; - expect(fileEdits, hasLength(1)); - - String fileContent = testCode; - if (target != null) { - expect(fileEdits.first.file, convertPath(target)); - fileContent = getFile(target).readAsStringSync(); - } - - resultCode = SourceEdit.applySequence(fileContent, change.edits[0].edits); - // verify - expect(resultCode, expected); - } - - assertNoFix(FixKind kind) async { - AnalysisError error = await _findErrorToFix(); - await _assertNoFix(kind, error); - } - - List<LinkedEditSuggestion> expectedSuggestions( - LinkedEditSuggestionKind kind, List<String> values) { - return values.map((value) { - return new LinkedEditSuggestion(value, kind); - }).toList(); - } - - void setUp() { - super.setUp(); - verifyNoTestUnitErrors = false; - } - - /** - * Computes fixes and verifies that there is a fix of the given kind. - */ - Future<Fix> _assertHasFix(FixKind kind, AnalysisError error, - {bool hasFixAllFix: false}) async { - if (hasFixAllFix && !kind.canBeAppliedTogether()) { - fail('Expected to find and return fix-all FixKind for $kind, ' - 'but kind.canBeAppliedTogether is ${kind.canBeAppliedTogether}'); - } - - // Compute the fixes for this AnalysisError - final List<Fix> fixes = await _computeFixes(error); - - // If hasFixAllFix is false, assert that none of the fixes are a fix-all fix - if (!hasFixAllFix) { - for (Fix fix in fixes) { - if (fix.isFixAllFix()) { - fail('The boolean hasFixAllFix is false, but such a fix was found ' - 'in the computed set of fixes: $fixes, error: $error.'); - } - } - } - // If hasFixAllFix is true, assert that there exists such a fix in the list - else { - bool foundFixAllFix = false; - for (Fix fix in fixes) { - if (fix.isFixAllFix()) { - foundFixAllFix = true; - break; - } - } - if (!foundFixAllFix) { - fail('The boolean hasFixAllFix is true, but no fix-all fix was found ' - 'in the computed set of fixes: $fixes, error: $error.'); - } - } - - Fix foundFix = null; - if (!hasFixAllFix) { - foundFix = fixes.firstWhere( - (fix) => fix.kind == kind && !fix.isFixAllFix(), - orElse: () => null, - ); - } else { - foundFix = fixes.lastWhere( - (fix) => fix.kind == kind && fix.isFixAllFix(), - orElse: () => null, - ); - } - if (foundFix == null) { - fail('Expected to find fix $kind in\n${fixes.join('\n')}, hasFixAllFix = ' - '$hasFixAllFix'); - } - return foundFix; - } - - void _assertLinkedGroup(LinkedEditGroup group, List<String> expectedStrings, - [List<LinkedEditSuggestion> expectedSuggestions]) { - List<Position> expectedPositions = _findResultPositions(expectedStrings); - expect(group.positions, unorderedEquals(expectedPositions)); - if (expectedSuggestions != null) { - expect(group.suggestions, unorderedEquals(expectedSuggestions)); - } - } - - Future _assertNoFix(FixKind kind, AnalysisError error) async { - List<Fix> fixes = await _computeFixes(error); - for (Fix fix in fixes) { - if (fix.kind == kind) { - fail('Unexpected fix $kind in\n${fixes.join('\n')}'); - } - } - } - - Future<List<AnalysisError>> _computeErrors() async { - return (await driver.getResult(convertPath(testFile))).errors; - } - - /** - * Computes fixes for the given [error] in [testUnit]. - */ - Future<List<Fix>> _computeFixes(AnalysisError error) async { - DartFixContext fixContext = new _DartFixContextImpl( - resourceProvider, - driver, - new AstProviderForDriver(driver), - testUnit, - error, - await _computeErrors()); - return await new DefaultFixContributor().internalComputeFixes(fixContext); - } - - /** - * Configures the [SourceFactory] to have the `my_pkg` package in - * `/packages/my_pkg/lib` folder. - */ - void _configureMyPkg(Map<String, String> pathToCode) { - pathToCode.forEach((path, code) { - newFile('$myPkgLibPath/$path', content: code); - }); - // configure SourceFactory - Folder myPkgFolder = getFolder(myPkgLibPath); - UriResolver pkgResolver = new PackageMapUriResolver(resourceProvider, { - 'my_pkg': [myPkgFolder] - }); - SourceFactory sourceFactory = new SourceFactory( - [new DartUriResolver(sdk), pkgResolver, resourceResolver]); - driver.configure(sourceFactory: sourceFactory); - // force 'my_pkg' resolution - addSource( - '/tmp/other.dart', - pathToCode.keys - .map((path) => "import 'package:my_pkg/$path';") - .join('\n')); - } - - Future<AnalysisError> _findErrorToFix() async { - List<AnalysisError> errors = await _computeErrors(); - List<AnalysisError> filteredErrors = errors; - if (errorFilter != null) { - filteredErrors = filteredErrors.where(errorFilter).toList(); - } - if (filteredErrors.length != 1) { - StringBuffer buffer = new StringBuffer(); - buffer.writeln('Expected one error, found:'); - for (AnalysisError error in errors) { - buffer.writeln(' $error [${error.errorCode}]'); - } - fail(buffer.toString()); - } - return filteredErrors[0]; - } - - Future<AnalysisError> _findErrorToFixOfType(ErrorCode errorCode) async { - List<AnalysisError> errors = await _computeErrors(); - if (errorFilter != null) { - errors = errors.where(errorFilter).toList(); - } - return errors.firstWhere((error) => errorCode == error.errorCode); - } - - List<Position> _findResultPositions(List<String> searchStrings) { - List<Position> positions = <Position>[]; - for (String search in searchStrings) { - int offset = resultCode.indexOf(search); - positions.add(new Position(testFile, offset)); - } - return positions; - } -} - -@reflectiveTest -class FixProcessorTest extends BaseFixProcessorTest { - test_addAsync_asyncFor() async { - await resolveTestUnit(''' -import 'dart:async'; -void main(Stream<String> names) { - await for (String name in names) { - print(name); - } -} -'''); - await assertHasFix(DartFixKind.ADD_ASYNC, ''' -import 'dart:async'; -Future main(Stream<String> names) async { - await for (String name in names) { - print(name); - } -} -'''); - } - - test_addAsync_BAD_nullFunctionBody() async { - await resolveTestUnit(''' -var F = await; -'''); - await assertNoFix(DartFixKind.ADD_ASYNC); - } - - test_addAsync_blockFunctionBody() async { - errorFilter = (AnalysisError error) { - return error.errorCode == - CompileTimeErrorCode.BUILT_IN_IDENTIFIER_AS_TYPE; - }; - await resolveTestUnit(''' -foo() {} -main() { - await foo(); -} -'''); - await assertHasFix(DartFixKind.ADD_ASYNC, ''' -foo() {} -main() async { - await foo(); -} -'''); - } - - test_addAsync_blockFunctionBody_getter() async { - errorFilter = (AnalysisError error) { - return error.errorCode == - CompileTimeErrorCode.BUILT_IN_IDENTIFIER_AS_TYPE; - }; - await resolveTestUnit(''' -int get foo => null; -int f() { - await foo; - return 1; -} -'''); - await assertHasFix(DartFixKind.ADD_ASYNC, ''' -import \'dart:async\'; - -int get foo => null; -Future<int> f() async { - await foo; - return 1; -} -'''); - } - - test_addAsync_closure() async { - errorFilter = (AnalysisError error) { - return error.errorCode == StaticWarningCode.UNDEFINED_IDENTIFIER_AWAIT; - }; - await resolveTestUnit(''' -import 'dart:async'; - -void takeFutureCallback(Future callback()) {} - -void doStuff() => takeFutureCallback(() => await 1); -'''); - await assertHasFix(DartFixKind.ADD_ASYNC, ''' -import 'dart:async'; - -void takeFutureCallback(Future callback()) {} - -void doStuff() => takeFutureCallback(() async => await 1); -'''); - } - - test_addAsync_expressionFunctionBody() async { - errorFilter = (AnalysisError error) { - return error.errorCode == ParserErrorCode.UNEXPECTED_TOKEN; - }; - await resolveTestUnit(''' -foo() {} -main() => await foo(); -'''); - await assertHasFix(DartFixKind.ADD_ASYNC, ''' -foo() {} -main() async => await foo(); -'''); - } - - test_addAsync_returnFuture() async { - errorFilter = (AnalysisError error) { - return error.errorCode == - CompileTimeErrorCode.BUILT_IN_IDENTIFIER_AS_TYPE; - }; - await resolveTestUnit(''' -foo() {} -int main() { - await foo(); - return 42; -} -'''); - await assertHasFix(DartFixKind.ADD_ASYNC, ''' -import 'dart:async'; - -foo() {} -Future<int> main() async { - await foo(); - return 42; -} -'''); - } - - test_addAsync_returnFuture_alreadyFuture() async { - errorFilter = (AnalysisError error) { - return error.errorCode == - CompileTimeErrorCode.BUILT_IN_IDENTIFIER_AS_TYPE; - }; - await resolveTestUnit(''' -import 'dart:async'; -foo() {} -Future<int> main() { - await foo(); - return 42; -} -'''); - await assertHasFix(DartFixKind.ADD_ASYNC, ''' -import 'dart:async'; -foo() {} -Future<int> main() async { - await foo(); - return 42; -} -'''); - } - - test_addAsync_returnFuture_dynamic() async { - errorFilter = (AnalysisError error) { - return error.errorCode == - CompileTimeErrorCode.BUILT_IN_IDENTIFIER_AS_TYPE; - }; - await resolveTestUnit(''' -foo() {} -dynamic main() { - await foo(); - return 42; -} -'''); - await assertHasFix(DartFixKind.ADD_ASYNC, ''' -foo() {} -dynamic main() async { - await foo(); - return 42; -} -'''); - } - - test_addAsync_returnFuture_noType() async { - errorFilter = (AnalysisError error) { - return error.errorCode == - CompileTimeErrorCode.BUILT_IN_IDENTIFIER_AS_TYPE; - }; - await resolveTestUnit(''' -foo() {} -main() { - await foo(); - return 42; -} -'''); - await assertHasFix(DartFixKind.ADD_ASYNC, ''' -foo() {} -main() async { - await foo(); - return 42; -} -'''); - } - - test_addExplicitCast_assignment_general() async { - await resolveTestUnit(''' -f(A a) { - B b; - b = a; -} -class A {} -class B {} -'''); - await assertHasFix(DartFixKind.ADD_EXPLICIT_CAST, ''' -f(A a) { - B b; - b = a as B; -} -class A {} -class B {} -'''); - } - - test_addExplicitCast_assignment_general_all() async { - await resolveTestUnit(''' -f(A a) { - B b, b2; - b = a; - b2 = a; -} -class A {} -class B {} -'''); - await assertHasFixAllFix(StaticTypeWarningCode.INVALID_ASSIGNMENT, - DartFixKind.ADD_EXPLICIT_CAST, ''' -f(A a) { - B b, b2; - b = a as B; - b2 = a as B; -} -class A {} -class B {} -'''); - } - - test_addExplicitCast_assignment_list() async { - await resolveTestUnit(''' -f(List<A> a) { - List<B> b; - b = a.where((e) => e is B).toList(); -} -class A {} -class B {} -'''); - await assertHasFix(DartFixKind.ADD_EXPLICIT_CAST, ''' -f(List<A> a) { - List<B> b; - b = a.where((e) => e is B).cast<B>().toList(); -} -class A {} -class B {} -'''); - } - - test_addExplicitCast_assignment_list_all() async { - await resolveTestUnit(''' -f(List<A> a) { - List<B> b, b2; - b = a.where((e) => e is B).toList(); - b2 = a.where((e) => e is B).toList(); -} -class A {} -class B {} -'''); - await assertHasFixAllFix(StaticTypeWarningCode.INVALID_ASSIGNMENT, - DartFixKind.ADD_EXPLICIT_CAST, ''' -f(List<A> a) { - List<B> b, b2; - b = a.where((e) => e is B).cast<B>().toList(); - b2 = a.where((e) => e is B).cast<B>().toList(); -} -class A {} -class B {} -'''); - } - - test_addExplicitCast_assignment_map() async { - await resolveTestUnit(''' -f(Map<A, B> a) { - Map<B, A> b; - b = a; -} -class A {} -class B {} -'''); - await assertHasFix(DartFixKind.ADD_EXPLICIT_CAST, ''' -f(Map<A, B> a) { - Map<B, A> b; - b = a.cast<B, A>(); -} -class A {} -class B {} -'''); - } - - test_addExplicitCast_assignment_map_all() async { - await resolveTestUnit(''' -f(Map<A, B> a) { - Map<B, A> b, b2; - b = a; - b2 = a; -} -class A {} -class B {} -'''); - await assertHasFixAllFix(StaticTypeWarningCode.INVALID_ASSIGNMENT, - DartFixKind.ADD_EXPLICIT_CAST, ''' -f(Map<A, B> a) { - Map<B, A> b, b2; - b = a.cast<B, A>(); - b2 = a.cast<B, A>(); -} -class A {} -class B {} -'''); - } - - test_addExplicitCast_assignment_needsParens() async { - await resolveTestUnit(''' -f(A a) { - B b; - b = a..m(); -} -class A { - int m() => 0; -} -class B {} -'''); - await assertHasFix(DartFixKind.ADD_EXPLICIT_CAST, ''' -f(A a) { - B b; - b = (a..m()) as B; -} -class A { - int m() => 0; -} -class B {} -'''); - } - - test_addExplicitCast_assignment_needsParens_all() async { - await resolveTestUnit(''' -f(A a) { - B b, b2; - b = a..m(); - b2 = a..m(); -} -class A { - int m() => 0; -} -class B {} -'''); - await assertHasFixAllFix(StaticTypeWarningCode.INVALID_ASSIGNMENT, - DartFixKind.ADD_EXPLICIT_CAST, ''' -f(A a) { - B b, b2; - b = (a..m()) as B; - b2 = (a..m()) as B; -} -class A { - int m() => 0; -} -class B {} -'''); - } - - test_addExplicitCast_assignment_set() async { - await resolveTestUnit(''' -f(Set<A> a) { - Set<B> b; - b = a; -} -class A {} -class B {} -'''); - await assertHasFix(DartFixKind.ADD_EXPLICIT_CAST, ''' -f(Set<A> a) { - Set<B> b; - b = a.cast<B>(); -} -class A {} -class B {} -'''); - } - - test_addExplicitCast_assignment_set_all() async { - await resolveTestUnit(''' -f(Set<A> a) { - Set<B> b, b2; - b = a; - b2 = a; -} -class A {} -class B {} -'''); - await assertHasFixAllFix(StaticTypeWarningCode.INVALID_ASSIGNMENT, - DartFixKind.ADD_EXPLICIT_CAST, ''' -f(Set<A> a) { - Set<B> b, b2; - b = a.cast<B>(); - b2 = a.cast<B>(); -} -class A {} -class B {} -'''); - } - - test_addExplicitCast_BAD_as() async { - await resolveTestUnit(''' -f(A a) { - C c = a as B; -} -class A {} -class B {} -class C {} -'''); - await assertNoFix(DartFixKind.ADD_EXPLICIT_CAST); - } - - test_addExplicitCast_BAD_cast() async { - await resolveTestUnit(''' -f(List<A> a) { - List<B> b = a.cast<A>(); -} -class A {} -class B {} -'''); - await assertNoFix(DartFixKind.ADD_EXPLICIT_CAST); - } - - test_addExplicitCast_declaration_general() async { - await resolveTestUnit(''' -f(A a) { - B b = a; -} -class A {} -class B {} -'''); - await assertHasFix(DartFixKind.ADD_EXPLICIT_CAST, ''' -f(A a) { - B b = a as B; -} -class A {} -class B {} -'''); - } - - test_addExplicitCast_declaration_general_all() async { - await resolveTestUnit(''' -f(A a) { - B b = a; - B b2 = a; -} -class A {} -class B {} -'''); - await assertHasFixAllFix(StaticTypeWarningCode.INVALID_ASSIGNMENT, - DartFixKind.ADD_EXPLICIT_CAST, ''' -f(A a) { - B b = a as B; - B b2 = a as B; -} -class A {} -class B {} -'''); - } - - test_addExplicitCast_declaration_list() async { - await resolveTestUnit(''' -f(List<A> a) { - List<B> b = a.where((e) => e is B).toList(); -} -class A {} -class B {} -'''); - await assertHasFix(DartFixKind.ADD_EXPLICIT_CAST, ''' -f(List<A> a) { - List<B> b = a.where((e) => e is B).cast<B>().toList(); -} -class A {} -class B {} -'''); - } - - test_addExplicitCast_declaration_list_all() async { - await resolveTestUnit(''' -f(List<A> a) { - List<B> b = a.where((e) => e is B).toList(); - List<B> b2 = a.where((e) => e is B).toList(); -} -class A {} -class B {} -'''); - await assertHasFixAllFix(StaticTypeWarningCode.INVALID_ASSIGNMENT, - DartFixKind.ADD_EXPLICIT_CAST, ''' -f(List<A> a) { - List<B> b = a.where((e) => e is B).cast<B>().toList(); - List<B> b2 = a.where((e) => e is B).cast<B>().toList(); -} -class A {} -class B {} -'''); - } - - test_addExplicitCast_declaration_map() async { - await resolveTestUnit(''' -f(Map<A, B> a) { - Map<B, A> b = a; -} -class A {} -class B {} -'''); - await assertHasFix(DartFixKind.ADD_EXPLICIT_CAST, ''' -f(Map<A, B> a) { - Map<B, A> b = a.cast<B, A>(); -} -class A {} -class B {} -'''); - } - - test_addExplicitCast_declaration_map_all() async { - await resolveTestUnit(''' -f(Map<A, B> a) { - Map<B, A> b = a; - Map<B, A> b2 = a; -} -class A {} -class B {} -'''); - await assertHasFixAllFix(StaticTypeWarningCode.INVALID_ASSIGNMENT, - DartFixKind.ADD_EXPLICIT_CAST, ''' -f(Map<A, B> a) { - Map<B, A> b = a.cast<B, A>(); - Map<B, A> b2 = a.cast<B, A>(); -} -class A {} -class B {} -'''); - } - - test_addExplicitCast_declaration_needsParens() async { - await resolveTestUnit(''' -f(A a) { - B b = a..m(); -} -class A { - int m() => 0; -} -class B {} -'''); - await assertHasFix(DartFixKind.ADD_EXPLICIT_CAST, ''' -f(A a) { - B b = (a..m()) as B; -} -class A { - int m() => 0; -} -class B {} -'''); - } - - test_addExplicitCast_declaration_needsParens_all() async { - await resolveTestUnit(''' -f(A a) { - B b = a..m(); - B b2 = a..m(); -} -class A { - int m() => 0; -} -class B {} -'''); - await assertHasFixAllFix(StaticTypeWarningCode.INVALID_ASSIGNMENT, - DartFixKind.ADD_EXPLICIT_CAST, ''' -f(A a) { - B b = (a..m()) as B; - B b2 = (a..m()) as B; -} -class A { - int m() => 0; -} -class B {} -'''); - } - - test_addExplicitCast_declaration_set() async { - await resolveTestUnit(''' -f(Set<A> a) { - Set<B> b = a; -} -class A {} -class B {} -'''); - await assertHasFix(DartFixKind.ADD_EXPLICIT_CAST, ''' -f(Set<A> a) { - Set<B> b = a.cast<B>(); -} -class A {} -class B {} -'''); - } - - test_addExplicitCast_declaration_set_all() async { - await resolveTestUnit(''' -f(Set<A> a) { - Set<B> b = a; - Set<B> b2 = a; -} -class A {} -class B {} -'''); - await assertHasFixAllFix(StaticTypeWarningCode.INVALID_ASSIGNMENT, - DartFixKind.ADD_EXPLICIT_CAST, ''' -f(Set<A> a) { - Set<B> b = a.cast<B>(); - Set<B> b2 = a.cast<B>(); -} -class A {} -class B {} -'''); - } - - test_addFieldFormalParameters_flutter() async { - addFlutterPackage(); - await resolveTestUnit(''' -import 'package:flutter/widgets.dart'; - -class MyWidget extends StatelessWidget { - final int a; - final int b; - final int c; - - MyWidget({Key key, this.a}) : super(key: key); -} -'''); - await assertHasFix(DartFixKind.ADD_FIELD_FORMAL_PARAMETERS, ''' -import 'package:flutter/widgets.dart'; - -class MyWidget extends StatelessWidget { - final int a; - final int b; - final int c; - - MyWidget({Key key, this.a, this.b, this.c}) : super(key: key); -} -'''); - } - - test_addFieldFormalParameters_hasRequiredParameter() async { - await resolveTestUnit(''' -class Test { - final int a; - final int b; - final int c; - Test(this.a); -} -'''); - await assertHasFix(DartFixKind.ADD_FIELD_FORMAL_PARAMETERS, ''' -class Test { - final int a; - final int b; - final int c; - Test(this.a, this.b, this.c); -} -'''); - } - - test_addFieldFormalParameters_noParameters() async { - await resolveTestUnit(''' -class Test { - final int a; - final int b; - final int c; - Test(); -} -'''); - await assertHasFix(DartFixKind.ADD_FIELD_FORMAL_PARAMETERS, ''' -class Test { - final int a; - final int b; - final int c; - Test(this.a, this.b, this.c); -} -'''); - } - - test_addFieldFormalParameters_noRequiredParameter() async { - await resolveTestUnit(''' -class Test { - final int a; - final int b; - final int c; - Test([this.c]); -} -'''); - await assertHasFix(DartFixKind.ADD_FIELD_FORMAL_PARAMETERS, ''' -class Test { - final int a; - final int b; - final int c; - Test(this.a, this.b, [this.c]); -} -'''); - } - - test_addFieldFormalParameters_notAllFinal() async { - await resolveTestUnit(''' -class Test { - final int a; - int b; - final int c; - Test(); -} -'''); - await assertHasFix(DartFixKind.ADD_FIELD_FORMAL_PARAMETERS, ''' -class Test { - final int a; - int b; - final int c; - Test(this.a, this.c); -} -'''); - } - - test_addMissingParameter_constructor_named_required_hasOne() async { - await resolveTestUnit(''' -class A { - A.named(int a) {} -} -main() { - new A.named(1, 2.0); -} -'''); - await assertHasFix(DartFixKind.ADD_MISSING_PARAMETER_REQUIRED, ''' -class A { - A.named(int a, double d) {} -} -main() { - new A.named(1, 2.0); -} -'''); - } - - test_addMissingParameter_constructor_unnamed_required_hasOne() async { - await resolveTestUnit(''' -class A { - A(int a) {} -} -main() { - new A(1, 2.0); -} -'''); - await assertHasFix(DartFixKind.ADD_MISSING_PARAMETER_REQUIRED, ''' -class A { - A(int a, double d) {} -} -main() { - new A(1, 2.0); -} -'''); - } - - test_addMissingParameter_function_positional_hasNamed() async { - await resolveTestUnit(''' -test({int a}) {} -main() { - test(1); -} -'''); - await assertNoFix(DartFixKind.ADD_MISSING_PARAMETER_POSITIONAL); - } - - test_addMissingParameter_function_positional_hasZero() async { - await resolveTestUnit(''' -test() {} -main() { - test(1); -} -'''); - await assertHasFix(DartFixKind.ADD_MISSING_PARAMETER_POSITIONAL, ''' -test([int i]) {} -main() { - test(1); -} -'''); - } - - test_addMissingParameter_function_required_hasNamed() async { - await resolveTestUnit(''' -test({int a}) {} -main() { - test(1); -} -'''); - await assertHasFix(DartFixKind.ADD_MISSING_PARAMETER_REQUIRED, ''' -test(int i, {int a}) {} -main() { - test(1); -} -'''); - } - - test_addMissingParameter_function_required_hasOne() async { - await resolveTestUnit(''' -test(int a) {} -main() { - test(1, 2.0); -} -'''); - await assertHasFix(DartFixKind.ADD_MISSING_PARAMETER_REQUIRED, ''' -test(int a, double d) {} -main() { - test(1, 2.0); -} -'''); - } - - test_addMissingParameter_function_required_hasZero() async { - await resolveTestUnit(''' -test() {} -main() { - test(1); -} -'''); - await assertHasFix(DartFixKind.ADD_MISSING_PARAMETER_REQUIRED, ''' -test(int i) {} -main() { - test(1); -} -'''); - } - - test_addMissingParameter_method_positional_hasOne() async { - await resolveTestUnit(''' -class A { - test(int a) {} - main() { - test(1, 2.0); - } -} -'''); - await assertHasFix(DartFixKind.ADD_MISSING_PARAMETER_POSITIONAL, ''' -class A { - test(int a, [double d]) {} - main() { - test(1, 2.0); - } -} -'''); - } - - test_addMissingParameter_method_required_hasOne() async { - await resolveTestUnit(''' -class A { - test(int a) {} - main() { - test(1, 2.0); - } -} -'''); - await assertHasFix(DartFixKind.ADD_MISSING_PARAMETER_REQUIRED, ''' -class A { - test(int a, double d) {} - main() { - test(1, 2.0); - } -} -'''); - } - - test_addMissingParameter_method_required_hasZero() async { - await resolveTestUnit(''' -class A { - test() {} - main() { - test(1); - } -} -'''); - await assertHasFix(DartFixKind.ADD_MISSING_PARAMETER_REQUIRED, ''' -class A { - test(int i) {} - main() { - test(1); - } -} -'''); - } - - test_addMissingParameterNamed_constructor_hasNamed() async { - await resolveTestUnit(''' -class A { - A(int a, {int b}) {} -} - -main() { - new A(1, b: 2, named: 3.0); -} -'''); - await assertHasFix(DartFixKind.ADD_MISSING_PARAMETER_NAMED, ''' -class A { - A(int a, {int b, double named}) {} -} - -main() { - new A(1, b: 2, named: 3.0); -} -'''); - } - - test_addMissingParameterNamed_constructor_hasRequired() async { - await resolveTestUnit(''' -class A { - A(int a) {} -} - -main() { - new A(1, named: 2.0); -} -'''); - await assertHasFix(DartFixKind.ADD_MISSING_PARAMETER_NAMED, ''' -class A { - A(int a, {double named}) {} -} - -main() { - new A(1, named: 2.0); -} -'''); - } - - test_addMissingParameterNamed_constructor_noParameters() async { - await resolveTestUnit(''' -class A { - A() {} -} - -main() { - new A(named: 42); -} -'''); - await assertHasFix(DartFixKind.ADD_MISSING_PARAMETER_NAMED, ''' -class A { - A({int named}) {} -} - -main() { - new A(named: 42); -} -'''); - } - - test_addMissingParameterNamed_constructor_noParameters_named() async { - await resolveTestUnit(''' -class A { - A.aaa() {} -} - -main() { - new A.aaa(named: 42); -} -'''); - await assertHasFix(DartFixKind.ADD_MISSING_PARAMETER_NAMED, ''' -class A { - A.aaa({int named}) {} -} - -main() { - new A.aaa(named: 42); -} -'''); - } - - test_addMissingParameterNamed_function_hasNamed() async { - await resolveTestUnit(''' -test(int a, {int b: 0}) {} - -main() { - test(1, b: 2, named: 3.0); -} -'''); - await assertHasFix(DartFixKind.ADD_MISSING_PARAMETER_NAMED, ''' -test(int a, {int b: 0, double named}) {} - -main() { - test(1, b: 2, named: 3.0); -} -'''); - } - - test_addMissingParameterNamed_function_hasRequired() async { - await resolveTestUnit(''' -test(int a) {} - -main() { - test(1, named: 2.0); -} -'''); - await assertHasFix(DartFixKind.ADD_MISSING_PARAMETER_NAMED, ''' -test(int a, {double named}) {} - -main() { - test(1, named: 2.0); -} -'''); - } - - test_addMissingParameterNamed_function_noParameters() async { - await resolveTestUnit(''' -test() {} - -main() { - test(named: 42); -} -'''); - await assertHasFix(DartFixKind.ADD_MISSING_PARAMETER_NAMED, ''' -test({int named}) {} - -main() { - test(named: 42); -} -'''); - } - - test_addMissingParameterNamed_method_hasNamed() async { - await resolveTestUnit(''' -class A { - test(int a, {int b: 0}) {} - - main() { - test(1, b: 2, named: 3.0); - } -} -'''); - await assertHasFix(DartFixKind.ADD_MISSING_PARAMETER_NAMED, ''' -class A { - test(int a, {int b: 0, double named}) {} - - main() { - test(1, b: 2, named: 3.0); - } -} -'''); - } - - test_addMissingParameterNamed_method_hasOptionalPositional() async { - await resolveTestUnit(''' -class A { - test(int a, [int b]) {} - - main() { - test(1, 2, named: 3.0); - } -} -'''); - await assertNoFix(DartFixKind.ADD_MISSING_PARAMETER_NAMED); - } - - test_addMissingParameterNamed_method_hasRequired() async { - await resolveTestUnit(''' -class A { - test(int a) {} - - main() { - test(1, named: 2.0); - } -} -'''); - await assertHasFix(DartFixKind.ADD_MISSING_PARAMETER_NAMED, ''' -class A { - test(int a, {double named}) {} - - main() { - test(1, named: 2.0); - } -} -'''); - } - - test_addMissingParameterNamed_method_noParameters() async { - await resolveTestUnit(''' -class A { - test() {} - - main() { - test(named: 42); - } -} -'''); - await assertHasFix(DartFixKind.ADD_MISSING_PARAMETER_NAMED, ''' -class A { - test({int named}) {} - - main() { - test(named: 42); - } -} -'''); - } - - test_addMissingRequiredArg_cons_flutter_children() async { - addFlutterPackage(); - _addMetaPackageSource(); - - await resolveTestUnit(''' -import 'package:flutter/widgets.dart'; -import 'package:meta/meta.dart'; - -class MyWidget extends Widget { - MyWidget({@required List<Widget> children}); -} - -build() { - return new MyWidget(); -} -'''); - - await assertHasFix(DartFixKind.ADD_MISSING_REQUIRED_ARGUMENT, ''' -import 'package:flutter/widgets.dart'; -import 'package:meta/meta.dart'; - -class MyWidget extends Widget { - MyWidget({@required List<Widget> children}); -} - -build() { - return new MyWidget(children: <Widget>[],); -} -'''); - } - - test_addMissingRequiredArg_cons_flutter_hasTrailingComma() async { - addFlutterPackage(); - _addMetaPackageSource(); - - await resolveTestUnit(''' -import 'package:flutter/widgets.dart'; -import 'package:meta/meta.dart'; - -class MyWidget extends Widget { - MyWidget({@required int a, @required int b}); -} - -build() { - return new MyWidget(a: 1,); -} -'''); - - await assertHasFix(DartFixKind.ADD_MISSING_REQUIRED_ARGUMENT, ''' -import 'package:flutter/widgets.dart'; -import 'package:meta/meta.dart'; - -class MyWidget extends Widget { - MyWidget({@required int a, @required int b}); -} - -build() { - return new MyWidget(a: 1, b: null,); -} -'''); - } - - test_addMissingRequiredArg_cons_single() async { - _addMetaPackageSource(); - addSource('/project/libA.dart', r''' -library libA; -import 'package:meta/meta.dart'; - -class A { - A({@required int a}) {} -} -'''); - - await resolveTestUnit(''' -import 'libA.dart'; - -main() { - A a = new A(); -} -'''); - await assertHasFix(DartFixKind.ADD_MISSING_REQUIRED_ARGUMENT, ''' -import 'libA.dart'; - -main() { - A a = new A(a: null); -} -'''); - } - - test_addMissingRequiredArg_cons_single_closure() async { - _addMetaPackageSource(); - - addSource('/project/libA.dart', r''' -library libA; -import 'package:meta/meta.dart'; - -typedef void VoidCallback(); - -class A { - A({@required VoidCallback onPressed}) {} -} -'''); - - await resolveTestUnit(''' -import 'libA.dart'; - -main() { - A a = new A(); -} -'''); - await assertHasFix(DartFixKind.ADD_MISSING_REQUIRED_ARGUMENT, ''' -import 'libA.dart'; - -main() { - A a = new A(onPressed: () {}); -} -'''); - } - - test_addMissingRequiredArg_cons_single_closure_2() async { - _addMetaPackageSource(); - - addSource('/project/libA.dart', r''' -library libA; -import 'package:meta/meta.dart'; - -typedef void Callback(e); - -class A { - A({@required Callback callback}) {} -} -'''); - - await resolveTestUnit(''' -import 'libA.dart'; - -main() { - A a = new A(); -} -'''); - await assertHasFix(DartFixKind.ADD_MISSING_REQUIRED_ARGUMENT, ''' -import 'libA.dart'; - -main() { - A a = new A(callback: (e) {}); -} -'''); - } - - test_addMissingRequiredArg_cons_single_closure_3() async { - _addMetaPackageSource(); - - addSource('/project/libA.dart', r''' -library libA; -import 'package:meta/meta.dart'; - -typedef void Callback(a,b,c); - -class A { - A({@required Callback callback}) {} -} -'''); - - await resolveTestUnit(''' -import 'libA.dart'; - -main() { - A a = new A(); -} -'''); - await assertHasFix(DartFixKind.ADD_MISSING_REQUIRED_ARGUMENT, ''' -import 'libA.dart'; - -main() { - A a = new A(callback: (a, b, c) {}); -} -'''); - } - - test_addMissingRequiredArg_cons_single_closure_4() async { - _addMetaPackageSource(); - - addSource('/project/libA.dart', r''' -library libA; -import 'package:meta/meta.dart'; - -typedef int Callback(int a, String b,c); - -class A { - A({@required Callback callback}) {} -} -'''); - - await resolveTestUnit(''' -import 'libA.dart'; - -main() { - A a = new A(); -} -'''); - await assertHasFix(DartFixKind.ADD_MISSING_REQUIRED_ARGUMENT, ''' -import 'libA.dart'; - -main() { - A a = new A(callback: (int a, String b, c) {}); -} -'''); - } - - test_addMissingRequiredArg_cons_single_list() async { - _addMetaPackageSource(); - - addSource('/project/libA.dart', r''' -library libA; -import 'package:meta/meta.dart'; - -class A { - A({@required List<String> names}) {} -} -'''); - - await resolveTestUnit(''' -import 'libA.dart'; - -main() { - A a = new A(); -} -'''); - await assertHasFix(DartFixKind.ADD_MISSING_REQUIRED_ARGUMENT, ''' -import 'libA.dart'; - -main() { - A a = new A(names: <String>[]); -} -'''); - } - - test_addMissingRequiredArg_multiple() async { - _addMetaPackageSource(); - - await resolveTestUnit(''' -import 'package:meta/meta.dart'; - -test({@required int a, @required int bcd}) {} -main() { - test(a: 3); -} -'''); - await assertHasFix(DartFixKind.ADD_MISSING_REQUIRED_ARGUMENT, ''' -import 'package:meta/meta.dart'; - -test({@required int a, @required int bcd}) {} -main() { - test(a: 3, bcd: null); -} -'''); - } - - test_addMissingRequiredArg_multiple_2() async { - _addMetaPackageSource(); - - await resolveTestUnit(''' -import 'package:meta/meta.dart'; - -test({@required int a, @required int bcd}) {} -main() { - test(); -} -'''); - - // For now we expect one error per missing arg (dartbug.com/28830). - List<AnalysisError> errors = await _computeErrors(); - expect(errors, hasLength(2)); - - List<AnalysisError> filteredErrors = errors - .where((e) => e.message == "The parameter 'a' is required.") - .toList(); - expect(filteredErrors, hasLength(1)); - - List<Fix> fixes = await _computeFixes(filteredErrors.first); - - List<Fix> filteredFixes = fixes - .where((fix) => fix.change.message == "Add required argument 'a'") - .toList(); - expect(filteredFixes, hasLength(1)); - change = filteredFixes.first.change; - resultCode = SourceEdit.applySequence(testCode, change.edits[0].edits); - // verify - expect(resultCode, ''' -import 'package:meta/meta.dart'; - -test({@required int a, @required int bcd}) {} -main() { - test(a: null); -} -'''); - } - - test_addMissingRequiredArg_single() async { - _addMetaPackageSource(); - - await resolveTestUnit(''' -import 'package:meta/meta.dart'; - -test({@required int abc}) {} -main() { - test(); -} -'''); - await assertHasFix(DartFixKind.ADD_MISSING_REQUIRED_ARGUMENT, ''' -import 'package:meta/meta.dart'; - -test({@required int abc}) {} -main() { - test(abc: null); -} -'''); - } - - test_addMissingRequiredArg_single_normal() async { - _addMetaPackageSource(); - - await resolveTestUnit(''' -import 'package:meta/meta.dart'; - -test(String x, {@required int abc}) {} -main() { - test("foo"); -} -'''); - await assertHasFix(DartFixKind.ADD_MISSING_REQUIRED_ARGUMENT, ''' -import 'package:meta/meta.dart'; - -test(String x, {@required int abc}) {} -main() { - test("foo", abc: null); -} -'''); - } - - test_addMissingRequiredArg_single_with_details() async { - _addMetaPackageSource(); - - await resolveTestUnit(''' -import 'package:meta/meta.dart'; - -test({@Required("Really who doesn't need an abc?") int abc}) {} -main() { - test(); -} -'''); - await assertHasFix(DartFixKind.ADD_MISSING_REQUIRED_ARGUMENT, ''' -import 'package:meta/meta.dart'; - -test({@Required("Really who doesn't need an abc?") int abc}) {} -main() { - test(abc: null); -} -'''); - } - - test_addStatic_multipleFields() async { - await resolveTestUnit(''' -class C { - const int x = 0, y = 0; -} -'''); - await assertHasFix(DartFixKind.ADD_STATIC, ''' -class C { - static const int x = 0, y = 0; -} -'''); - } - - test_addStatic_oneField() async { - await resolveTestUnit(''' -class C { - const int x = 0; -} -'''); - await assertHasFix(DartFixKind.ADD_STATIC, ''' -class C { - static const int x = 0; -} -'''); - } - - test_boolean() async { - await resolveTestUnit(''' -main() { - boolean v; -} -'''); - await assertHasFix(DartFixKind.REPLACE_BOOLEAN_WITH_BOOL, ''' -main() { - bool v; -} -'''); - } - - test_boolean_all() async { - await resolveTestUnit(''' -main() { - boolean v; - boolean w; -} -'''); - await assertHasFixAllFix(StaticWarningCode.UNDEFINED_CLASS_BOOLEAN, - DartFixKind.REPLACE_BOOLEAN_WITH_BOOL, ''' -main() { - bool v; - bool w; -} -'''); - } - - test_canBeNullAfterNullAware_chain() async { - await resolveTestUnit(''' -main(x) { - x?.a.b.c; -} -'''); - await assertHasFix(DartFixKind.REPLACE_WITH_NULL_AWARE, ''' -main(x) { - x?.a?.b?.c; -} -'''); - } - - test_canBeNullAfterNullAware_methodInvocation() async { - await resolveTestUnit(''' -main(x) { - x?.a.b(); -} -'''); - await assertHasFix(DartFixKind.REPLACE_WITH_NULL_AWARE, ''' -main(x) { - x?.a?.b(); -} -'''); - } - - test_canBeNullAfterNullAware_propertyAccess() async { - await resolveTestUnit(''' -main(x) { - x?.a().b; -} -'''); - await assertHasFix(DartFixKind.REPLACE_WITH_NULL_AWARE, ''' -main(x) { - x?.a()?.b; -} -'''); - } - - test_changeToStaticAccess_method() async { - await resolveTestUnit(''' -class A { - static foo() {} -} -main(A a) { - a.foo(); -} -'''); - await assertHasFix(DartFixKind.CHANGE_TO_STATIC_ACCESS, ''' -class A { - static foo() {} -} -main(A a) { - A.foo(); -} -'''); - } - - test_changeToStaticAccess_method_importType() async { - addSource('/project/libA.dart', r''' -library libA; -class A { - static foo() {} -} -'''); - addSource('/project/libB.dart', r''' -library libB; -import 'libA.dart'; -class B extends A {} -'''); - await resolveTestUnit(''' -import 'libB.dart'; -main(B b) { - b.foo(); -} -'''); - await assertHasFix(DartFixKind.CHANGE_TO_STATIC_ACCESS, ''' -import 'libA.dart'; -import 'libB.dart'; -main(B b) { - A.foo(); -} -'''); - } - - test_changeToStaticAccess_method_prefixLibrary() async { - await resolveTestUnit(''' -import 'dart:async' as pref; -main(pref.Future f) { - f.wait([]); -} -'''); - await assertHasFix(DartFixKind.CHANGE_TO_STATIC_ACCESS, ''' -import 'dart:async' as pref; -main(pref.Future f) { - pref.Future.wait([]); -} -'''); - } - - test_changeToStaticAccess_property() async { - await resolveTestUnit(''' -class A { - static get foo => 42; -} -main(A a) { - a.foo; -} -'''); - await assertHasFix(DartFixKind.CHANGE_TO_STATIC_ACCESS, ''' -class A { - static get foo => 42; -} -main(A a) { - A.foo; -} -'''); - } - - test_changeToStaticAccess_property_importType() async { - addSource('/project/libA.dart', r''' -library libA; -class A { - static get foo => null; -} -'''); - addSource('/project/libB.dart', r''' -library libB; -import 'libA.dart'; -class B extends A {} -'''); - await resolveTestUnit(''' -import 'libB.dart'; -main(B b) { - b.foo; -} -'''); - await assertHasFix(DartFixKind.CHANGE_TO_STATIC_ACCESS, ''' -import 'libA.dart'; -import 'libB.dart'; -main(B b) { - A.foo; -} -'''); - } - - test_changeTypeAnnotation_BAD_multipleVariables() async { - await resolveTestUnit(''' -main() { - String a, b = 42; -} -'''); - await assertNoFix(DartFixKind.CHANGE_TYPE_ANNOTATION); - } - - test_changeTypeAnnotation_BAD_notVariableDeclaration() async { - await resolveTestUnit(''' -main() { - String v; - v = 42; -} -'''); - await assertNoFix(DartFixKind.CHANGE_TYPE_ANNOTATION); - } - - test_changeTypeAnnotation_OK_generic() async { - await resolveTestUnit(''' -main() { - String v = <int>[]; -} -'''); - await assertHasFix(DartFixKind.CHANGE_TYPE_ANNOTATION, ''' -main() { - List<int> v = <int>[]; -} -'''); - } - - test_changeTypeAnnotation_OK_simple() async { - await resolveTestUnit(''' -main() { - String v = 'abc'.length; -} -'''); - await assertHasFix(DartFixKind.CHANGE_TYPE_ANNOTATION, ''' -main() { - int v = 'abc'.length; -} -'''); - } - - test_convertToNamedArguments_BAD_ambiguous() async { - await resolveTestUnit(''' -class A { - A({int a, int b}); -} - -main() { - new A(1, 2); -} -'''); - await assertNoFix(DartFixKind.CONVERT_TO_NAMED_ARGUMENTS); - } - - test_convertToNamedArguments_BAD_noCompatibleParameter() async { - await resolveTestUnit(''' -class A { - A({String a}); -} - -main() { - new A(1); -} -'''); - await assertNoFix(DartFixKind.CONVERT_TO_NAMED_ARGUMENTS); - } - - test_convertToNamedArguments_OK_instanceCreation() async { - await resolveTestUnit(''' -class A { - A({int a, double b}); -} - -main() { - new A(1.2, 3); -} -'''); - await assertHasFix(DartFixKind.CONVERT_TO_NAMED_ARGUMENTS, ''' -class A { - A({int a, double b}); -} - -main() { - new A(b: 1.2, a: 3); -} -'''); - } - - test_convertToNamedArguments_OK_instanceCreation_hasPositional() async { - await resolveTestUnit(''' -class A { - A(int a, {int b}); -} - -main() { - new A(1, 2); -} -'''); - await assertHasFix(DartFixKind.CONVERT_TO_NAMED_ARGUMENTS, ''' -class A { - A(int a, {int b}); -} - -main() { - new A(1, b: 2); -} -'''); - } - - test_convertToNamedArguments_OK_methodInvocation() async { - await resolveTestUnit(''' -class C { - void foo({int a}) {} -} - -main(C c) { - c.foo(1); -} -'''); - await assertHasFix(DartFixKind.CONVERT_TO_NAMED_ARGUMENTS, ''' -class C { - void foo({int a}) {} -} - -main(C c) { - c.foo(a: 1); -} -'''); - } - - test_createClass() async { - await resolveTestUnit(''' -main() { - Test v = null; -} -'''); - await assertHasFix(DartFixKind.CREATE_CLASS, ''' -main() { - Test v = null; -} - -class Test { -} -'''); - _assertLinkedGroup(change.linkedEditGroups[0], ['Test v =', 'Test {']); - } - - test_createClass_BAD_hasUnresolvedPrefix() async { - await resolveTestUnit(''' -main() { - prefix.Test v = null; -} -'''); - await assertNoFix(DartFixKind.CREATE_CLASS); - } - - test_createClass_inLibraryOfPrefix() async { - String libCode = r''' -library my.lib; - -class A {} -'''; - addSource('/project/lib.dart', libCode); - await resolveTestUnit(''' -import 'lib.dart' as lib; - -main() { - lib.A a = null; - lib.Test t = null; -} -'''); - AnalysisError error = await _findErrorToFix(); - fix = await _assertHasFix(DartFixKind.CREATE_CLASS, error); - change = fix.change; - // apply to "lib.dart" - List<SourceFileEdit> fileEdits = change.edits; - expect(fileEdits, hasLength(1)); - SourceFileEdit fileEdit = change.edits[0]; - expect(fileEdit.file, convertPath('/project/lib.dart')); - expect(SourceEdit.applySequence(libCode, fileEdit.edits), r''' -library my.lib; - -class A {} - -class Test { -} -'''); - expect(change.linkedEditGroups, hasLength(1)); - } - - test_createClass_innerLocalFunction() async { - await resolveTestUnit(''' -f() { - g() { - Test v = null; - } -} -'''); - await assertHasFix(DartFixKind.CREATE_CLASS, ''' -f() { - g() { - Test v = null; - } -} - -class Test { -} -'''); - _assertLinkedGroup(change.linkedEditGroups[0], ['Test v =', 'Test {']); - } - - test_createClass_instanceCreation_withoutNew_fromFunction() async { - await resolveTestUnit(''' -main() { - Test (); -} -'''); - await assertHasFix(DartFixKind.CREATE_CLASS, ''' -main() { - Test (); -} - -class Test { -} -'''); - _assertLinkedGroup(change.linkedEditGroups[0], ['Test ()', 'Test {']); - } - - test_createClass_instanceCreation_withoutNew_fromMethod() async { - await resolveTestUnit(''' -class A { - main() { - Test (); - } -} -'''); - await assertHasFix(DartFixKind.CREATE_CLASS, ''' -class A { - main() { - Test (); - } -} - -class Test { -} -'''); - _assertLinkedGroup(change.linkedEditGroups[0], ['Test ()', 'Test {']); - } - - test_createClass_itemOfList() async { - await resolveTestUnit(''' -main() { - var a = [Test]; -} -'''); - await assertHasFix(DartFixKind.CREATE_CLASS, ''' -main() { - var a = [Test]; -} - -class Test { -} -'''); - _assertLinkedGroup(change.linkedEditGroups[0], ['Test];', 'Test {']); - } - - test_createClass_itemOfList_inAnnotation() async { - errorFilter = (AnalysisError error) { - return error.errorCode == StaticWarningCode.UNDEFINED_IDENTIFIER; - }; - await resolveTestUnit(''' -class MyAnnotation { - const MyAnnotation(a, b); -} -@MyAnnotation(int, const [Test]) -main() {} -'''); - await assertHasFix(DartFixKind.CREATE_CLASS, ''' -class MyAnnotation { - const MyAnnotation(a, b); -} -@MyAnnotation(int, const [Test]) -main() {} - -class Test { -} -'''); - _assertLinkedGroup(change.linkedEditGroups[0], ['Test])', 'Test {']); - } - - test_createConstructor_forFinalFields() async { - errorFilter = (AnalysisError error) { - return error.message.contains("'a'"); - }; - await resolveTestUnit(''' -class Test { - final int a; - final int b = 2; - final int c; -} -'''); - await assertHasFix(DartFixKind.CREATE_CONSTRUCTOR_FOR_FINAL_FIELDS, ''' -class Test { - final int a; - final int b = 2; - final int c; - - Test(this.a, this.c); -} -'''); - } - - test_createConstructor_forFinalFields_flutter() async { - addFlutterPackage(); - errorFilter = (AnalysisError error) { - return error.message.contains("'a'"); - }; - await resolveTestUnit(''' -import 'package:flutter/widgets.dart'; - -class MyWidget extends StatelessWidget { - final int a; - final int b = 2; - final int c; -} -'''); - await assertHasFix(DartFixKind.CREATE_CONSTRUCTOR_FOR_FINAL_FIELDS, ''' -import 'package:flutter/widgets.dart'; - -class MyWidget extends StatelessWidget { - final int a; - final int b = 2; - final int c; - - const MyWidget({Key key, this.a, this.c}) : super(key: key); -} -'''); - } - - test_createConstructor_forFinalFields_flutter_childLast() async { - addFlutterPackage(); - errorFilter = (AnalysisError error) { - return error.message.contains("'a'"); - }; - await resolveTestUnit(''' -import 'package:flutter/widgets.dart'; - -class MyWidget extends StatelessWidget { - final int a; - final Widget child; - final int b; -} -'''); - await assertHasFix(DartFixKind.CREATE_CONSTRUCTOR_FOR_FINAL_FIELDS, ''' -import 'package:flutter/widgets.dart'; - -class MyWidget extends StatelessWidget { - final int a; - final Widget child; - final int b; - - const MyWidget({Key key, this.a, this.b, this.child}) : super(key: key); -} -'''); - } - - test_createConstructor_forFinalFields_flutter_childrenLast() async { - addFlutterPackage(); - errorFilter = (AnalysisError error) { - return error.message.contains("'a'"); - }; - await resolveTestUnit(''' -import 'package:flutter/widgets.dart'; - -class MyWidget extends StatelessWidget { - final int a; - final List<Widget> children; - final int b; -} -'''); - await assertHasFix(DartFixKind.CREATE_CONSTRUCTOR_FOR_FINAL_FIELDS, ''' -import 'package:flutter/widgets.dart'; - -class MyWidget extends StatelessWidget { - final int a; - final List<Widget> children; - final int b; - - const MyWidget({Key key, this.a, this.b, this.children}) : super(key: key); -} -'''); - } - - test_createConstructor_insteadOfSyntheticDefault() async { - await resolveTestUnit(''' -class A { - int field; - - method() {} -} -main() { - new A(1, 2.0); -} -'''); - await assertHasFix(DartFixKind.CREATE_CONSTRUCTOR, ''' -class A { - int field; - - A(int i, double d); - - method() {} -} -main() { - new A(1, 2.0); -} -'''); - } - - test_createConstructor_named() async { - await resolveTestUnit(''' -class A { - method() {} -} -main() { - new A.named(1, 2.0); -} -'''); - await assertHasFix(DartFixKind.CREATE_CONSTRUCTOR, ''' -class A { - A.named(int i, double d); - - method() {} -} -main() { - new A.named(1, 2.0); -} -'''); - _assertLinkedGroup(change.linkedEditGroups[0], ['named(int ', 'named(1']); - } - - test_createConstructor_named_emptyClassBody() async { - await resolveTestUnit(''' -class A {} -main() { - new A.named(1); -} -'''); - await assertHasFix(DartFixKind.CREATE_CONSTRUCTOR, ''' -class A { - A.named(int i); -} -main() { - new A.named(1); -} -'''); - _assertLinkedGroup(change.linkedEditGroups[0], ['named(int ', 'named(1']); - } - - test_createConstructorForFinalFields_inTopLevelMethod() async { - await resolveTestUnit(''' -main() { - final int v; -} -'''); - await assertNoFix(DartFixKind.CREATE_CONSTRUCTOR_FOR_FINAL_FIELDS); - } - - test_createConstructorForFinalFields_topLevelField() async { - await resolveTestUnit(''' -final int v; -'''); - await assertNoFix(DartFixKind.CREATE_CONSTRUCTOR_FOR_FINAL_FIELDS); - } - - test_createConstructorSuperExplicit() async { - await resolveTestUnit(''' -class A { - A(bool p1, int p2, double p3, String p4, {p5}); -} -class B extends A { - B() {} -} -'''); - await assertHasFix(DartFixKind.ADD_SUPER_CONSTRUCTOR_INVOCATION, ''' -class A { - A(bool p1, int p2, double p3, String p4, {p5}); -} -class B extends A { - B() : super(false, 0, 0.0, '') {} -} -'''); - } - - test_createConstructorSuperExplicit_hasInitializers() async { - await resolveTestUnit(''' -class A { - A(int p); -} -class B extends A { - int field; - B() : field = 42 {} -} -'''); - await assertHasFix(DartFixKind.ADD_SUPER_CONSTRUCTOR_INVOCATION, ''' -class A { - A(int p); -} -class B extends A { - int field; - B() : field = 42, super(0) {} -} -'''); - } - - test_createConstructorSuperExplicit_named() async { - await resolveTestUnit(''' -class A { - A.named(int p); -} -class B extends A { - B() {} -} -'''); - await assertHasFix(DartFixKind.ADD_SUPER_CONSTRUCTOR_INVOCATION, ''' -class A { - A.named(int p); -} -class B extends A { - B() : super.named(0) {} -} -'''); - } - - test_createConstructorSuperExplicit_named_private() async { - await resolveTestUnit(''' -class A { - A._named(int p); -} -class B extends A { - B() {} -} -'''); - await assertNoFix(DartFixKind.ADD_SUPER_CONSTRUCTOR_INVOCATION); - } - - test_createConstructorSuperExplicit_typeArgument() async { - await resolveTestUnit(''' -class A<T> { - A(T p); -} -class B extends A<int> { - B(); -} -'''); - await assertHasFix(DartFixKind.ADD_SUPER_CONSTRUCTOR_INVOCATION, ''' -class A<T> { - A(T p); -} -class B extends A<int> { - B() : super(0); -} -'''); - } - - test_createConstructorSuperImplicit() async { - await resolveTestUnit(''' -class A { - A(p1, int p2, List<String> p3, [int p4]); -} -class B extends A { - int existingField; - - void existingMethod() {} -} -'''); - await assertHasFix(DartFixKind.CREATE_CONSTRUCTOR_SUPER, ''' -class A { - A(p1, int p2, List<String> p3, [int p4]); -} -class B extends A { - int existingField; - - B(p1, int p2, List<String> p3) : super(p1, p2, p3); - - void existingMethod() {} -} -'''); - } - - test_createConstructorSuperImplicit_fieldInitializer() async { - await resolveTestUnit(''' -class A { - int _field; - A(this._field); -} -class B extends A { - int existingField; - - void existingMethod() {} -} -'''); - await assertHasFix(DartFixKind.CREATE_CONSTRUCTOR_SUPER, ''' -class A { - int _field; - A(this._field); -} -class B extends A { - int existingField; - - B(int field) : super(field); - - void existingMethod() {} -} -'''); - } - - test_createConstructorSuperImplicit_importType() async { - addSource('/project/libA.dart', r''' -library libA; -class A {} -'''); - addSource('/project/libB.dart', r''' -library libB; -import 'libA.dart'; -class B { - B(A a); -} -'''); - await resolveTestUnit(''' -import 'libB.dart'; -class C extends B { -} -'''); - await assertHasFix(DartFixKind.CREATE_CONSTRUCTOR_SUPER, ''' -import 'libA.dart'; -import 'libB.dart'; -class C extends B { - C(A a) : super(a); -} -'''); - } - - test_createConstructorSuperImplicit_named() async { - await resolveTestUnit(''' -class A { - A.named(p1, int p2); -} -class B extends A { - int existingField; - - void existingMethod() {} -} -'''); - await assertHasFix(DartFixKind.CREATE_CONSTRUCTOR_SUPER, ''' -class A { - A.named(p1, int p2); -} -class B extends A { - int existingField; - - B.named(p1, int p2) : super.named(p1, p2); - - void existingMethod() {} -} -'''); - } - - test_createConstructorSuperImplicit_private() async { - await resolveTestUnit(''' -class A { - A._named(p); -} -class B extends A { -} -'''); - await assertNoFix(DartFixKind.CREATE_CONSTRUCTOR_SUPER); - } - - test_createConstructorSuperImplicit_typeArgument() async { - await resolveTestUnit(''' -class C<T> { - final T x; - C(this.x); -} -class D extends C<int> { -}'''); - await assertHasFix(DartFixKind.CREATE_CONSTRUCTOR_SUPER, ''' -class C<T> { - final T x; - C(this.x); -} -class D extends C<int> { - D(int x) : super(x); -}'''); - } - - test_createField_BAD_inEnum() async { - await resolveTestUnit(''' -enum MyEnum { - AAA, BBB -} -main() { - MyEnum.foo; -} -'''); - await assertNoFix(DartFixKind.CREATE_FIELD); - } - - test_createField_BAD_inSDK() async { - await resolveTestUnit(''' -main(List p) { - p.foo = 1; -} -'''); - await assertNoFix(DartFixKind.CREATE_FIELD); - } - - test_createField_getter_multiLevel() async { - await resolveTestUnit(''' -class A { -} -class B { - A a; -} -class C { - B b; -} -main(C c) { - int v = c.b.a.test; -} -'''); - await assertHasFix(DartFixKind.CREATE_FIELD, ''' -class A { - int test; -} -class B { - A a; -} -class C { - B b; -} -main(C c) { - int v = c.b.a.test; -} -'''); - } - - test_createField_getter_qualified_instance() async { - await resolveTestUnit(''' -class A { -} -main(A a) { - int v = a.test; -} -'''); - await assertHasFix(DartFixKind.CREATE_FIELD, ''' -class A { - int test; -} -main(A a) { - int v = a.test; -} -'''); - } - - test_createField_getter_qualified_instance_differentLibrary() async { - addSource('/project/other.dart', ''' -/** - * A comment to push the offset of the braces for the following class - * declaration past the end of the content of the test file. Used to catch an - * index out of bounds exception that occurs when using the test source instead - * of the target source to compute the location at which to insert the field. - */ -class A { -} -'''); - await resolveTestUnit(''' -import 'other.dart'; -main(A a) { - int v = a.test; -} -'''); - await assertHasFix( - DartFixKind.CREATE_FIELD, - ''' -/** - * A comment to push the offset of the braces for the following class - * declaration past the end of the content of the test file. Used to catch an - * index out of bounds exception that occurs when using the test source instead - * of the target source to compute the location at which to insert the field. - */ -class A { - int test; -} -''', - target: '/project/other.dart'); - } - - test_createField_getter_qualified_instance_dynamicType() async { - await resolveTestUnit(''' -class A { - B b; - void f(Object p) { - p == b.test; - } -} -class B { -} -'''); - await assertHasFix(DartFixKind.CREATE_FIELD, ''' -class A { - B b; - void f(Object p) { - p == b.test; - } -} -class B { - var test; -} -'''); - } - - test_createField_getter_qualified_propagatedType() async { - await resolveTestUnit(''' -class A { - A get self => this; -} -main() { - var a = new A(); - int v = a.self.test; -} -'''); - await assertHasFix(DartFixKind.CREATE_FIELD, ''' -class A { - int test; - - A get self => this; -} -main() { - var a = new A(); - int v = a.self.test; -} -'''); - } - - test_createField_getter_unqualified_instance_asInvocationArgument() async { - await resolveTestUnit(''' -class A { - main() { - f(test); - } -} -f(String s) {} -'''); - await assertHasFix(DartFixKind.CREATE_FIELD, ''' -class A { - String test; - - main() { - f(test); - } -} -f(String s) {} -'''); - } - - test_createField_getter_unqualified_instance_assignmentRhs() async { - await resolveTestUnit(''' -class A { - main() { - int v = test; - } -} -'''); - await assertHasFix(DartFixKind.CREATE_FIELD, ''' -class A { - int test; - - main() { - int v = test; - } -} -'''); - } - - test_createField_getter_unqualified_instance_asStatement() async { - await resolveTestUnit(''' -class A { - main() { - test; - } -} -'''); - await assertHasFix(DartFixKind.CREATE_FIELD, ''' -class A { - var test; - - main() { - test; - } -} -'''); - } - - test_createField_hint() async { - await resolveTestUnit(''' -class A { -} -main(A a) { - var x = a; - int v = x.test; -} -'''); - await assertHasFix(DartFixKind.CREATE_FIELD, ''' -class A { - int test; -} -main(A a) { - var x = a; - int v = x.test; -} -'''); - } - - test_createField_hint_setter() async { - await resolveTestUnit(''' -class A { -} -main(A a) { - var x = a; - x.test = 0; -} -'''); - await assertHasFix(DartFixKind.CREATE_FIELD, ''' -class A { - int test; -} -main(A a) { - var x = a; - x.test = 0; -} -'''); - } - - test_createField_importType() async { - addSource('/project/libA.dart', r''' -library libA; -class A {} -'''); - addSource('/project/libB.dart', r''' -library libB; -import 'libA.dart'; -A getA() => null; -'''); - await resolveTestUnit(''' -import 'libB.dart'; -class C { -} -main(C c) { - c.test = getA(); -} -'''); - await assertHasFix(DartFixKind.CREATE_FIELD, ''' -import 'libA.dart'; -import 'libB.dart'; -class C { - A test; -} -main(C c) { - c.test = getA(); -} -'''); - } - - test_createField_invalidInitializer_withoutType() async { - await resolveTestUnit(''' -class C { - C(this.text); -} -'''); - await assertHasFix(DartFixKind.CREATE_FIELD, ''' -class C { - var text; - - C(this.text); -} -'''); - } - - test_createField_invalidInitializer_withType() async { - await resolveTestUnit(''' -class C { - C(String this.text); -} -'''); - await assertHasFix(DartFixKind.CREATE_FIELD, ''' -class C { - String text; - - C(String this.text); -} -'''); - } - - test_createField_setter_generic_BAD() async { - await resolveTestUnit(''' -class A { -} -class B<T> { - List<T> items; - main(A a) { - a.test = items; - } -} -'''); - await assertHasFix(DartFixKind.CREATE_FIELD, ''' -class A { - List test; -} -class B<T> { - List<T> items; - main(A a) { - a.test = items; - } -} -'''); - } - - test_createField_setter_generic_OK_local() async { - await resolveTestUnit(''' -class A<T> { - List<T> items; - - main(A a) { - test = items; - } -} -'''); - await assertHasFix(DartFixKind.CREATE_FIELD, ''' -class A<T> { - List<T> items; - - List<T> test; - - main(A a) { - test = items; - } -} -'''); - } - - test_createField_setter_qualified_instance_hasField() async { - await resolveTestUnit(''' -class A { - int aaa; - int zzz; - - existingMethod() {} -} -main(A a) { - a.test = 5; -} -'''); - await assertHasFix(DartFixKind.CREATE_FIELD, ''' -class A { - int aaa; - int zzz; - - int test; - - existingMethod() {} -} -main(A a) { - a.test = 5; -} -'''); - } - - test_createField_setter_qualified_instance_hasMethod() async { - await resolveTestUnit(''' -class A { - existingMethod() {} -} -main(A a) { - a.test = 5; -} -'''); - await assertHasFix(DartFixKind.CREATE_FIELD, ''' -class A { - int test; - - existingMethod() {} -} -main(A a) { - a.test = 5; -} -'''); - } - - test_createField_setter_qualified_static() async { - await resolveTestUnit(''' -class A { -} -main() { - A.test = 5; -} -'''); - await assertHasFix(DartFixKind.CREATE_FIELD, ''' -class A { - static int test; -} -main() { - A.test = 5; -} -'''); - } - - test_createField_setter_unqualified_instance() async { - await resolveTestUnit(''' -class A { - main() { - test = 5; - } -} -'''); - await assertHasFix(DartFixKind.CREATE_FIELD, ''' -class A { - int test; - - main() { - test = 5; - } -} -'''); - } - - test_createField_setter_unqualified_static() async { - await resolveTestUnit(''' -class A { - static main() { - test = 5; - } -} -'''); - await assertHasFix(DartFixKind.CREATE_FIELD, ''' -class A { - static int test; - - static main() { - test = 5; - } -} -'''); - } - - test_createFile_forImport() async { - testFile = '/my/project/bin/test.dart'; - await resolveTestUnit(''' -import 'my_file.dart'; -'''); - AnalysisError error = await _findErrorToFix(); - fix = await _assertHasFix(DartFixKind.CREATE_FILE, error); - change = fix.change; - // validate change - List<SourceFileEdit> fileEdits = change.edits; - expect(fileEdits, hasLength(1)); - SourceFileEdit fileEdit = change.edits[0]; - expect(fileEdit.file, convertPath('/my/project/bin/my_file.dart')); - expect(fileEdit.fileStamp, -1); - expect(fileEdit.edits, hasLength(1)); - expect(fileEdit.edits[0].replacement, contains('library my_file;')); - } - - test_createFile_forImport_BAD_inPackage_lib_justLib() async { - newFile('/projects/my_package/pubspec.yaml', content: 'name: my_package'); - testFile = '/projects/my_package/test.dart'; - await resolveTestUnit(''' -import 'lib'; -'''); - await assertNoFix(DartFixKind.CREATE_FILE); - } - - test_createFile_forImport_BAD_notDart() async { - testFile = '/my/project/bin/test.dart'; - await resolveTestUnit(''' -import 'my_file.txt'; -'''); - await assertNoFix(DartFixKind.CREATE_FILE); - } - - test_createFile_forImport_inPackage_lib() async { - newFile('/projects/my_package/pubspec.yaml', content: 'name: my_package'); - testFile = '/projects/my_package/lib/test.dart'; - newFolder('/projects/my_package/lib'); - await resolveTestUnit(''' -import 'a/bb/c_cc/my_lib.dart'; -'''); - AnalysisError error = await _findErrorToFix(); - fix = await _assertHasFix(DartFixKind.CREATE_FILE, error); - change = fix.change; - // validate change - List<SourceFileEdit> fileEdits = change.edits; - expect(fileEdits, hasLength(1)); - SourceFileEdit fileEdit = change.edits[0]; - expect(fileEdit.file, - convertPath('/projects/my_package/lib/a/bb/c_cc/my_lib.dart')); - expect(fileEdit.fileStamp, -1); - expect(fileEdit.edits, hasLength(1)); - expect(fileEdit.edits[0].replacement, - contains('library my_package.a.bb.c_cc.my_lib;')); - } - - test_createFile_forImport_inPackage_test() async { - newFile('/projects/my_package/pubspec.yaml', content: 'name: my_package'); - testFile = '/projects/my_package/test/misc/test_all.dart'; - await resolveTestUnit(''' -import 'a/bb/my_lib.dart'; -'''); - AnalysisError error = await _findErrorToFix(); - fix = await _assertHasFix(DartFixKind.CREATE_FILE, error); - change = fix.change; - // validate change - List<SourceFileEdit> fileEdits = change.edits; - expect(fileEdits, hasLength(1)); - SourceFileEdit fileEdit = change.edits[0]; - expect(fileEdit.file, - convertPath('/projects/my_package/test/misc/a/bb/my_lib.dart')); - expect(fileEdit.fileStamp, -1); - expect(fileEdit.edits, hasLength(1)); - expect(fileEdit.edits[0].replacement, - contains('library my_package.test.misc.a.bb.my_lib;')); - } - - test_createFile_forPart() async { - testFile = convertPath('/my/project/bin/test.dart'); - await resolveTestUnit(''' -library my.lib; -part 'my_part.dart'; -'''); - AnalysisError error = await _findErrorToFix(); - fix = await _assertHasFix(DartFixKind.CREATE_FILE, error); - change = fix.change; - // validate change - List<SourceFileEdit> fileEdits = change.edits; - expect(fileEdits, hasLength(1)); - SourceFileEdit fileEdit = change.edits[0]; - expect(fileEdit.file, convertPath('/my/project/bin/my_part.dart')); - expect(fileEdit.fileStamp, -1); - expect(fileEdit.edits, hasLength(1)); - expect(fileEdit.edits[0].replacement, contains('part of my.lib;')); - } - - test_createFile_forPart_inPackageLib() async { - newFile('/my/pubspec.yaml', content: r''' -name: my_test -'''); - testFile = '/my/lib/test.dart'; - addTestSource(''' -library my.lib; -part 'my_part.dart'; -''', Uri.parse('package:my/test.dart')); - // configure SourceFactory - UriResolver pkgResolver = new PackageMapUriResolver(resourceProvider, { - 'my': <Folder>[getFolder('/my/lib')], - }); - SourceFactory sourceFactory = new SourceFactory( - [new DartUriResolver(sdk), pkgResolver, resourceResolver]); - driver.configure(sourceFactory: sourceFactory); - testUnit = (await driver.getResult(convertPath(testFile))).unit; - // prepare fix - AnalysisError error = await _findErrorToFix(); - fix = await _assertHasFix(DartFixKind.CREATE_FILE, error); - change = fix.change; - // validate change - List<SourceFileEdit> fileEdits = change.edits; - expect(fileEdits, hasLength(1)); - SourceFileEdit fileEdit = change.edits[0]; - expect(fileEdit.file, convertPath('/my/lib/my_part.dart')); - expect(fileEdit.fileStamp, -1); - expect(fileEdit.edits, hasLength(1)); - expect(fileEdit.edits[0].replacement, contains('part of my.lib;')); - } - - test_createGetter_BAD_inSDK() async { - await resolveTestUnit(''' -main(List p) { - int v = p.foo; -} -'''); - await assertNoFix(DartFixKind.CREATE_GETTER); - } - - test_createGetter_hint_getter() async { - await resolveTestUnit(''' -class A { -} -main(A a) { - var x = a; - int v = x.test; -} -'''); - await assertHasFix(DartFixKind.CREATE_GETTER, ''' -class A { - int get test => null; -} -main(A a) { - var x = a; - int v = x.test; -} -'''); - } - - test_createGetter_location_afterLastGetter() async { - await resolveTestUnit(''' -class A { - int existingField; - - int get existingGetter => null; - - existingMethod() {} -} -main(A a) { - int v = a.test; -} -'''); - await assertHasFix(DartFixKind.CREATE_GETTER, ''' -class A { - int existingField; - - int get existingGetter => null; - - int get test => null; - - existingMethod() {} -} -main(A a) { - int v = a.test; -} -'''); - } - - test_createGetter_multiLevel() async { - await resolveTestUnit(''' -class A { -} -class B { - A a; -} -class C { - B b; -} -main(C c) { - int v = c.b.a.test; -} -'''); - await assertHasFix(DartFixKind.CREATE_GETTER, ''' -class A { - int get test => null; -} -class B { - A a; -} -class C { - B b; -} -main(C c) { - int v = c.b.a.test; -} -'''); - } - - test_createGetter_qualified_instance() async { - await resolveTestUnit(''' -class A { -} -main(A a) { - int v = a.test; -} -'''); - await assertHasFix(DartFixKind.CREATE_GETTER, ''' -class A { - int get test => null; -} -main(A a) { - int v = a.test; -} -'''); - } - - test_createGetter_qualified_instance_differentLibrary() async { - addSource('/project/other.dart', ''' -/** - * A comment to push the offset of the braces for the following class - * declaration past the end of the content of the test file. Used to catch an - * index out of bounds exception that occurs when using the test source instead - * of the target source to compute the location at which to insert the field. - */ -class A { -} -'''); - await resolveTestUnit(''' -import 'other.dart'; -main(A a) { - int v = a.test; -} -'''); - await assertHasFix( - DartFixKind.CREATE_GETTER, - ''' -/** - * A comment to push the offset of the braces for the following class - * declaration past the end of the content of the test file. Used to catch an - * index out of bounds exception that occurs when using the test source instead - * of the target source to compute the location at which to insert the field. - */ -class A { - int get test => null; -} -''', - target: '/project/other.dart'); - } - - test_createGetter_qualified_instance_dynamicType() async { - await resolveTestUnit(''' -class A { - B b; - void f(Object p) { - p == b.test; - } -} -class B { -} -'''); - await assertHasFix(DartFixKind.CREATE_GETTER, ''' -class A { - B b; - void f(Object p) { - p == b.test; - } -} -class B { - get test => null; -} -'''); - } - - test_createGetter_qualified_propagatedType() async { - await resolveTestUnit(''' -class A { - A get self => this; -} -main() { - var a = new A(); - int v = a.self.test; -} -'''); - await assertHasFix(DartFixKind.CREATE_GETTER, ''' -class A { - A get self => this; - - int get test => null; -} -main() { - var a = new A(); - int v = a.self.test; -} -'''); - } - - test_createGetter_setterContext() async { - await resolveTestUnit(''' -class A { -} -main(A a) { - a.test = 42; -} -'''); - await assertNoFix(DartFixKind.CREATE_GETTER); - } - - test_createGetter_unqualified_instance_asInvocationArgument() async { - await resolveTestUnit(''' -class A { - main() { - f(test); - } -} -f(String s) {} -'''); - await assertHasFix(DartFixKind.CREATE_GETTER, ''' -class A { - String get test => null; - - main() { - f(test); - } -} -f(String s) {} -'''); - } - - test_createGetter_unqualified_instance_assignmentLhs() async { - await resolveTestUnit(''' -class A { - main() { - test = 42; - } -} -'''); - await assertNoFix(DartFixKind.CREATE_GETTER); - } - - test_createGetter_unqualified_instance_assignmentRhs() async { - await resolveTestUnit(''' -class A { - main() { - int v = test; - } -} -'''); - await assertHasFix(DartFixKind.CREATE_GETTER, ''' -class A { - int get test => null; - - main() { - int v = test; - } -} -'''); - } - - test_createGetter_unqualified_instance_asStatement() async { - await resolveTestUnit(''' -class A { - main() { - test; - } -} -'''); - await assertHasFix(DartFixKind.CREATE_GETTER, ''' -class A { - get test => null; - - main() { - test; - } -} -'''); - } - - test_createLocalVariable_functionType_named() async { - await resolveTestUnit(''' -typedef MY_FUNCTION(int p); -foo(MY_FUNCTION f) {} -main() { - foo(bar); -} -'''); - await assertHasFix(DartFixKind.CREATE_LOCAL_VARIABLE, ''' -typedef MY_FUNCTION(int p); -foo(MY_FUNCTION f) {} -main() { - MY_FUNCTION bar; - foo(bar); -} -'''); - } - - test_createLocalVariable_functionType_named_generic() async { - await resolveTestUnit(''' -typedef MY_FUNCTION<T>(T p); -foo(MY_FUNCTION<int> f) {} -main() { - foo(bar); -} -'''); - await assertHasFix(DartFixKind.CREATE_LOCAL_VARIABLE, ''' -typedef MY_FUNCTION<T>(T p); -foo(MY_FUNCTION<int> f) {} -main() { - MY_FUNCTION<int> bar; - foo(bar); -} -'''); - } - - test_createLocalVariable_functionType_synthetic() async { - await resolveTestUnit(''' -foo(f(int p)) {} -main() { - foo(bar); -} -'''); - await assertHasFix(DartFixKind.CREATE_LOCAL_VARIABLE, ''' -foo(f(int p)) {} -main() { - Function(int p) bar; - foo(bar); -} -'''); - } - - test_createLocalVariable_read_typeAssignment() async { - await resolveTestUnit(''' -main() { - int a = test; -} -'''); - await assertHasFix(DartFixKind.CREATE_LOCAL_VARIABLE, ''' -main() { - int test; - int a = test; -} -'''); - } - - test_createLocalVariable_read_typeCondition() async { - await resolveTestUnit(''' -main() { - if (!test) { - print(42); - } -} -'''); - await assertHasFix(DartFixKind.CREATE_LOCAL_VARIABLE, ''' -main() { - bool test; - if (!test) { - print(42); - } -} -'''); - } - - test_createLocalVariable_read_typeInvocationArgument() async { - await resolveTestUnit(''' -main() { - f(test); -} -f(String p) {} -'''); - await assertHasFix(DartFixKind.CREATE_LOCAL_VARIABLE, ''' -main() { - String test; - f(test); -} -f(String p) {} -'''); - _assertLinkedGroup(change.linkedEditGroups[0], ['String test;']); - _assertLinkedGroup(change.linkedEditGroups[1], ['test;', 'test);']); - } - - test_createLocalVariable_read_typeInvocationTarget() async { - await resolveTestUnit(''' -main() { - test.add('hello'); -} -'''); - await assertHasFix(DartFixKind.CREATE_LOCAL_VARIABLE, ''' -main() { - var test; - test.add('hello'); -} -'''); - _assertLinkedGroup(change.linkedEditGroups[0], ['test;', 'test.add(']); - } - - test_createLocalVariable_withImport() async { - addPackageSource('pkg', 'a/a.dart', ''' -class A {} -'''); - addPackageSource('pkg', 'b/b.dart', ''' -class B {} -'''); - addPackageSource('pkg', 'c/c.dart', ''' -import 'package:pkg/a/a.dart'; -import 'package:pkg/b/b.dart'; - -class C { - C(A a, B b); -} -'''); - - await resolveTestUnit(''' -import 'package:pkg/a/a.dart'; -import 'package:pkg/c/c.dart'; - -main() { - A a; - new C(a, b); -} -'''); - await assertHasFix(DartFixKind.CREATE_LOCAL_VARIABLE, ''' -import 'package:pkg/a/a.dart'; -import 'package:pkg/b/b.dart'; -import 'package:pkg/c/c.dart'; - -main() { - A a; - B b; - new C(a, b); -} -'''); - - List<LinkedEditGroup> groups = change.linkedEditGroups; - expect(groups, hasLength(2)); - LinkedEditGroup typeGroup = groups[0]; - List<Position> typePositions = typeGroup.positions; - expect(typePositions, hasLength(1)); - expect(typePositions[0].offset, 112); - LinkedEditGroup nameGroup = groups[1]; - List<Position> groupPositions = nameGroup.positions; - expect(groupPositions, hasLength(2)); - expect(groupPositions[0].offset, 114); - expect(groupPositions[1].offset, 128); - } - - test_createLocalVariable_write_assignment() async { - await resolveTestUnit(''' -main() { - test = 42; -} -'''); - await assertHasFix(DartFixKind.CREATE_LOCAL_VARIABLE, ''' -main() { - var test = 42; -} -'''); - } - - test_createLocalVariable_write_assignment_compound() async { - await resolveTestUnit(''' -main() { - test += 42; -} -'''); - await assertHasFix(DartFixKind.CREATE_LOCAL_VARIABLE, ''' -main() { - int test; - test += 42; -} -'''); - } - - test_createMissingOverrides_field_untyped() async { - await resolveTestUnit(''' -class A { - var f; -} - -class B implements A { -} -'''); - await assertHasFix(DartFixKind.CREATE_MISSING_OVERRIDES, ''' -class A { - var f; -} - -class B implements A { - @override - var f; -} -'''); - } - - test_createMissingOverrides_functionTypeAlias() async { - await resolveTestUnit(''' -typedef int Binary(int left, int right); - -abstract class Emulator { - void performBinary(Binary binary); -} - -class MyEmulator extends Emulator { -} -'''); - await assertHasFix(DartFixKind.CREATE_MISSING_OVERRIDES, ''' -typedef int Binary(int left, int right); - -abstract class Emulator { - void performBinary(Binary binary); -} - -class MyEmulator extends Emulator { - @override - void performBinary(Binary binary) { - // TODO: implement performBinary - } -} -'''); - } - - test_createMissingOverrides_functionTypedParameter() async { - await resolveTestUnit(''' -abstract class A { - void forEach(int f(double p1, String p2)); -} - -class B extends A { -} -'''); - await assertHasFix(DartFixKind.CREATE_MISSING_OVERRIDES, ''' -abstract class A { - void forEach(int f(double p1, String p2)); -} - -class B extends A { - @override - void forEach(int Function(double p1, String p2) f) { - // TODO: implement forEach - } -} -'''); - } - - test_createMissingOverrides_generics_typeArguments() async { - await resolveTestUnit(''' -class Iterator<T> { -} - -abstract class IterableMixin<T> { - Iterator<T> get iterator; -} - -class Test extends IterableMixin<int> { -} -'''); - await assertHasFix(DartFixKind.CREATE_MISSING_OVERRIDES, ''' -class Iterator<T> { -} - -abstract class IterableMixin<T> { - Iterator<T> get iterator; -} - -class Test extends IterableMixin<int> { - @override - // TODO: implement iterator - Iterator<int> get iterator => null; -} -'''); - } - - test_createMissingOverrides_generics_typeParameters() async { - await resolveTestUnit(''' -abstract class ItemProvider<T> { - List<T> getItems(); -} - -class Test<V> extends ItemProvider<V> { -} -'''); - await assertHasFix(DartFixKind.CREATE_MISSING_OVERRIDES, ''' -abstract class ItemProvider<T> { - List<T> getItems(); -} - -class Test<V> extends ItemProvider<V> { - @override - List<V> getItems() { - // TODO: implement getItems - return null; - } -} -'''); - } - - test_createMissingOverrides_getter() async { - await resolveTestUnit(''' -abstract class A { - get g1; - int get g2; -} - -class B extends A { -} -'''); - await assertHasFix(DartFixKind.CREATE_MISSING_OVERRIDES, ''' -abstract class A { - get g1; - int get g2; -} - -class B extends A { - @override - // TODO: implement g1 - get g1 => null; - - @override - // TODO: implement g2 - int get g2 => null; -} -'''); - } - - test_createMissingOverrides_importPrefix() async { - await resolveTestUnit(''' -import 'dart:async' as aaa; -abstract class A { - Map<aaa.Future, List<aaa.Future>> g(aaa.Future p); -} - -class B extends A { -} -'''); - await assertHasFix(DartFixKind.CREATE_MISSING_OVERRIDES, ''' -import 'dart:async' as aaa; -abstract class A { - Map<aaa.Future, List<aaa.Future>> g(aaa.Future p); -} - -class B extends A { - @override - Map<aaa.Future, List<aaa.Future>> g(aaa.Future p) { - // TODO: implement g - return null; - } -} -'''); - } - - test_createMissingOverrides_mergeToField_getterSetter() async { - await resolveTestUnit(''' -class A { - int ma; - void mb() {} - double mc; -} - -class B implements A { -} -'''); - await assertHasFix(DartFixKind.CREATE_MISSING_OVERRIDES, ''' -class A { - int ma; - void mb() {} - double mc; -} - -class B implements A { - @override - int ma; - - @override - double mc; - - @override - void mb() { - // TODO: implement mb - } -} -'''); - } - - test_createMissingOverrides_method() async { - await resolveTestUnit(''' -abstract class A { - void m1(); - int m2(); - String m3(int p1, double p2, Map<int, List<String>> p3); - String m4(p1, p2); - String m5(p1, [int p2 = 2, int p3, p4 = 4]); - String m6(p1, {int p2 = 2, int p3, p4: 4}); -} - -class B extends A { -} -'''); - String expectedCode = ''' -abstract class A { - void m1(); - int m2(); - String m3(int p1, double p2, Map<int, List<String>> p3); - String m4(p1, p2); - String m5(p1, [int p2 = 2, int p3, p4 = 4]); - String m6(p1, {int p2 = 2, int p3, p4: 4}); -} - -class B extends A { - @override - void m1() { - // TODO: implement m1 - } - - @override - int m2() { - // TODO: implement m2 - return null; - } - - @override - String m3(int p1, double p2, Map<int, List<String>> p3) { - // TODO: implement m3 - return null; - } - - @override - String m4(p1, p2) { - // TODO: implement m4 - return null; - } - - @override - String m5(p1, [int p2 = 2, int p3, p4 = 4]) { - // TODO: implement m5 - return null; - } - - @override - String m6(p1, {int p2 = 2, int p3, p4 = 4}) { - // TODO: implement m6 - return null; - } -} -'''; - await assertHasFix(DartFixKind.CREATE_MISSING_OVERRIDES, expectedCode); - // end position should be on "m1", not on "m2", "m3", etc - { - Position endPosition = change.selection; - expect(endPosition, isNotNull); - expect(endPosition.file, testFile); - int endOffset = endPosition.offset; - String endString = expectedCode.substring(endOffset, endOffset + 25); - expect(endString, contains('m1')); - expect(endString, isNot(contains('m2'))); - expect(endString, isNot(contains('m3'))); - expect(endString, isNot(contains('m4'))); - expect(endString, isNot(contains('m5'))); - expect(endString, isNot(contains('m6'))); - } - } - - test_createMissingOverrides_method_emptyClassBody() async { - await resolveTestUnit(''' -abstract class A { - void foo(); -} - -class B extends A {} -'''); - await assertHasFix(DartFixKind.CREATE_MISSING_OVERRIDES, ''' -abstract class A { - void foo(); -} - -class B extends A { - @override - void foo() { - // TODO: implement foo - } -} -'''); - } - - test_createMissingOverrides_method_generic() async { - await resolveTestUnit(''' -class C<T> {} -class V<E> {} - -abstract class A { - E1 foo<E1, E2 extends C<int>>(V<E2> v); -} - -class B implements A { -} -'''); - await assertHasFix(DartFixKind.CREATE_MISSING_OVERRIDES, ''' -class C<T> {} -class V<E> {} - -abstract class A { - E1 foo<E1, E2 extends C<int>>(V<E2> v); -} - -class B implements A { - @override - E1 foo<E1, E2 extends C<int>>(V<E2> v) { - // TODO: implement foo - return null; - } -} -'''); - } - - test_createMissingOverrides_method_genericClass2() async { - await resolveTestUnit(''' -class A<R> { - R foo(int a) => null; -} - -class B<R> extends A<R> { - R bar(double b) => null; -} - -class X implements B<bool> { -} -'''); - await assertHasFix(DartFixKind.CREATE_MISSING_OVERRIDES, ''' -class A<R> { - R foo(int a) => null; -} - -class B<R> extends A<R> { - R bar(double b) => null; -} - -class X implements B<bool> { - @override - bool bar(double b) { - // TODO: implement bar - return null; - } - - @override - bool foo(int a) { - // TODO: implement foo - return null; - } -} -'''); - } - - test_createMissingOverrides_method_generic_withBounds() async { - // https://github.com/dart-lang/sdk/issues/31199 - await resolveTestUnit(''' -abstract class A<K, V> { - List<T> foo<T extends V>(K key); -} - -class B<K, V> implements A<K, V> { -} -'''); - await assertHasFix(DartFixKind.CREATE_MISSING_OVERRIDES, ''' -abstract class A<K, V> { - List<T> foo<T extends V>(K key); -} - -class B<K, V> implements A<K, V> { - @override - List<T> foo<T extends V>(K key) { - // TODO: implement foo - return null; - } -} -'''); - } - - test_createMissingOverrides_method_notEmptyClassBody() async { - await resolveTestUnit(''' -abstract class A { - void foo(); -} - -class B extends A { - void bar() {} -} -'''); - await assertHasFix(DartFixKind.CREATE_MISSING_OVERRIDES, ''' -abstract class A { - void foo(); -} - -class B extends A { - void bar() {} - - @override - void foo() { - // TODO: implement foo - } -} -'''); - } - - test_createMissingOverrides_operator() async { - await resolveTestUnit(''' -abstract class A { - int operator [](int index); - void operator []=(int index, String value); -} - -class B extends A { -} -'''); - await assertHasFix(DartFixKind.CREATE_MISSING_OVERRIDES, ''' -abstract class A { - int operator [](int index); - void operator []=(int index, String value); -} - -class B extends A { - @override - int operator [](int index) { - // TODO: implement [] - return null; - } - - @override - void operator []=(int index, String value) { - // TODO: implement []= - } -} -'''); - } - - test_createMissingOverrides_setter() async { - await resolveTestUnit(''' -abstract class A { - set s1(x); - set s2(int x); - void set s3(String x); -} - -class B extends A { -} -'''); - await assertHasFix(DartFixKind.CREATE_MISSING_OVERRIDES, ''' -abstract class A { - set s1(x); - set s2(int x); - void set s3(String x); -} - -class B extends A { - @override - void set s1(x) { - // TODO: implement s1 - } - - @override - void set s2(int x) { - // TODO: implement s2 - } - - @override - void set s3(String x) { - // TODO: implement s3 - } -} -'''); - } - - test_createMixin() async { - await resolveTestUnit(''' -main() { - Test v = null; -} -'''); - await assertHasFix(DartFixKind.CREATE_MIXIN, ''' -main() { - Test v = null; -} - -mixin Test { -} -'''); - _assertLinkedGroup(change.linkedEditGroups[0], ['Test v =', 'Test {']); - } - - test_createMixin_BAD_hasUnresolvedPrefix() async { - await resolveTestUnit(''' -main() { - prefix.Test v = null; -} -'''); - await assertNoFix(DartFixKind.CREATE_MIXIN); - } - - test_createMixin_BAD_instanceCreation_withNew() async { - await resolveTestUnit(''' -main() { - new Test(); -} -'''); - await assertNoFix(DartFixKind.CREATE_MIXIN); - } - - test_createMixin_BAD_instanceCreation_withoutNew() async { - await resolveTestUnit(''' -main() { - Test(); -} -'''); - await assertNoFix(DartFixKind.CREATE_MIXIN); - } - - test_createMixin_inLibraryOfPrefix() async { - String libCode = r''' -library my.lib; - -class A {} -'''; - addSource('/project/lib.dart', libCode); - await resolveTestUnit(''' -import 'lib.dart' as lib; - -main() { - lib.A a = null; - lib.Test t = null; -} -'''); - AnalysisError error = await _findErrorToFix(); - fix = await _assertHasFix(DartFixKind.CREATE_MIXIN, error); - change = fix.change; - // apply to "lib.dart" - List<SourceFileEdit> fileEdits = change.edits; - expect(fileEdits, hasLength(1)); - SourceFileEdit fileEdit = change.edits[0]; - expect(fileEdit.file, convertPath('/project/lib.dart')); - expect(SourceEdit.applySequence(libCode, fileEdit.edits), r''' -library my.lib; - -class A {} - -mixin Test { -} -'''); - expect(change.linkedEditGroups, hasLength(1)); - } - - test_createMixin_innerLocalFunction() async { - await resolveTestUnit(''' -f() { - g() { - Test v = null; - } -} -'''); - await assertHasFix(DartFixKind.CREATE_MIXIN, ''' -f() { - g() { - Test v = null; - } -} - -mixin Test { -} -'''); - _assertLinkedGroup(change.linkedEditGroups[0], ['Test v =', 'Test {']); - } - - test_createMixin_itemOfList() async { - await resolveTestUnit(''' -main() { - var a = [Test]; -} -'''); - await assertHasFix(DartFixKind.CREATE_MIXIN, ''' -main() { - var a = [Test]; -} - -mixin Test { -} -'''); - _assertLinkedGroup(change.linkedEditGroups[0], ['Test];', 'Test {']); - } - - test_createMixin_itemOfList_inAnnotation() async { - errorFilter = (AnalysisError error) { - return error.errorCode == StaticWarningCode.UNDEFINED_IDENTIFIER; - }; - await resolveTestUnit(''' -class MyAnnotation { - const MyAnnotation(a, b); -} -@MyAnnotation(int, const [Test]) -main() {} -'''); - await assertHasFix(DartFixKind.CREATE_MIXIN, ''' -class MyAnnotation { - const MyAnnotation(a, b); -} -@MyAnnotation(int, const [Test]) -main() {} - -mixin Test { -} -'''); - _assertLinkedGroup(change.linkedEditGroups[0], ['Test])', 'Test {']); - } - - test_createNoSuchMethod_BAD_classTypeAlias() async { - await resolveTestUnit(''' -abstract class A { - m(); -} - -class B = Object with A; -'''); - await assertNoFix( - DartFixKind.CREATE_NO_SUCH_METHOD, - ); - } - - test_createNoSuchMethod_OK() async { - await resolveTestUnit(''' -abstract class A { - m1(); - int m2(); -} - -class B extends A { - existing() {} -} -'''); - await assertHasFix(DartFixKind.CREATE_NO_SUCH_METHOD, ''' -abstract class A { - m1(); - int m2(); -} - -class B extends A { - existing() {} - - noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation); -} -'''); - } - - test_creationFunction_forFunctionType_cascadeSecond() async { - await resolveTestUnit(''' -class A { - B ma() => null; -} -class B { - useFunction(int g(double a, String b)) {} -} - -main() { - A a = new A(); - a..ma().useFunction(test); -} -'''); - await assertHasFix(DartFixKind.CREATE_FUNCTION, ''' -class A { - B ma() => null; -} -class B { - useFunction(int g(double a, String b)) {} -} - -main() { - A a = new A(); - a..ma().useFunction(test); -} - -int test(double a, String b) { -} -'''); - } - - test_creationFunction_forFunctionType_coreFunction() async { - await resolveTestUnit(''' -main() { - useFunction(g: test); -} -useFunction({Function g}) {} -'''); - await assertHasFix(DartFixKind.CREATE_FUNCTION, ''' -main() { - useFunction(g: test); -} -useFunction({Function g}) {} - -test() { -} -'''); - } - - test_creationFunction_forFunctionType_dynamicArgument() async { - await resolveTestUnit(''' -main() { - useFunction(test); -} -useFunction(int g(a, b)) {} -'''); - await assertHasFix(DartFixKind.CREATE_FUNCTION, ''' -main() { - useFunction(test); -} -useFunction(int g(a, b)) {} - -int test(a, b) { -} -'''); - } - - test_creationFunction_forFunctionType_function() async { - await resolveTestUnit(''' -main() { - useFunction(test); -} -useFunction(int g(double a, String b)) {} -'''); - await assertHasFix(DartFixKind.CREATE_FUNCTION, ''' -main() { - useFunction(test); -} -useFunction(int g(double a, String b)) {} - -int test(double a, String b) { -} -'''); - } - - test_creationFunction_forFunctionType_function_namedArgument() async { - await resolveTestUnit(''' -main() { - useFunction(g: test); -} -useFunction({int g(double a, String b)}) {} -'''); - await assertHasFix(DartFixKind.CREATE_FUNCTION, ''' -main() { - useFunction(g: test); -} -useFunction({int g(double a, String b)}) {} - -int test(double a, String b) { -} -'''); - } - - test_creationFunction_forFunctionType_importType() async { - addSource('/project/libA.dart', r''' -library libA; -class A {} -'''); - addSource('/project/libB.dart', r''' -library libB; -import 'libA.dart'; -useFunction(int g(A a)) {} -'''); - await resolveTestUnit(''' -import 'libB.dart'; -main() { - useFunction(test); -} -'''); - await assertHasFix(DartFixKind.CREATE_FUNCTION, ''' -import 'libA.dart'; -import 'libB.dart'; -main() { - useFunction(test); -} - -int test(A a) { -} -'''); - } - - test_creationFunction_forFunctionType_method_enclosingClass_static() async { - await resolveTestUnit(''' -class A { - static foo() { - useFunction(test); - } -} -useFunction(int g(double a, String b)) {} -'''); - await assertHasFix(DartFixKind.CREATE_METHOD, ''' -class A { - static foo() { - useFunction(test); - } - - static int test(double a, String b) { - } -} -useFunction(int g(double a, String b)) {} -'''); - } - - test_creationFunction_forFunctionType_method_enclosingClass_static2() async { - await resolveTestUnit(''' -class A { - var f; - A() : f = useFunction(test); -} -useFunction(int g(double a, String b)) {} -'''); - await assertHasFix(DartFixKind.CREATE_METHOD, ''' -class A { - var f; - A() : f = useFunction(test); - - static int test(double a, String b) { - } -} -useFunction(int g(double a, String b)) {} -'''); - } - - test_creationFunction_forFunctionType_method_targetClass() async { - await resolveTestUnit(''' -main(A a) { - useFunction(a.test); -} -class A { -} -useFunction(int g(double a, String b)) {} -'''); - await assertHasFix(DartFixKind.CREATE_METHOD, ''' -main(A a) { - useFunction(a.test); -} -class A { - int test(double a, String b) { - } -} -useFunction(int g(double a, String b)) {} -'''); - } - - test_creationFunction_forFunctionType_method_targetClass_hasOtherMember() async { - await resolveTestUnit(''' -main(A a) { - useFunction(a.test); -} -class A { - m() {} -} -useFunction(int g(double a, String b)) {} -'''); - await assertHasFix(DartFixKind.CREATE_METHOD, ''' -main(A a) { - useFunction(a.test); -} -class A { - m() {} - - int test(double a, String b) { - } -} -useFunction(int g(double a, String b)) {} -'''); - } - - test_creationFunction_forFunctionType_notFunctionType() async { - await resolveTestUnit(''' -main(A a) { - useFunction(a.test); -} -typedef A(); -useFunction(g) {} -'''); - await assertNoFix(DartFixKind.CREATE_METHOD); - await assertNoFix(DartFixKind.CREATE_FUNCTION); - } - - test_creationFunction_forFunctionType_unknownTarget() async { - await resolveTestUnit(''' -main(A a) { - useFunction(a.test); -} -class A { -} -useFunction(g) {} -'''); - await assertNoFix(DartFixKind.CREATE_METHOD); - } - - test_expectedToken_semicolon() async { - await resolveTestUnit(''' -main() { - print(0) -} -'''); - await assertHasFix(DartFixKind.INSERT_SEMICOLON, ''' -main() { - print(0); -} -'''); - } - - test_illegalAsyncReturnType_adjacentNodes() async { - errorFilter = (AnalysisError error) { - return error.errorCode == StaticTypeWarningCode.ILLEGAL_ASYNC_RETURN_TYPE; - }; - await resolveTestUnit(''' -import 'dart:async'; -var v;int main() async => 0; -'''); - await assertHasFix(DartFixKind.REPLACE_RETURN_TYPE_FUTURE, ''' -import 'dart:async'; -var v;Future<int> main() async => 0; -'''); - } - - test_illegalAsyncReturnType_asyncLibrary_import() async { - errorFilter = (AnalysisError error) { - return error.errorCode == StaticTypeWarningCode.ILLEGAL_ASYNC_RETURN_TYPE; - }; - await resolveTestUnit(''' -library main; -int main() async { -} -'''); - await assertHasFix(DartFixKind.REPLACE_RETURN_TYPE_FUTURE, ''' -library main; - -import 'dart:async'; - -Future<int> main() async { -} -'''); - } - - test_illegalAsyncReturnType_asyncLibrary_usePrefix() async { - errorFilter = (AnalysisError error) { - return error.errorCode == StaticTypeWarningCode.ILLEGAL_ASYNC_RETURN_TYPE; - }; - await resolveTestUnit(''' -import 'dart:async' as al; -int main() async { -} -'''); - await assertHasFix(DartFixKind.REPLACE_RETURN_TYPE_FUTURE, ''' -import 'dart:async' as al; -al.Future<int> main() async { -} -'''); - } - - test_illegalAsyncReturnType_complexTypeName() async { - errorFilter = (AnalysisError error) { - return error.errorCode == StaticTypeWarningCode.ILLEGAL_ASYNC_RETURN_TYPE; - }; - await resolveTestUnit(''' -import 'dart:async'; -List<int> main() async { -} -'''); - await assertHasFix(DartFixKind.REPLACE_RETURN_TYPE_FUTURE, ''' -import 'dart:async'; -Future<List<int>> main() async { -} -'''); - } - - test_importLibraryPackage_preferDirectOverExport() async { - _configureMyPkg({'b.dart': 'class Test {}', 'a.dart': "export 'b.dart';"}); - await resolveTestUnit(''' -main() { - Test test = null; -} -'''); - await assertHasFix(DartFixKind.IMPORT_LIBRARY_PROJECT1, ''' -import 'package:my_pkg/b.dart'; - -main() { - Test test = null; -} -'''); - await assertHasFix(DartFixKind.IMPORT_LIBRARY_PROJECT2, ''' -import 'package:my_pkg/a.dart'; - -main() { - Test test = null; -} -'''); - } - - test_importLibraryPackage_preferDirectOverExport_src() async { - myPkgLibPath = '/my/src/packages/my_pkg/lib'; - _configureMyPkg({'b.dart': 'class Test {}', 'a.dart': "export 'b.dart';"}); - await resolveTestUnit(''' -main() { - Test test = null; -} -'''); - await assertHasFix(DartFixKind.IMPORT_LIBRARY_PROJECT1, ''' -import 'package:my_pkg/b.dart'; - -main() { - Test test = null; -} -'''); - await assertHasFix(DartFixKind.IMPORT_LIBRARY_PROJECT2, ''' -import 'package:my_pkg/a.dart'; - -main() { - Test test = null; -} -'''); - } - - test_importLibraryProject_BAD_inLibSrc_differentContextRoot() async { - addPackageSource('bbb', 'b1.dart', r''' -import 'src/b2.dart'; -'''); - addPackageSource('bbb', 'src/b2.dart', 'class Test {}'); - await resolveTestUnit(''' -import 'package:bbb/b1.dart'; -main() { - Test t; -} -'''); - errorFilter = (AnalysisError error) { - return error.errorCode == StaticWarningCode.UNDEFINED_CLASS; - }; - await assertNoFix(DartFixKind.IMPORT_LIBRARY_PROJECT3); - } - - test_importLibraryProject_BAD_notInLib_BUILD() async { - testFile = '/project/lib/test.dart'; - addSource('/other/test/lib.dart', 'class Test {}'); - await resolveTestUnit(''' -main() { - Test t; -} -'''); - await assertNoFix(DartFixKind.IMPORT_LIBRARY_PROJECT1); - } - - test_importLibraryProject_BAD_notInLib_pubspec() async { - testFile = '/project/lib/test.dart'; - addSource('/other/test/lib.dart', 'class Test {}'); - await resolveTestUnit(''' -main() { - Test t; -} -'''); - await assertNoFix(DartFixKind.IMPORT_LIBRARY_PROJECT1); - } - - test_importLibraryProject_OK_inLibSrc_thisContextRoot() async { - testFile = '/project/lib/test.dart'; - packageMap['project'] = [newFolder('/project/lib')]; - addSource('/project/lib/src/lib.dart', 'class Test {}'); - configureDriver(); - await resolveTestUnit(''' -main() { - Test t; -} -'''); - errorFilter = (AnalysisError error) { - return error.errorCode == StaticWarningCode.UNDEFINED_CLASS; - }; - await assertHasFix(DartFixKind.IMPORT_LIBRARY_PROJECT3, ''' -import 'package:project/src/lib.dart'; - -main() { - Test t; -} -'''); - } - - test_importLibraryProject_withClass_annotation() async { - testFile = '/project/lib/test.dart'; - addSource('/project/lib/lib.dart', ''' -library lib; -class Test { - const Test(int p); -} -'''); - await resolveTestUnit(''' -@Test(0) -main() { -} -'''); - await assertHasFix(DartFixKind.IMPORT_LIBRARY_PROJECT1, ''' -import 'lib.dart'; - -@Test(0) -main() { -} -'''); - } - - test_importLibraryProject_withClass_hasOtherLibraryWithPrefix() async { - testFile = '/project/bin/test.dart'; - addSource('/project/bin/a.dart', ''' -library a; -class One {} -'''); - addSource('/project/bin/b.dart', ''' -library b; -class One {} -class Two {} -'''); - await resolveTestUnit(''' -import 'b.dart' show Two; -main () { - new Two(); - new One(); -} -'''); - await assertHasFix(DartFixKind.IMPORT_LIBRARY_PROJECT1, ''' -import 'a.dart'; -import 'b.dart' show Two; -main () { - new Two(); - new One(); -} -'''); - } - - test_importLibraryProject_withClass_inParentFolder() async { - testFile = '/project/bin/test.dart'; - addSource('/project/lib.dart', ''' -library lib; -class Test {} -'''); - await resolveTestUnit(''' -main() { - Test t = null; -} -'''); - await assertHasFix(DartFixKind.IMPORT_LIBRARY_PROJECT1, ''' -import '../lib.dart'; - -main() { - Test t = null; -} -'''); - } - - test_importLibraryProject_withClass_inRelativeFolder() async { - testFile = '/project/bin/test.dart'; - addSource('/project/lib/sub/folder/lib.dart', ''' -library lib; -class Test {} -'''); - await resolveTestUnit(''' -main() { - Test t = null; -} -'''); - await assertHasFix(DartFixKind.IMPORT_LIBRARY_PROJECT1, ''' -import '../lib/sub/folder/lib.dart'; - -main() { - Test t = null; -} -'''); - } - - test_importLibraryProject_withClass_inSameFolder() async { - testFile = '/project/bin/test.dart'; - addSource('/project/bin/lib.dart', ''' -library lib; -class Test {} -'''); - await resolveTestUnit(''' -main() { - Test t = null; -} -'''); - await assertHasFix(DartFixKind.IMPORT_LIBRARY_PROJECT1, ''' -import 'lib.dart'; - -main() { - Test t = null; -} -'''); - } - - test_importLibraryProject_withClass_instanceCreation_const() async { - testFile = '/project/lib/test.dart'; - addSource('/project/lib/lib.dart', ''' -class Test { - const Test(); -} -'''); - await resolveTestUnit(''' -main() { - return const Test(); -} -'''); - await assertHasFix(DartFixKind.IMPORT_LIBRARY_PROJECT1, ''' -import 'lib.dart'; - -main() { - return const Test(); -} -'''); - } - - test_importLibraryProject_withClass_instanceCreation_const_namedConstructor() async { - testFile = '/project/lib/test.dart'; - addSource('/project/lib/lib.dart', ''' -class Test { - const Test.named(); -} -'''); - await resolveTestUnit(''' -main() { - const Test.named(); -} -'''); - await assertHasFix(DartFixKind.IMPORT_LIBRARY_PROJECT1, ''' -import 'lib.dart'; - -main() { - const Test.named(); -} -'''); - } - - test_importLibraryProject_withClass_instanceCreation_implicit() async { - testFile = '/project/lib/test.dart'; - addSource('/project/lib/lib.dart', ''' -class Test { - const Test(); -} -'''); - await resolveTestUnit(''' -main() { - return Test(); -} -'''); - await assertHasFix(DartFixKind.IMPORT_LIBRARY_PROJECT1, ''' -import 'lib.dart'; - -main() { - return Test(); -} -'''); - } - - test_importLibraryProject_withClass_instanceCreation_new() async { - testFile = '/project/lib/test.dart'; - addSource('/project/lib/lib.dart', ''' -class Test { - const Test(); -} -'''); - await resolveTestUnit(''' -main() { - return new Test(); -} -'''); - await assertHasFix(DartFixKind.IMPORT_LIBRARY_PROJECT1, ''' -import 'lib.dart'; - -main() { - return new Test(); -} -'''); - } - - test_importLibraryProject_withClass_instanceCreation_new_namedConstructor() async { - testFile = '/project/lib/test.dart'; - addSource('/project/lib/lib.dart', ''' -class Test { - Test.named(); -} -'''); - await resolveTestUnit(''' -main() { - new Test.named(); -} -'''); - await assertHasFix(DartFixKind.IMPORT_LIBRARY_PROJECT1, ''' -import 'lib.dart'; - -main() { - new Test.named(); -} -'''); - } - - test_importLibraryProject_withFunction() async { - testFile = '/project/lib/test.dart'; - addSource('/project/lib/lib.dart', ''' -library lib; -myFunction() {} -'''); - await resolveTestUnit(''' -main() { - myFunction(); -} -'''); - await assertHasFix(DartFixKind.IMPORT_LIBRARY_PROJECT1, ''' -import 'lib.dart'; - -main() { - myFunction(); -} -'''); - } - - test_importLibraryProject_withFunction_unresolvedMethod() async { - testFile = '/project/lib/test.dart'; - addSource('/project/lib/lib.dart', ''' -library lib; -myFunction() {} -'''); - await resolveTestUnit(''' -class A { - main() { - myFunction(); - } -} -'''); - await assertHasFix(DartFixKind.IMPORT_LIBRARY_PROJECT1, ''' -import 'lib.dart'; - -class A { - main() { - myFunction(); - } -} -'''); - } - - test_importLibraryProject_withFunctionTypeAlias() async { - testFile = '/project/bin/test.dart'; - addSource('/project/bin/lib.dart', ''' -library lib; -typedef MyFunction(); -'''); - await resolveTestUnit(''' -main() { - MyFunction t = null; -} -'''); - await assertHasFix(DartFixKind.IMPORT_LIBRARY_PROJECT1, ''' -import 'lib.dart'; - -main() { - MyFunction t = null; -} -'''); - } - - test_importLibraryProject_withTopLevelVariable() async { - testFile = '/project/lib/test.dart'; - addSource('/project/lib/lib.dart', ''' -library lib; -int MY_VAR = 42; -'''); - await resolveTestUnit(''' -main() { - print(MY_VAR); -} -'''); - await assertHasFix(DartFixKind.IMPORT_LIBRARY_PROJECT1, ''' -import 'lib.dart'; - -main() { - print(MY_VAR); -} -'''); - } - - test_importLibrarySdk_withClass_AsExpression() async { - await resolveTestUnit(''' -main(p) { - p as Future; -} -'''); - await assertHasFix(DartFixKind.IMPORT_LIBRARY_SDK, ''' -import 'dart:async'; - -main(p) { - p as Future; -} -'''); - } - - test_importLibrarySdk_withClass_instanceCreation_explicitNew() async { - await resolveTestUnit(''' -class C { - foo() { - new Future(); - } -} -'''); - await assertHasFix(DartFixKind.IMPORT_LIBRARY_SDK, ''' -import 'dart:async'; - -class C { - foo() { - new Future(); - } -} -'''); - } - - test_importLibrarySdk_withClass_instanceCreation_explicitNew_namedConstructor() async { - await resolveTestUnit(''' -class C { - foo() { - new Future.value(0); - } -} -'''); - await assertHasFix(DartFixKind.IMPORT_LIBRARY_SDK, ''' -import 'dart:async'; - -class C { - foo() { - new Future.value(0); - } -} -'''); - } - - test_importLibrarySdk_withClass_instanceCreation_implicitNew() async { - configurePreviewDart2(); - await resolveTestUnit(''' -class C { - foo() { - Future(); - } -} -'''); - await assertHasFix(DartFixKind.IMPORT_LIBRARY_SDK, ''' -import 'dart:async'; - -class C { - foo() { - Future(); - } -} -'''); - } - - test_importLibrarySdk_withClass_instanceCreation_implicitNew_namedConstructor() async { - configurePreviewDart2(); - await resolveTestUnit(''' -class C { - foo() { - Future.value(0); - } -} -'''); - await assertHasFix(DartFixKind.IMPORT_LIBRARY_SDK, ''' -import 'dart:async'; - -class C { - foo() { - Future.value(0); - } -} -'''); - } - - test_importLibrarySdk_withClass_invocationTarget() async { - await resolveTestUnit(''' -main() { - Future.wait(null); -} -'''); - await assertHasFix(DartFixKind.IMPORT_LIBRARY_SDK, ''' -import 'dart:async'; - -main() { - Future.wait(null); -} -'''); - } - - test_importLibrarySdk_withClass_IsExpression() async { - await resolveTestUnit(''' -main(p) { - p is Future; -} -'''); - await assertHasFix(DartFixKind.IMPORT_LIBRARY_SDK, ''' -import 'dart:async'; - -main(p) { - p is Future; -} -'''); - } - - test_importLibrarySdk_withClass_itemOfList() async { - await resolveTestUnit(''' -main() { - var a = [Future]; -} -'''); - await assertHasFix(DartFixKind.IMPORT_LIBRARY_SDK, ''' -import 'dart:async'; - -main() { - var a = [Future]; -} -'''); - } - - test_importLibrarySdk_withClass_itemOfList_inAnnotation() async { - errorFilter = (AnalysisError error) { - return error.errorCode == StaticWarningCode.UNDEFINED_IDENTIFIER; - }; - await resolveTestUnit(''' -class MyAnnotation { - const MyAnnotation(a, b); -} -@MyAnnotation(int, const [Future]) -main() {} -'''); - await assertHasFix(DartFixKind.IMPORT_LIBRARY_SDK, ''' -import 'dart:async'; - -class MyAnnotation { - const MyAnnotation(a, b); -} -@MyAnnotation(int, const [Future]) -main() {} -'''); - } - - test_importLibrarySdk_withClass_typeAnnotation() async { - await resolveTestUnit(''' -main() { - Future f = null; -} -'''); - await assertHasFix(DartFixKind.IMPORT_LIBRARY_SDK, ''' -import 'dart:async'; - -main() { - Future f = null; -} -'''); - } - - test_importLibrarySdk_withClass_typeAnnotation_PrefixedIdentifier() async { - await resolveTestUnit(''' -main() { - Future.wait; -} -'''); - await assertHasFix(DartFixKind.IMPORT_LIBRARY_SDK, ''' -import 'dart:async'; - -main() { - Future.wait; -} -'''); - } - - test_importLibrarySdk_withClass_typeArgument() async { - await resolveTestUnit(''' -main() { - List<Future> futures = []; -} -'''); - await assertHasFix(DartFixKind.IMPORT_LIBRARY_SDK, ''' -import 'dart:async'; - -main() { - List<Future> futures = []; -} -'''); - } - - test_importLibrarySdk_withTopLevelVariable() async { - await resolveTestUnit(''' -main() { - print(PI); -} -'''); - await assertHasFix(DartFixKind.IMPORT_LIBRARY_SDK, ''' -import 'dart:math'; - -main() { - print(PI); -} -'''); - } - - test_importLibrarySdk_withTopLevelVariable_annotation() async { - await resolveTestUnit(''' -@PI -main() { -} -'''); - await assertHasFix(DartFixKind.IMPORT_LIBRARY_SDK, ''' -import 'dart:math'; - -@PI -main() { -} -'''); - } - - test_importLibraryShow_project() async { - testFile = '/project/bin/test.dart'; - addSource('/project/bin/lib.dart', ''' -class A {} -class B {} -'''); - await resolveTestUnit(''' -import 'lib.dart' show A; -main() { - A a; - B b; -} -'''); - await assertNoFix(DartFixKind.IMPORT_LIBRARY_PROJECT1); - await assertHasFix(DartFixKind.IMPORT_LIBRARY_SHOW, ''' -import 'lib.dart' show A, B; -main() { - A a; - B b; -} -'''); - } - - test_importLibraryShow_sdk() async { - await resolveTestUnit(''' -import 'dart:async' show Stream; -main() { - Stream s = null; - Future f = null; -} -'''); - await assertNoFix(DartFixKind.IMPORT_LIBRARY_SDK); - await assertHasFix(DartFixKind.IMPORT_LIBRARY_SHOW, ''' -import 'dart:async' show Future, Stream; -main() { - Stream s = null; - Future f = null; -} -'''); - } - - test_impreciseIntAsDouble() async { - await resolveTestUnit(''' -double x = 1000000000000000000000000; -'''); - await assertHasFix(DartFixKind.CHANGE_TO_NEAREST_PRECISE_VALUE, ''' -double x = 999999999999999983222784; -'''); - } - - test_impreciseIntAsDouble_asCapitalHex() async { - await resolveTestUnit(''' -double x = 0X1000000000000000000000001; -'''); - await assertHasFix(DartFixKind.CHANGE_TO_NEAREST_PRECISE_VALUE, ''' -double x = 0x1000000000000000000000000; -'''); - } - - test_impreciseIntAsDouble_asHex() async { - await resolveTestUnit(''' -double x = 0x1000000000000000000000001; -'''); - await assertHasFix(DartFixKind.CHANGE_TO_NEAREST_PRECISE_VALUE, ''' -double x = 0x1000000000000000000000000; -'''); - } - - test_impreciseIntAsDouble_maxValue() async { - await resolveTestUnit(''' -double x = 10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000; -'''); - await assertHasFix(DartFixKind.CHANGE_TO_NEAREST_PRECISE_VALUE, ''' -double x = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368; -'''); - } - - test_impreciseIntAsDouble_maxValue_asHex() async { - await resolveTestUnit(''' -double x = 0x100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000; -'''); - await assertHasFix(DartFixKind.CHANGE_TO_NEAREST_PRECISE_VALUE, ''' -double x = 0xFFFFFFFFFFFFF800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000; -'''); - } - - test_isNotNull() async { - await resolveTestUnit(''' -main(p) { - p is! Null; -} -'''); - await assertHasFix(DartFixKind.USE_NOT_EQ_NULL, ''' -main(p) { - p != null; -} -'''); - } - - test_isNotNull_all() async { - await resolveTestUnit(''' -main(p, q) { - p is! Null; - q is! Null; -} -'''); - await assertHasFixAllFix( - HintCode.TYPE_CHECK_IS_NOT_NULL, DartFixKind.USE_NOT_EQ_NULL, ''' -main(p, q) { - p != null; - q != null; -} -'''); - } - - test_isNull() async { - await resolveTestUnit(''' -main(p) { - p is Null; -} -'''); - await assertHasFix(DartFixKind.USE_EQ_EQ_NULL, ''' -main(p) { - p == null; -} -'''); - } - - test_isNull_all() async { - await resolveTestUnit(''' -main(p, q) { - p is Null; - q is Null; -} -'''); - await assertHasFixAllFix( - HintCode.TYPE_CHECK_IS_NULL, DartFixKind.USE_EQ_EQ_NULL, ''' -main(p, q) { - p == null; - q == null; -} -'''); - } - - test_makeEnclosingClassAbstract_declaresAbstractMethod() async { - await resolveTestUnit(''' -class A { - m(); -} -'''); - await assertHasFix(DartFixKind.MAKE_CLASS_ABSTRACT, ''' -abstract class A { - m(); -} -'''); - } - - test_makeEnclosingClassAbstract_inheritsAbstractMethod() async { - await resolveTestUnit(''' -abstract class A { - m(); -} -class B extends A { -} -'''); - await assertHasFix(DartFixKind.MAKE_CLASS_ABSTRACT, ''' -abstract class A { - m(); -} -abstract class B extends A { -} -'''); - } - - test_makeFieldNotFinal_hasType() async { - await resolveTestUnit(''' -class A { - final int fff = 1; - main() { - fff = 2; - } -} -'''); - await assertHasFix(DartFixKind.MAKE_FIELD_NOT_FINAL, ''' -class A { - int fff = 1; - main() { - fff = 2; - } -} -'''); - } - - test_makeFieldNotFinal_noType() async { - await resolveTestUnit(''' -class A { - final fff = 1; - main() { - fff = 2; - } -} -'''); - await assertHasFix(DartFixKind.MAKE_FIELD_NOT_FINAL, ''' -class A { - var fff = 1; - main() { - fff = 2; - } -} -'''); - } - - test_moveTypeArgumentsToClass_explicitConst() async { - await resolveTestUnit(''' -main() { - const C.named<int>(); -} -class C<E> { - const C.named(); -} -'''); - await assertHasFix(DartFixKind.MOVE_TYPE_ARGUMENTS_TO_CLASS, ''' -main() { - const C<int>.named(); -} -class C<E> { - const C.named(); -} -'''); - } - - test_moveTypeArgumentsToClass_explicitNew() async { - await resolveTestUnit(''' -main() { - new C.named<int>(); -} -class C<E> { - C.named(); -} -'''); - await assertHasFix(DartFixKind.MOVE_TYPE_ARGUMENTS_TO_CLASS, ''' -main() { - new C<int>.named(); -} -class C<E> { - C.named(); -} -'''); - } - - test_moveTypeArgumentsToClass_explicitNew_BAD_alreadyThere() async { - await resolveTestUnit(''' -main() { - new C<String>.named<int>(); -} -class C<E> { - C.named(); -} -'''); - await assertNoFix(DartFixKind.MOVE_TYPE_ARGUMENTS_TO_CLASS); - } - - test_moveTypeArgumentsToClass_explicitNew_BAD_wrongNumber() async { - await resolveTestUnit(''' -main() { - new C.named<int, String>(); -} -class C<E> { - C.named(); -} -'''); - await assertNoFix(DartFixKind.MOVE_TYPE_ARGUMENTS_TO_CLASS); - } - - test_moveTypeArgumentsToClass_implicitConst() async { - await resolveTestUnit(''' -main() { - const C c = C.named<int>(); -} -class C<E> { - const C.named(); -} -'''); - await assertHasFix(DartFixKind.MOVE_TYPE_ARGUMENTS_TO_CLASS, ''' -main() { - const C c = C<int>.named(); -} -class C<E> { - const C.named(); -} -'''); - } - - test_moveTypeArgumentsToClass_implicitNew() async { - await resolveTestUnit(''' -main() { - C.named<int>(); -} -class C<E> { - C.named(); -} -'''); - await assertHasFix(DartFixKind.MOVE_TYPE_ARGUMENTS_TO_CLASS, ''' -main() { - C<int>.named(); -} -class C<E> { - C.named(); -} -'''); - } - - test_noException_1() async { - await resolveTestUnit(''' -main(p) { - p i s Null; -}'''); - List<AnalysisError> errors = await _computeErrors(); - for (var error in errors) { - await _computeFixes(error); - } - } - - test_nonBoolCondition_addNotNull() async { - await resolveTestUnit(''' -main(String p) { - if (p) { - print(p); - } -} -'''); - await assertHasFix(DartFixKind.ADD_NE_NULL, ''' -main(String p) { - if (p != null) { - print(p); - } -} -'''); - } - - test_nonBoolCondition_addNotNull_all() async { - await resolveTestUnit(''' -main(String p, String q) { - if (p) { - print(p); - } - if (q) { - print(q); - } -} -'''); - await assertHasFixAllFix( - StaticTypeWarningCode.NON_BOOL_CONDITION, DartFixKind.ADD_NE_NULL, ''' -main(String p, String q) { - if (p != null) { - print(p); - } - if (q != null) { - print(q); - } -} -'''); - } - - test_removeDeadCode_condition() async { - await resolveTestUnit(''' -main(int p) { - if (true || p > 5) { - print(1); - } -} -'''); - await assertHasFix(DartFixKind.REMOVE_DEAD_CODE, ''' -main(int p) { - if (true) { - print(1); - } -} -'''); - } - - test_removeDeadCode_statements_one() async { - await resolveTestUnit(''' -int main() { - print(0); - return 42; - print(1); -} -'''); - await assertHasFix(DartFixKind.REMOVE_DEAD_CODE, ''' -int main() { - print(0); - return 42; -} -'''); - } - - test_removeDeadCode_statements_two() async { - await resolveTestUnit(''' -int main() { - print(0); - return 42; - print(1); - print(2); -} -'''); - await assertHasFix(DartFixKind.REMOVE_DEAD_CODE, ''' -int main() { - print(0); - return 42; -} -'''); - } - - test_removeParentheses_inGetterDeclaration() async { - await resolveTestUnit(''' -class A { - int get foo() => 0; -} -'''); - await assertHasFix(DartFixKind.REMOVE_PARAMETERS_IN_GETTER_DECLARATION, ''' -class A { - int get foo => 0; -} -'''); - } - - test_removeParentheses_inGetterInvocation() async { - await resolveTestUnit(''' -class A { - int get foo => 0; -} -main(A a) { - a.foo(); -} -'''); - await assertHasFix(DartFixKind.REMOVE_PARENTHESIS_IN_GETTER_INVOCATION, ''' -class A { - int get foo => 0; -} -main(A a) { - a.foo; -} -'''); - } - - test_removeTypeArguments_explicitConst() async { - await resolveTestUnit(''' -main() { - const C.named<int>(); -} -class C<E> { - const C.named(); -} -'''); - await assertHasFix(DartFixKind.REMOVE_TYPE_ARGUMENTS, ''' -main() { - const C.named(); -} -class C<E> { - const C.named(); -} -'''); - } - - test_removeTypeArguments_explicitNew() async { - await resolveTestUnit(''' -main() { - new C.named<int>(); -} -class C<E> { - C.named(); -} -'''); - await assertHasFix(DartFixKind.REMOVE_TYPE_ARGUMENTS, ''' -main() { - new C.named(); -} -class C<E> { - C.named(); -} -'''); - } - - test_removeTypeArguments_implicitConst() async { - await resolveTestUnit(''' -main() { - const C c = C.named<int>(); -} -class C<E> { - const C.named(); -} -'''); - await assertHasFix(DartFixKind.REMOVE_TYPE_ARGUMENTS, ''' -main() { - const C c = C.named(); -} -class C<E> { - const C.named(); -} -'''); - } - - test_removeTypeArguments_implicitNew() async { - await resolveTestUnit(''' -main() { - C.named<int>(); -} -class C<E> { - C.named(); -} -'''); - await assertHasFix(DartFixKind.REMOVE_TYPE_ARGUMENTS, ''' -main() { - C.named(); -} -class C<E> { - C.named(); -} -'''); - } - - test_removeUnnecessaryCast_assignment() async { - await resolveTestUnit(''' -main(Object p) { - if (p is String) { - String v = ((p as String)); - } -} -'''); - await assertHasFix(DartFixKind.REMOVE_UNNECESSARY_CAST, ''' -main(Object p) { - if (p is String) { - String v = p; - } -} -'''); - } - - test_removeUnnecessaryCast_assignment_all() async { - await resolveTestUnit(''' -main(Object p, Object q) { - if (p is String) { - String v = ((p as String)); - } - if (q is int) { - int v = ((q as int)); - } -} -'''); - await assertHasFixAllFix( - HintCode.UNNECESSARY_CAST, DartFixKind.REMOVE_UNNECESSARY_CAST, ''' -main(Object p, Object q) { - if (p is String) { - String v = p; - } - if (q is int) { - int v = q; - } -} -'''); - } - - test_removeUnusedCatchClause() async { - errorFilter = (AnalysisError error) => true; - await resolveTestUnit(''' -main() { - try { - throw 42; - } on int catch (e) { - } -} -'''); - await assertHasFix(DartFixKind.REMOVE_UNUSED_CATCH_CLAUSE, ''' -main() { - try { - throw 42; - } on int { - } -} -'''); - } - - test_removeUnusedCatchStack() async { - errorFilter = (AnalysisError error) => true; - await resolveTestUnit(''' -main() { - try { - throw 42; - } catch (e, stack) { - } -} -'''); - await assertHasFix(DartFixKind.REMOVE_UNUSED_CATCH_STACK, ''' -main() { - try { - throw 42; - } catch (e) { - } -} -'''); - } - - test_removeUnusedImport() async { - await resolveTestUnit(''' -import 'dart:math'; -main() { -} -'''); - await assertHasFix(DartFixKind.REMOVE_UNUSED_IMPORT, ''' -main() { -} -'''); - } - - test_removeUnusedImport_all() async { - await resolveTestUnit(''' -import 'dart:math'; -import 'dart:math'; -import 'dart:math'; -main() { -} -'''); - await assertHasFixAllFix( - HintCode.UNUSED_IMPORT, DartFixKind.REMOVE_UNUSED_IMPORT, ''' -main() { -} -'''); - } - - test_removeUnusedImport_all_diverseImports() async { - await resolveTestUnit(''' -import 'dart:math'; -import 'dart:math'; -import 'dart:async'; -main() { -} -'''); - await assertHasFixAllFix( - HintCode.UNUSED_IMPORT, DartFixKind.REMOVE_UNUSED_IMPORT, ''' -main() { -} -'''); - } - - test_removeUnusedImport_all_diverseImports2() async { - await resolveTestUnit(''' -import 'dart:async'; -import 'dart:math' as math; -import 'dart:async'; - -var tau = math.pi * 2; - -main() { -} -'''); - await assertHasFixAllFix( - HintCode.UNUSED_IMPORT, DartFixKind.REMOVE_UNUSED_IMPORT, ''' -import 'dart:math' as math; - -var tau = math.pi * 2; - -main() { -} -'''); - } - - test_removeUnusedImport_all_singleLine() async { - await resolveTestUnit(''' -import 'dart:math'; import 'dart:math'; import 'dart:math'; -main() { -} -'''); - await assertHasFixAllFix( - HintCode.UNUSED_IMPORT, DartFixKind.REMOVE_UNUSED_IMPORT, ''' -main() { -} -'''); - } - - test_removeUnusedImport_anotherImportOnLine() async { - await resolveTestUnit(''' -import 'dart:math'; import 'dart:async'; - -main() { - Future f; -} -'''); - await assertHasFix(DartFixKind.REMOVE_UNUSED_IMPORT, ''' -import 'dart:async'; - -main() { - Future f; -} -'''); - } - - test_removeUnusedImport_severalLines() async { - await resolveTestUnit(''' -import - 'dart:math'; -main() { -} -'''); - await assertHasFix(DartFixKind.REMOVE_UNUSED_IMPORT, ''' -main() { -} -'''); - } - - test_replaceVarWithDynamic() async { - errorFilter = (AnalysisError error) { - return error.errorCode == ParserErrorCode.VAR_AS_TYPE_NAME; - }; - await resolveTestUnit(''' -class A { - Map<String, var> m; -} -'''); - await assertHasFix(DartFixKind.REPLACE_VAR_WITH_DYNAMIC, ''' -class A { - Map<String, dynamic> m; -} -'''); - } - - test_replaceWithConstInstanceCreation_explicitNew() async { - await resolveTestUnit(''' -class A { - const A(); -} -const a = new A(); -'''); - await assertHasFix(DartFixKind.USE_CONST, ''' -class A { - const A(); -} -const a = const A(); -'''); - } - - test_undefinedClass_useSimilar_BAD_prefixed() async { - await resolveTestUnit(''' -import 'dart:async' as c; -main() { - c.Fture v = null; -} -'''); - await assertHasFix(DartFixKind.CHANGE_TO, ''' -import 'dart:async' as c; -main() { - c.Future v = null; -} -'''); - } - - test_undefinedClass_useSimilar_fromImport() async { - await resolveTestUnit(''' -main() { - Stirng s = 'abc'; -} -'''); - await assertHasFix(DartFixKind.CHANGE_TO, ''' -main() { - String s = 'abc'; -} -'''); - } - - test_undefinedClass_useSimilar_fromThisLibrary() async { - await resolveTestUnit(''' -class MyClass {} -main() { - MyCalss v = null; -} -'''); - await assertHasFix(DartFixKind.CHANGE_TO, ''' -class MyClass {} -main() { - MyClass v = null; -} -'''); - } - - test_undefinedFunction_create_bottomArgument() async { - await resolveTestUnit(''' -main() { - test(throw 42); -} -'''); - await assertHasFix(DartFixKind.CREATE_FUNCTION, ''' -main() { - test(throw 42); -} - -void test(param0) { -} -'''); - } - - test_undefinedFunction_create_duplicateArgumentNames() async { - await resolveTestUnit(''' -class C { - int x; -} - -foo(C c1, C c2) { - bar(c1.x, c2.x); -} -'''); - await assertHasFix(DartFixKind.CREATE_FUNCTION, ''' -class C { - int x; -} - -foo(C c1, C c2) { - bar(c1.x, c2.x); -} - -void bar(int x, int x2) { -} -'''); - } - - test_undefinedFunction_create_dynamicArgument() async { - await resolveTestUnit(''' -main() { - dynamic v; - test(v); -} -'''); - await assertHasFix(DartFixKind.CREATE_FUNCTION, ''' -main() { - dynamic v; - test(v); -} - -void test(v) { -} -'''); - } - - test_undefinedFunction_create_dynamicReturnType() async { - await resolveTestUnit(''' -main() { - dynamic v = test(); -} -'''); - await assertHasFix(DartFixKind.CREATE_FUNCTION, ''' -main() { - dynamic v = test(); -} - -test() { -} -'''); - } - - test_undefinedFunction_create_fromFunction() async { - await resolveTestUnit(''' -main() { - int v = myUndefinedFunction(1, 2.0, '3'); -} -'''); - await assertHasFix(DartFixKind.CREATE_FUNCTION, ''' -main() { - int v = myUndefinedFunction(1, 2.0, '3'); -} - -int myUndefinedFunction(int i, double d, String s) { -} -'''); - } - - test_undefinedFunction_create_fromMethod() async { - await resolveTestUnit(''' -class A { - main() { - int v = myUndefinedFunction(1, 2.0, '3'); - } -} -'''); - await assertHasFix(DartFixKind.CREATE_FUNCTION, ''' -class A { - main() { - int v = myUndefinedFunction(1, 2.0, '3'); - } -} - -int myUndefinedFunction(int i, double d, String s) { -} -'''); - } - - test_undefinedFunction_create_generic_BAD() async { - await resolveTestUnit(''' -class A<T> { - Map<int, T> items; - main() { - process(items); - } -} -'''); - await assertHasFix(DartFixKind.CREATE_FUNCTION, ''' -class A<T> { - Map<int, T> items; - main() { - process(items); - } -} - -void process(Map items) { -} -'''); - } - - test_undefinedFunction_create_generic_OK() async { - await resolveTestUnit(''' -class A { - List<int> items; - main() { - process(items); - } -} -'''); - await assertHasFix(DartFixKind.CREATE_FUNCTION, ''' -class A { - List<int> items; - main() { - process(items); - } -} - -void process(List<int> items) { -} -'''); - _assertLinkedGroup( - change.linkedEditGroups[2], - ['List<int> items) {'], - expectedSuggestions(LinkedEditSuggestionKind.TYPE, - ['List<int>', 'Iterable<int>', 'Object'])); - } - - test_undefinedFunction_create_importType() async { - addSource('/project/lib.dart', r''' -library lib; -import 'dart:async'; -Future getFuture() => null; -'''); - await resolveTestUnit(''' -import 'lib.dart'; -main() { - test(getFuture()); -} -'''); - await assertHasFix(DartFixKind.CREATE_FUNCTION, ''' -import 'dart:async'; - -import 'lib.dart'; -main() { - test(getFuture()); -} - -void test(Future future) { -} -'''); - } - - test_undefinedFunction_create_nullArgument() async { - await resolveTestUnit(''' -main() { - test(null); -} -'''); - await assertHasFix(DartFixKind.CREATE_FUNCTION, ''' -main() { - test(null); -} - -void test(param0) { -} -'''); - } - - test_undefinedFunction_create_returnType_bool_expressions() async { - await assert_undefinedFunction_create_returnType_bool("!test();"); - await assert_undefinedFunction_create_returnType_bool("b && test();"); - await assert_undefinedFunction_create_returnType_bool("test() && b;"); - await assert_undefinedFunction_create_returnType_bool("b || test();"); - await assert_undefinedFunction_create_returnType_bool("test() || b;"); - } - - test_undefinedFunction_create_returnType_bool_statements() async { - await assert_undefinedFunction_create_returnType_bool("assert ( test() );"); - await assert_undefinedFunction_create_returnType_bool("if ( test() ) {}"); - await assert_undefinedFunction_create_returnType_bool( - "while ( test() ) {}"); - await assert_undefinedFunction_create_returnType_bool( - "do {} while ( test() );"); - } - - test_undefinedFunction_create_returnType_fromAssignment_eq() async { - await resolveTestUnit(''' -main() { - int v; - v = myUndefinedFunction(); -} -'''); - await assertHasFix(DartFixKind.CREATE_FUNCTION, ''' -main() { - int v; - v = myUndefinedFunction(); -} - -int myUndefinedFunction() { -} -'''); - } - - test_undefinedFunction_create_returnType_fromAssignment_plusEq() async { - await resolveTestUnit(''' -main() { - int v; - v += myUndefinedFunction(); -} -'''); - await assertHasFix(DartFixKind.CREATE_FUNCTION, ''' -main() { - int v; - v += myUndefinedFunction(); -} - -num myUndefinedFunction() { -} -'''); - } - - test_undefinedFunction_create_returnType_fromBinary_right() async { - await resolveTestUnit(''' -main() { - 0 + myUndefinedFunction(); -} -'''); - await assertHasFix(DartFixKind.CREATE_FUNCTION, ''' -main() { - 0 + myUndefinedFunction(); -} - -num myUndefinedFunction() { -} -'''); - } - - test_undefinedFunction_create_returnType_fromInitializer() async { - await resolveTestUnit(''' -main() { - int v = myUndefinedFunction(); -} -'''); - await assertHasFix(DartFixKind.CREATE_FUNCTION, ''' -main() { - int v = myUndefinedFunction(); -} - -int myUndefinedFunction() { -} -'''); - } - - test_undefinedFunction_create_returnType_fromInvocationArgument() async { - await resolveTestUnit(''' -foo(int p) {} -main() { - foo( myUndefinedFunction() ); -} -'''); - await assertHasFix(DartFixKind.CREATE_FUNCTION, ''' -foo(int p) {} -main() { - foo( myUndefinedFunction() ); -} - -int myUndefinedFunction() { -} -'''); - } - - test_undefinedFunction_create_returnType_fromReturn() async { - await resolveTestUnit(''' -int main() { - return myUndefinedFunction(); -} -'''); - await assertHasFix(DartFixKind.CREATE_FUNCTION, ''' -int main() { - return myUndefinedFunction(); -} - -int myUndefinedFunction() { -} -'''); - } - - test_undefinedFunction_create_returnType_void() async { - await resolveTestUnit(''' -main() { - myUndefinedFunction(); -} -'''); - await assertHasFix(DartFixKind.CREATE_FUNCTION, ''' -main() { - myUndefinedFunction(); -} - -void myUndefinedFunction() { -} -'''); - } - - test_undefinedFunction_useSimilar_fromImport() async { - await resolveTestUnit(''' -main() { - pritn(0); -} -'''); - await assertHasFix(DartFixKind.CHANGE_TO, ''' -main() { - print(0); -} -'''); - } - - test_undefinedFunction_useSimilar_prefixed_fromImport() async { - await resolveTestUnit(''' -import 'dart:core' as c; -main() { - c.prnt(42); -} -'''); - await assertHasFix(DartFixKind.CHANGE_TO, ''' -import 'dart:core' as c; -main() { - c.print(42); -} -'''); - } - - test_undefinedFunction_useSimilar_prefixed_ignoreLocal() async { - await resolveTestUnit(''' -import 'dart:async' as c; -main() { - c.main(); -} -'''); - await assertNoFix(DartFixKind.CHANGE_TO); - } - - test_undefinedFunction_useSimilar_thisLibrary() async { - await resolveTestUnit(''' -myFunction() {} -main() { - myFuntcion(); -} -'''); - await assertHasFix(DartFixKind.CHANGE_TO, ''' -myFunction() {} -main() { - myFunction(); -} -'''); - } - - test_undefinedGetter_useSimilar_hint() async { - await resolveTestUnit(''' -class A { - int myField; -} -main(A a) { - var x = a; - print(x.myFild); -} -'''); - await assertHasFix(DartFixKind.CHANGE_TO, ''' -class A { - int myField; -} -main(A a) { - var x = a; - print(x.myField); -} -'''); - } - - test_undefinedGetter_useSimilar_qualified() async { - await resolveTestUnit(''' -class A { - int myField; -} -main(A a) { - print(a.myFild); -} -'''); - await assertHasFix(DartFixKind.CHANGE_TO, ''' -class A { - int myField; -} -main(A a) { - print(a.myField); -} -'''); - } - - test_undefinedGetter_useSimilar_qualified_static() async { - await resolveTestUnit(''' -class A { - static int MY_NAME = 1; -} -main() { - A.MY_NAM; -} -'''); - await assertHasFix(DartFixKind.CHANGE_TO, ''' -class A { - static int MY_NAME = 1; -} -main() { - A.MY_NAME; -} -'''); - } - - test_undefinedGetter_useSimilar_unqualified() async { - await resolveTestUnit(''' -class A { - int myField; - main() { - print(myFild); - } -} -'''); - await assertHasFix(DartFixKind.CHANGE_TO, ''' -class A { - int myField; - main() { - print(myField); - } -} -'''); - } - - test_undefinedMethod_create_BAD_inSDK() async { - await resolveTestUnit(''' -main() { - List.foo(); -} -'''); - await assertNoFix(DartFixKind.CREATE_METHOD); - } - - test_undefinedMethod_create_BAD_targetIsEnum() async { - await resolveTestUnit(''' -enum MyEnum {A, B} -main() { - MyEnum.foo(); -} -'''); - await assertNoFix(DartFixKind.CREATE_METHOD); - } - - test_undefinedMethod_create_generic_BAD_argumentType() async { - await resolveTestUnit(''' -class A<T> { - B b; - Map<int, T> items; - main() { - b.process(items); - } -} - -class B { -} -'''); - await assertHasFix(DartFixKind.CREATE_METHOD, ''' -class A<T> { - B b; - Map<int, T> items; - main() { - b.process(items); - } -} - -class B { - void process(Map items) {} -} -'''); - } - - test_undefinedMethod_create_generic_BAD_returnType() async { - await resolveTestUnit(''' -class A<T> { - main() { - T t = new B().compute(); - } -} - -class B { -} -'''); - await assertHasFix(DartFixKind.CREATE_METHOD, ''' -class A<T> { - main() { - T t = new B().compute(); - } -} - -class B { - compute() {} -} -'''); - } - - test_undefinedMethod_create_generic_OK_literal() async { - await resolveTestUnit(''' -class A { - B b; - List<int> items; - main() { - b.process(items); - } -} - -class B {} -'''); - await assertHasFix(DartFixKind.CREATE_METHOD, ''' -class A { - B b; - List<int> items; - main() { - b.process(items); - } -} - -class B { - void process(List<int> items) {} -} -'''); - } - - test_undefinedMethod_create_generic_OK_local() async { - await resolveTestUnit(''' -class A<T> { - List<T> items; - main() { - process(items); - } -} -'''); - await assertHasFix(DartFixKind.CREATE_METHOD, ''' -class A<T> { - List<T> items; - main() { - process(items); - } - - void process(List<T> items) {} -} -'''); - } - - test_undefinedMethod_createQualified_emptyClassBody() async { - await resolveTestUnit(''' -class A {} -main() { - A.myUndefinedMethod(); -} -'''); - await assertHasFix(DartFixKind.CREATE_METHOD, ''' -class A { - static void myUndefinedMethod() {} -} -main() { - A.myUndefinedMethod(); -} -'''); - } - - test_undefinedMethod_createQualified_fromClass() async { - await resolveTestUnit(''' -class A { -} -main() { - A.myUndefinedMethod(); -} -'''); - await assertHasFix(DartFixKind.CREATE_METHOD, ''' -class A { - static void myUndefinedMethod() {} -} -main() { - A.myUndefinedMethod(); -} -'''); - } - - test_undefinedMethod_createQualified_fromClass_hasOtherMember() async { - await resolveTestUnit(''' -class A { - foo() {} -} -main() { - A.myUndefinedMethod(); -} -'''); - await assertHasFix(DartFixKind.CREATE_METHOD, ''' -class A { - foo() {} - - static void myUndefinedMethod() {} -} -main() { - A.myUndefinedMethod(); -} -'''); - } - - test_undefinedMethod_createQualified_fromInstance() async { - await resolveTestUnit(''' -class A { -} -main(A a) { - a.myUndefinedMethod(); -} -'''); - await assertHasFix(DartFixKind.CREATE_METHOD, ''' -class A { - void myUndefinedMethod() {} -} -main(A a) { - a.myUndefinedMethod(); -} -'''); - } - - test_undefinedMethod_createQualified_targetIsFunctionType() async { - await resolveTestUnit(''' -typedef A(); -main() { - A.myUndefinedMethod(); -} -'''); - await assertNoFix(DartFixKind.CREATE_METHOD); - } - - test_undefinedMethod_createQualified_targetIsUnresolved() async { - await resolveTestUnit(''' -main() { - NoSuchClass.myUndefinedMethod(); -} -'''); - await assertNoFix(DartFixKind.CREATE_METHOD); - } - - test_undefinedMethod_createUnqualified_duplicateArgumentNames() async { - await resolveTestUnit(''' -class C { - int x; -} - -class D { - foo(C c1, C c2) { - bar(c1.x, c2.x); - } -}'''); - await assertHasFix(DartFixKind.CREATE_METHOD, ''' -class C { - int x; -} - -class D { - foo(C c1, C c2) { - bar(c1.x, c2.x); - } - - void bar(int x, int x2) {} -}'''); - } - - test_undefinedMethod_createUnqualified_parameters() async { - await resolveTestUnit(''' -class A { - main() { - myUndefinedMethod(0, 1.0, '3'); - } -} -'''); - await assertHasFix(DartFixKind.CREATE_METHOD, ''' -class A { - main() { - myUndefinedMethod(0, 1.0, '3'); - } - - void myUndefinedMethod(int i, double d, String s) {} -} -'''); - // linked positions - int index = 0; - _assertLinkedGroup( - change.linkedEditGroups[index++], ['void myUndefinedMethod(']); - _assertLinkedGroup(change.linkedEditGroups[index++], - ['myUndefinedMethod(0', 'myUndefinedMethod(int']); - _assertLinkedGroup( - change.linkedEditGroups[index++], - ['int i'], - expectedSuggestions(LinkedEditSuggestionKind.TYPE, - ['int', 'num', 'Object', 'Comparable<num>'])); - _assertLinkedGroup(change.linkedEditGroups[index++], ['i,']); - _assertLinkedGroup( - change.linkedEditGroups[index++], - ['double d'], - expectedSuggestions(LinkedEditSuggestionKind.TYPE, - ['double', 'num', 'Object', 'Comparable<num>'])); - _assertLinkedGroup(change.linkedEditGroups[index++], ['d,']); - _assertLinkedGroup( - change.linkedEditGroups[index++], - ['String s'], - expectedSuggestions(LinkedEditSuggestionKind.TYPE, - ['String', 'Object', 'Comparable<String>'])); - _assertLinkedGroup(change.linkedEditGroups[index++], ['s)']); - } - - test_undefinedMethod_createUnqualified_parameters_named() async { - await resolveTestUnit(''' -class A { - main() { - myUndefinedMethod(0, bbb: 1.0, ccc: '2'); - } -} -'''); - await assertHasFix(DartFixKind.CREATE_METHOD, ''' -class A { - main() { - myUndefinedMethod(0, bbb: 1.0, ccc: '2'); - } - - void myUndefinedMethod(int i, {double bbb, String ccc}) {} -} -'''); - // linked positions - int index = 0; - _assertLinkedGroup( - change.linkedEditGroups[index++], ['void myUndefinedMethod(']); - _assertLinkedGroup(change.linkedEditGroups[index++], - ['myUndefinedMethod(0', 'myUndefinedMethod(int']); - _assertLinkedGroup( - change.linkedEditGroups[index++], - ['int i'], - expectedSuggestions(LinkedEditSuggestionKind.TYPE, - ['int', 'num', 'Object', 'Comparable<num>'])); - _assertLinkedGroup(change.linkedEditGroups[index++], ['i,']); - _assertLinkedGroup( - change.linkedEditGroups[index++], - ['double bbb'], - expectedSuggestions(LinkedEditSuggestionKind.TYPE, - ['double', 'num', 'Object', 'Comparable<num>'])); - _assertLinkedGroup( - change.linkedEditGroups[index++], - ['String ccc'], - expectedSuggestions(LinkedEditSuggestionKind.TYPE, - ['String', 'Object', 'Comparable<String>'])); - } - - test_undefinedMethod_createUnqualified_returnType() async { - await resolveTestUnit(''' -class A { - main() { - int v = myUndefinedMethod(); - } -} -'''); - await assertHasFix(DartFixKind.CREATE_METHOD, ''' -class A { - main() { - int v = myUndefinedMethod(); - } - - int myUndefinedMethod() {} -} -'''); - // linked positions - _assertLinkedGroup(change.linkedEditGroups[0], ['int myUndefinedMethod(']); - _assertLinkedGroup(change.linkedEditGroups[1], - ['myUndefinedMethod();', 'myUndefinedMethod() {']); - } - - test_undefinedMethod_createUnqualified_staticFromField() async { - await resolveTestUnit(''' -class A { - static var f = myUndefinedMethod(); -} -'''); - await assertHasFix(DartFixKind.CREATE_METHOD, ''' -class A { - static var f = myUndefinedMethod(); - - static myUndefinedMethod() {} -} -'''); - } - - test_undefinedMethod_createUnqualified_staticFromMethod() async { - await resolveTestUnit(''' -class A { - static main() { - myUndefinedMethod(); - } -} -'''); - await assertHasFix(DartFixKind.CREATE_METHOD, ''' -class A { - static main() { - myUndefinedMethod(); - } - - static void myUndefinedMethod() {} -} -'''); - } - - test_undefinedMethod_hint_createQualified_fromInstance() async { - await resolveTestUnit(''' -class A { -} -main() { - var a = new A(); - a.myUndefinedMethod(); -} -'''); - await assertHasFix(DartFixKind.CREATE_METHOD, ''' -class A { - void myUndefinedMethod() {} -} -main() { - var a = new A(); - a.myUndefinedMethod(); -} -'''); - } - - test_undefinedMethod_parameterType_differentPrefixInTargetUnit() async { - String code2 = r''' -library test2; -import 'test3.dart' as bbb; -export 'test3.dart'; -class D { -} -'''; - addSource('/project/test2.dart', code2); - addSource('/project/test3.dart', r''' -library test3; -class E {} -'''); - await resolveTestUnit(''' -library test; -import 'test2.dart' as aaa; -main(aaa.D d, aaa.E e) { - d.foo(e); -} -'''); - AnalysisError error = await _findErrorToFix(); - fix = await _assertHasFix(DartFixKind.CREATE_METHOD, error); - change = fix.change; - // apply to "test2.dart" - List<SourceFileEdit> fileEdits = change.edits; - expect(fileEdits, hasLength(1)); - SourceFileEdit fileEdit = change.edits[0]; - expect(fileEdit.file, convertPath('/project/test2.dart')); - expect(SourceEdit.applySequence(code2, fileEdit.edits), r''' -library test2; -import 'test3.dart' as bbb; -export 'test3.dart'; -class D { - void foo(bbb.E e) {} -} -'''); - } - - test_undefinedMethod_parameterType_inTargetUnit() async { - String code2 = r''' -library test2; -class D { -} -class E {} -'''; - addSource('/project/test2.dart', code2); - await resolveTestUnit(''' -library test; -import 'test2.dart' as test2; -main(test2.D d, test2.E e) { - d.foo(e); -} -'''); - AnalysisError error = await _findErrorToFix(); - fix = await _assertHasFix(DartFixKind.CREATE_METHOD, error); - change = fix.change; - // apply to "test2.dart" - List<SourceFileEdit> fileEdits = change.edits; - expect(fileEdits, hasLength(1)); - SourceFileEdit fileEdit = change.edits[0]; - expect(fileEdit.file, convertPath('/project/test2.dart')); - expect(SourceEdit.applySequence(code2, fileEdit.edits), r''' -library test2; -class D { - void foo(E e) {} -} -class E {} -'''); - } - - test_undefinedMethod_useSimilar_ignoreOperators() async { - await resolveTestUnit(''' -main(Object object) { - object.then(); -} -'''); - await assertNoFix(DartFixKind.CHANGE_TO); - } - - test_undefinedMethod_useSimilar_qualified() async { - await resolveTestUnit(''' -class A { - myMethod() {} -} -main() { - A a = new A(); - a.myMehtod(); -} -'''); - await assertHasFix(DartFixKind.CHANGE_TO, ''' -class A { - myMethod() {} -} -main() { - A a = new A(); - a.myMethod(); -} -'''); - } - - test_undefinedMethod_useSimilar_unqualified_superClass() async { - await resolveTestUnit(''' -class A { - myMethod() {} -} -class B extends A { - main() { - myMehtod(); - } -} -'''); - await assertHasFix(DartFixKind.CHANGE_TO, ''' -class A { - myMethod() {} -} -class B extends A { - main() { - myMethod(); - } -} -'''); - } - - test_undefinedMethod_useSimilar_unqualified_thisClass() async { - await resolveTestUnit(''' -class A { - myMethod() {} - main() { - myMehtod(); - } -} -'''); - await assertHasFix(DartFixKind.CHANGE_TO, ''' -class A { - myMethod() {} - main() { - myMethod(); - } -} -'''); - } - - test_undefinedParameter_convertFlutterChild_BAD_listNotWidget() async { - addFlutterPackage(); - await resolveTestUnit(''' -import 'package:flutter/widgets.dart'; -build() { - return new Container( - child: new Row( - child: <Widget>[ - new Container(), - null, - ], - ), - ); -} -'''); - await assertNoFix(DartFixKind.CONVERT_FLUTTER_CHILD); - } - - test_undefinedParameter_convertFlutterChild_OK_hasList() async { - addFlutterPackage(); - await resolveTestUnit(''' -import 'package:flutter/widgets.dart'; -build() { - return new Container( - child: new Row( - child: [ - new Text('111'), - new Text('222'), - ], - ), - ); -} -'''); - await assertHasFix(DartFixKind.CONVERT_FLUTTER_CHILD, ''' -import 'package:flutter/widgets.dart'; -build() { - return new Container( - child: new Row( - children: <Widget>[ - new Text('111'), - new Text('222'), - ], - ), - ); -} -'''); - } - - test_undefinedParameter_convertFlutterChild_OK_hasTypedList() async { - addFlutterPackage(); - await resolveTestUnit(''' -import 'package:flutter/widgets.dart'; -build() { - return new Container( - child: new Row( - child: <Widget>[ - new Text('111'), - new Text('222'), - ], - ), - ); -} -'''); - await assertHasFix(DartFixKind.CONVERT_FLUTTER_CHILD, ''' -import 'package:flutter/widgets.dart'; -build() { - return new Container( - child: new Row( - children: <Widget>[ - new Text('111'), - new Text('222'), - ], - ), - ); -} -'''); - } - - test_undefinedParameter_convertFlutterChild_OK_multiLine() async { - addFlutterPackage(); - await resolveTestUnit(''' -import 'package:flutter/material.dart'; -build() { - return new Scaffold( - body: new Row( - child: new Container( - width: 200.0, - height: 300.0, - ), - ), - ); -} -'''); - await assertHasFix(DartFixKind.CONVERT_FLUTTER_CHILD, ''' -import 'package:flutter/material.dart'; -build() { - return new Scaffold( - body: new Row( - children: <Widget>[ - new Container( - width: 200.0, - height: 300.0, - ), - ], - ), - ); -} -'''); - } - - test_undefinedParameter_convertFlutterChild_OK_widgetVariable() async { - addFlutterPackage(); - await resolveTestUnit(''' -import 'package:flutter/material.dart'; -build() { - var text = new Text('foo'); - new Row( - child: text, - ); -} -'''); - await assertHasFix(DartFixKind.CONVERT_FLUTTER_CHILD, ''' -import 'package:flutter/material.dart'; -build() { - var text = new Text('foo'); - new Row( - children: <Widget>[text], - ); -} -'''); - } - - test_undefinedParameter_convertFlutterChildren_BAD_notWidget() async { - addFlutterPackage(); - await resolveTestUnit(''' -import 'package:flutter/widgets.dart'; -build() { - return new Center( - children: [ - new Object(), - ], - ); -} -'''); - await assertNoFix(DartFixKind.CONVERT_FLUTTER_CHILDREN); - } - - test_undefinedParameter_convertFlutterChildren_OK_multiLine() async { - addFlutterPackage(); - await resolveTestUnit(''' -import 'package:flutter/widgets.dart'; -build() { - return new Center( - children: [ - new Container( - width: 200.0, - height: 300.0, - ), - ], - ); -} -'''); - await assertHasFix(DartFixKind.CONVERT_FLUTTER_CHILDREN, ''' -import 'package:flutter/widgets.dart'; -build() { - return new Center( - child: new Container( - width: 200.0, - height: 300.0, - ), - ); -} -'''); - } - - test_undefinedParameter_convertFlutterChildren_OK_singleLine() async { - addFlutterPackage(); - await resolveTestUnit(''' -import 'package:flutter/widgets.dart'; -build() { - return new Center( - children: [ - new Text('foo'), - ], - ); -} -'''); - await assertHasFix(DartFixKind.CONVERT_FLUTTER_CHILDREN, ''' -import 'package:flutter/widgets.dart'; -build() { - return new Center( - child: new Text('foo'), - ); -} -'''); - } - - test_undefinedParameter_convertFlutterChildren_OK_singleLine2() async { - addFlutterPackage(); - await resolveTestUnit(''' -import 'package:flutter/widgets.dart'; -build() { - var text = new Text('foo'); - new Center( - children: [text], - ); -} -'''); - await assertHasFix(DartFixKind.CONVERT_FLUTTER_CHILDREN, ''' -import 'package:flutter/widgets.dart'; -build() { - var text = new Text('foo'); - new Center( - child: text, - ); -} -'''); - } - - test_undefinedSetter_useSimilar_hint() async { - await resolveTestUnit(''' -class A { - int myField; -} -main(A a) { - var x = a; - x.myFild = 42; -} -'''); - await assertHasFix(DartFixKind.CHANGE_TO, ''' -class A { - int myField; -} -main(A a) { - var x = a; - x.myField = 42; -} -'''); - } - - test_undefinedSetter_useSimilar_qualified() async { - await resolveTestUnit(''' -class A { - int myField; -} -main(A a) { - a.myFild = 42; -} -'''); - await assertHasFix(DartFixKind.CHANGE_TO, ''' -class A { - int myField; -} -main(A a) { - a.myField = 42; -} -'''); - } - - test_undefinedSetter_useSimilar_unqualified() async { - await resolveTestUnit(''' -class A { - int myField; - main() { - myFild = 42; - } -} -'''); - await assertHasFix(DartFixKind.CHANGE_TO, ''' -class A { - int myField; - main() { - myField = 42; - } -} -'''); - } - - test_useEffectiveIntegerDivision() async { - await resolveTestUnit(''' -main() { - var a = 5; - var b = 2; - print((a / b).toInt()); -} -'''); - await assertHasFix(DartFixKind.USE_EFFECTIVE_INTEGER_DIVISION, ''' -main() { - var a = 5; - var b = 2; - print(a ~/ b); -} -'''); - } - - test_useImportPrefix_withClass() async { - await resolveTestUnit(''' -import 'dart:async' as pref; -main() { - pref.Stream s = null; - Future f = null; -} -'''); - await assertHasFix(DartFixKind.IMPORT_LIBRARY_PREFIX, ''' -import 'dart:async' as pref; -main() { - pref.Stream s = null; - pref.Future f = null; -} -'''); - } - - test_useImportPrefix_withTopLevelVariable() async { - await resolveTestUnit(''' -import 'dart:math' as pref; -main() { - print(pref.E); - print(PI); -} -'''); - await assertHasFix(DartFixKind.IMPORT_LIBRARY_PREFIX, ''' -import 'dart:math' as pref; -main() { - print(pref.E); - print(pref.PI); -} -'''); - } - - void _addMetaPackageSource() { - addPackageSource('meta', 'meta.dart', r''' -library meta; - -const Required required = const Required(); - -class Required { - final String reason; - const Required([this.reason]); -} -'''); - } -} - -@reflectiveTest -class LintFixTest extends BaseFixProcessorTest { - AnalysisError error; - - Future applyFix(FixKind kind) async { - fix = await _assertHasFix(kind, error); - change = fix.change; - // apply to "file" - List<SourceFileEdit> fileEdits = change.edits; - expect(fileEdits, hasLength(1)); - resultCode = SourceEdit.applySequence(testCode, change.edits[0].edits); - } - - @override - assertNoFix(FixKind kind) async { - await _assertNoFix(kind, error); - } - - Future<void> findLint(String src, String lintCode, {int length: 1}) async { - int errorOffset = src.indexOf('/*LINT*/'); - await resolveTestUnit(src.replaceAll('/*LINT*/', '')); - error = new AnalysisError( - resolutionMap.elementDeclaredByCompilationUnit(testUnit).source, - errorOffset, - length, - new LintCode(lintCode, '<ignored>')); - } - - test_addRequiredAnnotation() async { - String src = ''' -void function({String /*LINT*/param}) { - assert(param != null); -} -'''; - await findLint(src, LintNames.always_require_non_null_named_parameters); - await applyFix(DartFixKind.LINT_ADD_REQUIRED); - verifyResult(''' -void function({@required String param}) { - assert(param != null); -} -'''); - } - - test_isNotEmpty() async { - String src = ''' -f(c) { - if (/*LINT*/!c.isEmpty) {} -} -'''; - await findLint(src, LintNames.prefer_is_not_empty); - - await applyFix(DartFixKind.USE_IS_NOT_EMPTY); - - verifyResult(''' -f(c) { - if (c.isNotEmpty) {} -} -'''); - } - - test_lint_addMissingOverride_field() async { - String src = ''' -class abstract Test { - int get t; -} -class Sub extends Test { - int /*LINT*/t = 42; -} -'''; - await findLint(src, LintNames.annotate_overrides); - - await applyFix(DartFixKind.LINT_ADD_OVERRIDE); - - verifyResult(''' -class abstract Test { - int get t; -} -class Sub extends Test { - @override - int t = 42; -} -'''); - } - - test_lint_addMissingOverride_getter() async { - String src = ''' -class Test { - int get t => null; -} -class Sub extends Test { - int get /*LINT*/t => null; -} -'''; - await findLint(src, LintNames.annotate_overrides); - - await applyFix(DartFixKind.LINT_ADD_OVERRIDE); - - verifyResult(''' -class Test { - int get t => null; -} -class Sub extends Test { - @override - int get t => null; -} -'''); - } - - test_lint_addMissingOverride_method() async { - String src = ''' -class Test { - void t() { } -} -class Sub extends Test { - void /*LINT*/t() { } -} -'''; - await findLint(src, LintNames.annotate_overrides); - - await applyFix(DartFixKind.LINT_ADD_OVERRIDE); - - verifyResult(''' -class Test { - void t() { } -} -class Sub extends Test { - @override - void t() { } -} -'''); - } - - test_lint_addMissingOverride_method_with_doc_comment() async { - String src = ''' -class Test { - void t() { } -} -class Sub extends Test { - /// Doc comment. - void /*LINT*/t() { } -} -'''; - await findLint(src, LintNames.annotate_overrides); - - await applyFix(DartFixKind.LINT_ADD_OVERRIDE); - - verifyResult(''' -class Test { - void t() { } -} -class Sub extends Test { - /// Doc comment. - @override - void t() { } -} -'''); - } - - test_lint_addMissingOverride_method_with_doc_comment_2() async { - String src = ''' -class Test { - void t() { } -} -class Sub extends Test { - /** - * Doc comment. - */ - void /*LINT*/t() { } -} -'''; - await findLint(src, LintNames.annotate_overrides); - - await applyFix(DartFixKind.LINT_ADD_OVERRIDE); - - verifyResult(''' -class Test { - void t() { } -} -class Sub extends Test { - /** - * Doc comment. - */ - @override - void t() { } -} -'''); - } - - test_lint_addMissingOverride_method_with_doc_comment_and_metadata() async { - String src = ''' -class Test { - void t() { } -} -class Sub extends Test { - /// Doc comment. - @foo - void /*LINT*/t() { } -} -'''; - await findLint(src, LintNames.annotate_overrides); - - await applyFix(DartFixKind.LINT_ADD_OVERRIDE); - - verifyResult(''' -class Test { - void t() { } -} -class Sub extends Test { - /// Doc comment. - @override - @foo - void t() { } -} -'''); - } - - test_lint_addMissingOverride_method_with_non_doc_comment() async { - String src = ''' -class Test { - void t() { } -} -class Sub extends Test { - // Non-doc comment. - void /*LINT*/t() { } -} -'''; - await findLint(src, LintNames.annotate_overrides); - - await applyFix(DartFixKind.LINT_ADD_OVERRIDE); - - verifyResult(''' -class Test { - void t() { } -} -class Sub extends Test { - // Non-doc comment. - @override - void t() { } -} -'''); - } - - test_lint_removeInterpolationBraces() async { - String src = r''' -main() { - var v = 42; - print('v: /*LINT*/${ v}'); -} -'''; - await findLint(src, LintNames.unnecessary_brace_in_string_interp, - length: 4); - await applyFix(DartFixKind.LINT_REMOVE_INTERPOLATION_BRACES); - verifyResult(r''' -main() { - var v = 42; - print('v: $v'); -} -'''); - } - - test_makeFieldFinal_noKeyword() async { - String src = ''' -class C { - /*LINT*/f = 2; -} -'''; - await findLint(src, LintNames.prefer_final_fields); - - await applyFix(DartFixKind.MAKE_FINAL); - - verifyResult(''' -class C { - final f = 2; -} -'''); - } - - test_makeFieldFinal_type() async { - String src = ''' -class C { - int /*LINT*/f = 2; -} -'''; - await findLint(src, LintNames.prefer_final_fields); - - await applyFix(DartFixKind.MAKE_FINAL); - - verifyResult(''' -class C { - final int f = 2; -} -'''); - } - - test_makeFieldFinal_var() async { - String src = ''' -class C { - var /*LINT*/f = 2; -} -'''; - await findLint(src, LintNames.prefer_final_fields); - - await applyFix(DartFixKind.MAKE_FINAL); - - verifyResult(''' -class C { - final f = 2; -} -'''); - } - - test_makeLocalFinal_type() async { - String src = ''' -bad() { - int /*LINT*/x = 2; -} -'''; - await findLint(src, LintNames.prefer_final_locals); - - await applyFix(DartFixKind.MAKE_FINAL); - - verifyResult(''' -bad() { - final int x = 2; -} -'''); - } - - test_makeLocalFinal_var() async { - String src = ''' -bad() { - var /*LINT*/x = 2; -} -'''; - await findLint(src, LintNames.prefer_final_locals); - - await applyFix(DartFixKind.MAKE_FINAL); - - verifyResult(''' -bad() { - final x = 2; -} -'''); - } - - test_removeAwait_intLiteral() async { - String src = ''' -bad() async { - print(/*LINT*/await 23); -} -'''; - await findLint(src, LintNames.await_only_futures); - - await applyFix(DartFixKind.REMOVE_AWAIT); - - verifyResult(''' -bad() async { - print(23); -} -'''); - } - - test_removeAwait_StringLiteral() async { - String src = ''' -bad() async { - print(/*LINT*/await 'hola'); -} -'''; - await findLint(src, LintNames.await_only_futures); - - await applyFix(DartFixKind.REMOVE_AWAIT); - - verifyResult(''' -bad() async { - print('hola'); -} -'''); - } - - test_removeEmptyCatch_newLine() async { - String src = ''' -void foo() { - try {} - catch (e) {/*LINT*/} - finally {} -} -'''; - await findLint(src, LintNames.empty_catches); - - await applyFix(DartFixKind.REMOVE_EMPTY_CATCH); - - verifyResult(''' -void foo() { - try {} - finally {} -} -'''); - } - - test_removeEmptyCatch_sameLine() async { - String src = ''' -void foo() { - try {} catch (e) {/*LINT*/} finally {} -} -'''; - await findLint(src, LintNames.empty_catches); - - await applyFix(DartFixKind.REMOVE_EMPTY_CATCH); - - verifyResult(''' -void foo() { - try {} finally {} -} -'''); - } - - test_removeEmptyConstructorBody() async { - String src = ''' -class C { - C() {/*LINT*/} -} -'''; - await findLint(src, LintNames.empty_constructor_bodies); - - await applyFix(DartFixKind.REMOVE_EMPTY_CONSTRUCTOR_BODY); - - verifyResult(''' -class C { - C(); -} -'''); - } - - test_removeEmptyElse_newLine() async { - String src = ''' -void foo(bool cond) { - if (cond) { - // - } - else /*LINT*/; -} -'''; - await findLint(src, LintNames.avoid_empty_else); - - await applyFix(DartFixKind.REMOVE_EMPTY_ELSE); - - verifyResult(''' -void foo(bool cond) { - if (cond) { - // - } -} -'''); - } - - test_removeEmptyElse_sameLine() async { - String src = ''' -void foo(bool cond) { - if (cond) { - // - } else /*LINT*/; -} -'''; - await findLint(src, LintNames.avoid_empty_else); - - await applyFix(DartFixKind.REMOVE_EMPTY_ELSE); - - verifyResult(''' -void foo(bool cond) { - if (cond) { - // - } -} -'''); - } - - test_removeEmptyStatement_insideBlock() async { - String src = ''' -void foo() { - while(true) { - /*LINT*/; - } -} -'''; - await findLint(src, LintNames.empty_statements); - - await applyFix(DartFixKind.REMOVE_EMPTY_STATEMENT); - - verifyResult(''' -void foo() { - while(true) { - } -} -'''); - } - - test_removeEmptyStatement_outOfBlock_otherLine() async { - String src = ''' -void foo() { - while(true) - /*LINT*/; - print('hi'); -} -'''; - await findLint(src, LintNames.empty_statements); - - await applyFix(DartFixKind.REPLACE_WITH_BRACKETS); - - verifyResult(''' -void foo() { - while(true) {} - print('hi'); -} -'''); - } - - test_removeEmptyStatement_outOfBlock_sameLine() async { - String src = ''' -void foo() { - while(true)/*LINT*/; - print('hi'); -} -'''; - await findLint(src, LintNames.empty_statements); - - await applyFix(DartFixKind.REPLACE_WITH_BRACKETS); - - verifyResult(''' -void foo() { - while(true) {} - print('hi'); -} -'''); - } - - test_removeInitializer_field() async { - String src = ''' -class Test { - int /*LINT*/x = null; -} -'''; - await findLint(src, LintNames.avoid_init_to_null); - - await applyFix(DartFixKind.REMOVE_INITIALIZER); - - verifyResult(''' -class Test { - int x; -} -'''); - } - - test_removeInitializer_listOfVariableDeclarations() async { - String src = ''' -String a = 'a', /*LINT*/b = null, c = 'c'; -'''; - await findLint(src, LintNames.avoid_init_to_null); - - await applyFix(DartFixKind.REMOVE_INITIALIZER); - - verifyResult(''' -String a = 'a', b, c = 'c'; -'''); - } - - test_removeInitializer_topLevel() async { - String src = ''' -var /*LINT*/x = null; -'''; - await findLint(src, LintNames.avoid_init_to_null); - - await applyFix(DartFixKind.REMOVE_INITIALIZER); - - verifyResult(''' -var x; -'''); - } - - test_removeMethodDeclaration_getter() async { - String src = ''' -class A { - int x; -} -class B extends A { - @override - int get /*LINT*/x => super.x; -} -'''; - await findLint(src, LintNames.unnecessary_override); - - await applyFix(DartFixKind.REMOVE_METHOD_DECLARATION); - - verifyResult(''' -class A { - int x; -} -class B extends A { -} -'''); - } - - test_removeMethodDeclaration_method() async { - String src = ''' -class A { - @override - String /*LINT*/toString() => super.toString(); -} -'''; - await findLint(src, LintNames.unnecessary_override); - - await applyFix(DartFixKind.REMOVE_METHOD_DECLARATION); - - verifyResult(''' -class A { -} -'''); - } - - test_removeMethodDeclaration_setter() async { - String src = ''' -class A { - int x; -} -class B extends A { - @override - set /*LINT*/x(int other) { - this.x = other; - } -} -'''; - await findLint(src, LintNames.unnecessary_override); - - await applyFix(DartFixKind.REMOVE_METHOD_DECLARATION); - - verifyResult(''' -class A { - int x; -} -class B extends A { -} -'''); - } - - test_removeThisExpression_methodInvocation_oneCharacterOperator() async { - String src = ''' -class A { - void foo() { - /*LINT*/this.foo(); - } -} -'''; - await findLint(src, LintNames.unnecessary_this); - - await applyFix(DartFixKind.REMOVE_THIS_EXPRESSION); - - verifyResult(''' -class A { - void foo() { - foo(); - } -} -'''); - } - - test_removeThisExpression_methodInvocation_twoCharactersOperator() async { - String src = ''' -class A { - void foo() { - /*LINT*/this?.foo(); - } -} -'''; - await findLint(src, LintNames.unnecessary_this); - - await applyFix(DartFixKind.REMOVE_THIS_EXPRESSION); - - verifyResult(''' -class A { - void foo() { - foo(); - } -} -'''); - } - - test_removeThisExpression_notAThisExpression() async { - String src = ''' -void foo() { - final /*LINT*/this.id; -} -'''; - await findLint(src, LintNames.unnecessary_this); - - await assertNoFix(DartFixKind.REMOVE_THIS_EXPRESSION); - } - - test_removeThisExpression_propertyAccess_oneCharacterOperator() async { - String src = ''' -class A { - int x; - void foo() { - /*LINT*/this.x = 2; - } -} -'''; - await findLint(src, LintNames.unnecessary_this); - - await applyFix(DartFixKind.REMOVE_THIS_EXPRESSION); - - verifyResult(''' -class A { - int x; - void foo() { - x = 2; - } -} -'''); - } - - test_removeThisExpression_propertyAccess_twoCharactersOperator() async { - String src = ''' -class A { - int x; - void foo() { - /*LINT*/this?.x = 2; - } -} -'''; - await findLint(src, LintNames.unnecessary_this); - - await applyFix(DartFixKind.REMOVE_THIS_EXPRESSION); - - verifyResult(''' -class A { - int x; - void foo() { - x = 2; - } -} -'''); - } - - test_removeTypeAnnotation_avoidAnnotatingWithDynamic_InsideFunctionTypedFormalParameter() async { - String src = ''' -bad(void foo(/*LINT*/dynamic x)) { - return null; -} -'''; - await findLint(src, LintNames.avoid_annotating_with_dynamic); - - await applyFix(DartFixKind.REMOVE_TYPE_NAME); - - verifyResult(''' -bad(void foo(x)) { - return null; -} -'''); - } - - test_removeTypeAnnotation_avoidAnnotatingWithDynamic_NamedParameter() async { - String src = ''' -bad({/*LINT*/dynamic defaultValue}) { - return null; -} -'''; - await findLint(src, LintNames.avoid_annotating_with_dynamic); - - await applyFix(DartFixKind.REMOVE_TYPE_NAME); - - verifyResult(''' -bad({defaultValue}) { - return null; -} -'''); - } - - test_removeTypeAnnotation_avoidAnnotatingWithDynamic_NormalParameter() async { - String src = ''' -bad(/*LINT*/dynamic defaultValue) { - return null; -} -'''; - await findLint(src, LintNames.avoid_annotating_with_dynamic); - - await applyFix(DartFixKind.REMOVE_TYPE_NAME); - - verifyResult(''' -bad(defaultValue) { - return null; -} -'''); - } - - test_removeTypeAnnotation_avoidAnnotatingWithDynamic_OptionalParameter() async { - String src = ''' -bad([/*LINT*/dynamic defaultValue]) { - return null; -} -'''; - await findLint(src, LintNames.avoid_annotating_with_dynamic); - - await applyFix(DartFixKind.REMOVE_TYPE_NAME); - - verifyResult(''' -bad([defaultValue]) { - return null; -} -'''); - } - - test_removeTypeAnnotation_avoidReturnTypesOnSetters_void() async { - String src = ''' -/*LINT*/void set speed2(int ms) {} -'''; - await findLint(src, LintNames.avoid_return_types_on_setters); - - await applyFix(DartFixKind.REMOVE_TYPE_NAME); - - verifyResult(''' -set speed2(int ms) {} -'''); - } - - test_removeTypeAnnotation_avoidTypesOnClosureParameters_FunctionTypedFormalParameter() async { - String src = ''' -var functionWithFunction = (/*LINT*/int f(int x)) => f(0); -'''; - await findLint(src, LintNames.avoid_types_on_closure_parameters); - - await applyFix(DartFixKind.REPLACE_WITH_IDENTIFIER); - - verifyResult(''' -var functionWithFunction = (f) => f(0); -'''); - } - - test_removeTypeAnnotation_avoidTypesOnClosureParameters_NamedParameter() async { - String src = ''' -var x = ({/*LINT*/Future<int> defaultValue}) { - return null; -}; -'''; - await findLint(src, LintNames.avoid_types_on_closure_parameters); - - await applyFix(DartFixKind.REMOVE_TYPE_NAME); - - verifyResult(''' -var x = ({defaultValue}) { - return null; -}; -'''); - } - - test_removeTypeAnnotation_avoidTypesOnClosureParameters_NormalParameter() async { - String src = ''' -var x = (/*LINT*/Future<int> defaultValue) { - return null; -}; -'''; - await findLint(src, LintNames.avoid_types_on_closure_parameters); - - await applyFix(DartFixKind.REMOVE_TYPE_NAME); - - verifyResult(''' -var x = (defaultValue) { - return null; -}; -'''); - } - - test_removeTypeAnnotation_avoidTypesOnClosureParameters_OptionalParameter() async { - String src = ''' -var x = ([/*LINT*/Future<int> defaultValue]) { - return null; -}; -'''; - await findLint(src, LintNames.avoid_types_on_closure_parameters); - - await applyFix(DartFixKind.REMOVE_TYPE_NAME); - - verifyResult(''' -var x = ([defaultValue]) { - return null; -}; -'''); - } - - test_removeTypeAnnotation_typeInitFormals_void() async { - String src = ''' -class C { - int f; - C(/*LINT*/int this.f); -} -'''; - await findLint(src, LintNames.type_init_formals); - - await applyFix(DartFixKind.REMOVE_TYPE_NAME); - - verifyResult(''' -class C { - int f; - C(this.f); -} -'''); - } - - test_renameToCamelCase_BAD_parameter_optionalNamed() async { - String src = ''' -foo({int /*LINT*/my_integer_variable}) { - print(my_integer_variable); -} -'''; - await findLint(src, LintNames.non_constant_identifier_names); - await assertNoFix(DartFixKind.RENAME_TO_CAMEL_CASE); - } - - test_renameToCamelCase_OK_localVariable() async { - String src = ''' -main() { - int /*LINT*/my_integer_variable = 42; - int foo; - print(my_integer_variable); - print(foo); -} -'''; - await findLint(src, LintNames.non_constant_identifier_names); - - await applyFix(DartFixKind.RENAME_TO_CAMEL_CASE); - - verifyResult(''' -main() { - int myIntegerVariable = 42; - int foo; - print(myIntegerVariable); - print(foo); -} -'''); - } - - test_renameToCamelCase_OK_parameter_closure() async { - String src = ''' -main() { - [0, 1, 2].forEach((/*LINT*/my_integer_variable) { - print(my_integer_variable); - }); -} -'''; - await findLint(src, LintNames.non_constant_identifier_names); - - await applyFix(DartFixKind.RENAME_TO_CAMEL_CASE); - - verifyResult(''' -main() { - [0, 1, 2].forEach((myIntegerVariable) { - print(myIntegerVariable); - }); -} -'''); - } - - test_renameToCamelCase_OK_parameter_function() async { - String src = ''' -main(int /*LINT*/my_integer_variable) { - print(my_integer_variable); -} -'''; - await findLint(src, LintNames.non_constant_identifier_names); - - await applyFix(DartFixKind.RENAME_TO_CAMEL_CASE); - - verifyResult(''' -main(int myIntegerVariable) { - print(myIntegerVariable); -} -'''); - } - - test_renameToCamelCase_OK_parameter_method() async { - String src = ''' -class A { - main(int /*LINT*/my_integer_variable) { - print(my_integer_variable); - } -} -'''; - await findLint(src, LintNames.non_constant_identifier_names); - - await applyFix(DartFixKind.RENAME_TO_CAMEL_CASE); - - verifyResult(''' -class A { - main(int myIntegerVariable) { - print(myIntegerVariable); - } -} -'''); - } - - test_renameToCamelCase_OK_parameter_optionalPositional() async { - String src = ''' -main([int /*LINT*/my_integer_variable]) { - print(my_integer_variable); -} -'''; - await findLint(src, LintNames.non_constant_identifier_names); - - await applyFix(DartFixKind.RENAME_TO_CAMEL_CASE); - - verifyResult(''' -main([int myIntegerVariable]) { - print(myIntegerVariable); -} -'''); - } - - test_replaceFinalWithConst_method() async { - String src = ''' -/*LINT*/final int a = 1; -'''; - await findLint(src, LintNames.prefer_const_declarations); - - await applyFix(DartFixKind.REPLACE_FINAL_WITH_CONST); - - verifyResult(''' -const int a = 1; -'''); - } - - test_replaceWithConditionalAssignment_withCodeBeforeAndAfter() async { - String src = ''' -class Person { - String _fullName; - void foo() { - print('hi'); - /*LINT*/if (_fullName == null) { - _fullName = getFullUserName(this); - } - print('hi'); - } -} -'''; - await findLint(src, LintNames.prefer_conditional_assignment); - - await applyFix(DartFixKind.REPLACE_WITH_CONDITIONAL_ASSIGNMENT); - - verifyResult(''' -class Person { - String _fullName; - void foo() { - print('hi'); - _fullName ??= getFullUserName(this); - print('hi'); - } -} -'''); - } - - test_replaceWithConditionalAssignment_withOneBlock() async { - String src = ''' -class Person { - String _fullName; - void foo() { - /*LINT*/if (_fullName == null) { - _fullName = getFullUserName(this); - } - } -} -'''; - await findLint(src, LintNames.prefer_conditional_assignment); - - await applyFix(DartFixKind.REPLACE_WITH_CONDITIONAL_ASSIGNMENT); - - verifyResult(''' -class Person { - String _fullName; - void foo() { - _fullName ??= getFullUserName(this); - } -} -'''); - } - - test_replaceWithConditionalAssignment_withoutBlock() async { - String src = ''' -class Person { - String _fullName; - void foo() { - /*LINT*/if (_fullName == null) - _fullName = getFullUserName(this); - } -} -'''; - await findLint(src, LintNames.prefer_conditional_assignment); - - await applyFix(DartFixKind.REPLACE_WITH_CONDITIONAL_ASSIGNMENT); - - verifyResult(''' -class Person { - String _fullName; - void foo() { - _fullName ??= getFullUserName(this); - } -} -'''); - } - - test_replaceWithConditionalAssignment_withTwoBlock() async { - String src = ''' -class Person { - String _fullName; - void foo() { - /*LINT*/if (_fullName == null) {{ - _fullName = getFullUserName(this); - }} - } -} -'''; - await findLint(src, LintNames.prefer_conditional_assignment); - - await applyFix(DartFixKind.REPLACE_WITH_CONDITIONAL_ASSIGNMENT); - - verifyResult(''' -class Person { - String _fullName; - void foo() { - _fullName ??= getFullUserName(this); - } -} -'''); - } - - test_replaceWithLiteral_linkedHashMap_withCommentsInGeneric() async { - String src = ''' -import 'dart:collection'; - -final a = /*LINT*/new LinkedHashMap<int,/*comment*/int>(); -'''; - await findLint(src, LintNames.prefer_collection_literals); - - await applyFix(DartFixKind.REPLACE_WITH_LITERAL); - - verifyResult(''' -import 'dart:collection'; - -final a = <int,/*comment*/int>{}; -'''); - } - - test_replaceWithLiteral_linkedHashMap_withDynamicGenerics() async { - String src = ''' -import 'dart:collection'; - -final a = /*LINT*/new LinkedHashMap<dynamic,dynamic>(); -'''; - await findLint(src, LintNames.prefer_collection_literals); - - await applyFix(DartFixKind.REPLACE_WITH_LITERAL); - - verifyResult(''' -import 'dart:collection'; - -final a = <dynamic,dynamic>{}; -'''); - } - - test_replaceWithLiteral_linkedHashMap_withGeneric() async { - String src = ''' -import 'dart:collection'; - -final a = /*LINT*/new LinkedHashMap<int,int>(); -'''; - await findLint(src, LintNames.prefer_collection_literals); - - await applyFix(DartFixKind.REPLACE_WITH_LITERAL); - - verifyResult(''' -import 'dart:collection'; - -final a = <int,int>{}; -'''); - } - - test_replaceWithLiteral_linkedHashMap_withoutGeneric() async { - String src = ''' -import 'dart:collection'; - -final a = /*LINT*/new LinkedHashMap(); -'''; - await findLint(src, LintNames.prefer_collection_literals); - - await applyFix(DartFixKind.REPLACE_WITH_LITERAL); - - verifyResult(''' -import 'dart:collection'; - -final a = {}; -'''); - } - - test_replaceWithLiteral_list_withGeneric() async { - String src = ''' -final a = /*LINT*/new List<int>(); -'''; - await findLint(src, LintNames.prefer_collection_literals); - - await applyFix(DartFixKind.REPLACE_WITH_LITERAL); - - verifyResult(''' -final a = <int>[]; -'''); - } - - test_replaceWithLiteral_list_withoutGeneric() async { - String src = ''' -final a = /*LINT*/new List(); -'''; - await findLint(src, LintNames.prefer_collection_literals); - - await applyFix(DartFixKind.REPLACE_WITH_LITERAL); - - verifyResult(''' -final a = []; -'''); - } - - test_replaceWithLiteral_map_withGeneric() async { - String src = ''' -final a = /*LINT*/new Map<int,int>(); -'''; - await findLint(src, LintNames.prefer_collection_literals); - - await applyFix(DartFixKind.REPLACE_WITH_LITERAL); - - verifyResult(''' -final a = <int,int>{}; -'''); - } - - test_replaceWithLiteral_map_withoutGeneric() async { - String src = ''' -final a = /*LINT*/new Map(); -'''; - await findLint(src, LintNames.prefer_collection_literals); - - await applyFix(DartFixKind.REPLACE_WITH_LITERAL); - - verifyResult(''' -final a = {}; -'''); - } - - test_replaceWithTearOff_function_oneParameter() async { - String src = ''' -final x = /*LINT*/(name) { - print(name); -}; -'''; - await findLint(src, LintNames.unnecessary_lambdas); - - await applyFix(DartFixKind.REPLACE_WITH_TEAR_OFF); - - verifyResult(''' -final x = print; -'''); - } - - test_replaceWithTearOff_function_zeroParameters() async { - String src = ''' -void foo(){} -Function finalVar() { - return /*LINT*/() { - foo(); - }; -} -'''; - await findLint(src, LintNames.unnecessary_lambdas); - - await applyFix(DartFixKind.REPLACE_WITH_TEAR_OFF); - - verifyResult(''' -void foo(){} -Function finalVar() { - return foo; -} -'''); - } - - test_replaceWithTearOff_lambda_asArgument() async { - String src = ''' -void foo() { - bool isPair(int a) => a % 2 == 0; - final finalList = <int>[]; - finalList.where(/*LINT*/(number) => - isPair(number)); -} -'''; - await findLint(src, LintNames.unnecessary_lambdas); - - await applyFix(DartFixKind.REPLACE_WITH_TEAR_OFF); - - verifyResult(''' -void foo() { - bool isPair(int a) => a % 2 == 0; - final finalList = <int>[]; - finalList.where(isPair); -} -'''); - } - - test_replaceWithTearOff_method_oneParameter() async { - String src = ''' -var a = /*LINT*/(x) => finalList.remove(x); -'''; - await findLint(src, LintNames.unnecessary_lambdas); - - await applyFix(DartFixKind.REPLACE_WITH_TEAR_OFF); - - verifyResult(''' -var a = finalList.remove; -'''); - } - - test_replaceWithTearOff_method_zeroParameter() async { - String src = ''' -final Object a; -Function finalVar() { - return /*LINT*/() { - return a.toString(); - }; -} -'''; - await findLint(src, LintNames.unnecessary_lambdas); - - await applyFix(DartFixKind.REPLACE_WITH_TEAR_OFF); - - verifyResult(''' -final Object a; -Function finalVar() { - return a.toString; -} -'''); - } - - void verifyResult(String expectedResult) { - expect(resultCode, expectedResult); - } -} - -class _DartFixContextImpl implements DartFixContext { - @override - final ResourceProvider resourceProvider; - - @override - final AnalysisDriver analysisDriver; - - @override - final AstProvider astProvider; - - @override - final CompilationUnit unit; - - @override - final AnalysisError error; - - @override - final List<AnalysisError> errors; - - _DartFixContextImpl(this.resourceProvider, this.analysisDriver, - this.astProvider, this.unit, this.error, this.errors); - - @override - GetTopLevelDeclarations get getTopLevelDeclarations => - analysisDriver.getTopLevelNameDeclarations; -}
diff --git a/pkg/analysis_server/test/services/correction/organize_directives_test.dart b/pkg/analysis_server/test/services/correction/organize_directives_test.dart index d2b6796..ff56f55 100644 --- a/pkg/analysis_server/test/services/correction/organize_directives_test.dart +++ b/pkg/analysis_server/test/services/correction/organize_directives_test.dart
@@ -5,8 +5,8 @@ import 'dart:async'; import 'package:analysis_server/src/services/correction/organize_directives.dart'; +import 'package:analyzer/dart/analysis/results.dart'; import 'package:analyzer/error/error.dart'; -import 'package:analyzer/src/dart/analysis/driver.dart'; import 'package:analyzer_plugin/protocol/protocol_common.dart' hide AnalysisError; import 'package:test/test.dart'; @@ -96,8 +96,8 @@ } test_remove_unresolvedDirectives() async { - addSource('/project/existing_part1.dart', 'part of lib;'); - addSource('/project/existing_part2.dart', 'part of lib;'); + addSource('/home/test/lib/existing_part1.dart', 'part of lib;'); + addSource('/home/test/lib/existing_part2.dart', 'part of lib;'); await _computeUnitAndErrors(r''' library lib; @@ -335,7 +335,8 @@ Future<void> _computeUnitAndErrors(String code) async { addTestSource(code); - AnalysisResult result = await driver.getResult(testSource.fullName); + ResolvedUnitResult result = + await session.getResolvedUnit(testSource.fullName); testUnit = result.unit; testErrors = result.errors; }
diff --git a/pkg/analysis_server/test/services/correction/sort_members_test.dart b/pkg/analysis_server/test/services/correction/sort_members_test.dart index d89bb36..81001fa 100644 --- a/pkg/analysis_server/test/services/correction/sort_members_test.dart +++ b/pkg/analysis_server/test/services/correction/sort_members_test.dart
@@ -5,7 +5,7 @@ import 'dart:async'; import 'package:analysis_server/src/services/correction/sort_members.dart'; -import 'package:analyzer/src/dart/analysis/driver.dart'; +import 'package:analyzer/dart/analysis/results.dart'; import 'package:analyzer_plugin/protocol/protocol_common.dart'; import 'package:test/test.dart'; import 'package:test_reflective_loader/test_reflective_loader.dart'; @@ -512,6 +512,24 @@ '''); } + test_mixinMembers_method() async { + await _parseTestUnit(r''' +mixin A { + c() {} + a() {} + b() {} +} +'''); + // validate change + _assertSort(r''' +mixin A { + a() {} + b() {} + c() {} +} +'''); + } + test_unitMembers_class() async { await _parseTestUnit(r''' class C {} @@ -664,6 +682,20 @@ '''); } + test_unitMembers_genericTypeAlias() async { + await _parseTestUnit(r''' +typedef FC = void Function(); +typedef FA = void Function(); +typedef FB = void Function(); +'''); + // validate change + _assertSort(r''' +typedef FA = void Function(); +typedef FB = void Function(); +typedef FC = void Function(); +'''); + } + test_unitMembers_importsAndDeclarations() async { await _parseTestUnit(r''' import 'dart:a'; @@ -711,6 +743,8 @@ await _parseTestUnit(r''' _mmm() {} typedef nnn(); +typedef GTAF3 = void Function(); +typedef _GTAF2 = void Function(); _nnn() {} typedef mmm(); typedef _nnn(); @@ -724,6 +758,7 @@ var nnn; var _mmm; var _nnn; +typedef GTAF1 = void Function(); set nnn(x) {} get mmm => null; set mmm(x) {} @@ -752,6 +787,9 @@ nnn() {} _mmm() {} _nnn() {} +typedef GTAF1 = void Function(); +typedef GTAF3 = void Function(); +typedef _GTAF2 = void Function(); typedef mmm(); typedef nnn(); typedef _mmm(); @@ -763,6 +801,19 @@ '''); } + test_unitMembers_mixin() async { + await _parseTestUnit(r''' +mixin C {} +mixin A {} +mixin B {} +'''); + _assertSort(r''' +mixin A {} +mixin B {} +mixin C {} +'''); + } + test_unitMembers_topLevelVariable() async { await _parseTestUnit(r''' int c; @@ -804,7 +855,7 @@ Future<void> _parseTestUnit(String code) async { addTestSource(code); - ParseResult result = await driver.parseFile(testSource.fullName); + ParsedUnitResult result = session.getParsedUnit(testSource.fullName); testUnit = result.unit; } }
diff --git a/pkg/analysis_server/test/services/correction/status_test.dart b/pkg/analysis_server/test/services/correction/status_test.dart index cce27cd..eb27ec2 100644 --- a/pkg/analysis_server/test/services/correction/status_test.dart +++ b/pkg/analysis_server/test/services/correction/status_test.dart
@@ -29,7 +29,7 @@ Element element = findElement('MyClass'); // check Location location = newLocation_fromElement(element); - expect(location.file, convertPath('/project/test.dart')); + expect(location.file, testFile); expect(location.offset, 6); expect(location.length, 7); expect(location.startLine, 1); @@ -52,7 +52,7 @@ sourceRange); // check Location location = newLocation_fromMatch(match); - expect(location.file, convertPath('/project/test.dart')); + expect(location.file, testFile); expect(location.offset, sourceRange.offset); expect(location.length, sourceRange.length); } @@ -65,7 +65,7 @@ AstNode node = findNodeAtString('main'); // check Location location = newLocation_fromNode(node); - expect(location.file, convertPath('/project/test.dart')); + expect(location.file, testFile); expect(location.offset, node.offset); expect(location.length, node.length); } @@ -75,7 +75,7 @@ SourceRange sourceRange = new SourceRange(10, 20); // check Location location = newLocation_fromUnit(testUnit, sourceRange); - expect(location.file, convertPath('/project/test.dart')); + expect(location.file, testFile); expect(location.offset, sourceRange.offset); expect(location.length, sourceRange.length); }
diff --git a/pkg/analysis_server/test/services/correction/strings_test.dart b/pkg/analysis_server/test/services/correction/strings_test.dart index abd4493..a7a68e7 100644 --- a/pkg/analysis_server/test/services/correction/strings_test.dart +++ b/pkg/analysis_server/test/services/correction/strings_test.dart
@@ -133,13 +133,6 @@ expect(isWhitespace('A'.codeUnitAt(0)), isFalse); } - void test_remove() { - expect(remove(null, 'x'), null); - expect(remove('abc', null), 'abc'); - expect(remove('abc abbc abbbc', 'b'), 'ac ac ac'); - expect(remove('abc abbc abbbc', 'bc'), 'a ab abb'); - } - void test_removeEnd() { expect(removeEnd(null, 'x'), null); expect(removeEnd('abc', null), 'abc'); @@ -165,11 +158,4 @@ expect(shorten('0123456789abcdef', 11), '0123...cdef'); expect(shorten('0123456789abcdef', 12), '01234...cdef'); } - - void test_substringAfterLast() { - expect(substringAfterLast('', '/'), ''); - expect(substringAfterLast('abc', ''), ''); - expect(substringAfterLast('abc', 'd'), 'abc'); - expect(substringAfterLast('abcbde', 'b'), 'de'); - } }
diff --git a/pkg/analysis_server/test/services/correction/test_all.dart b/pkg/analysis_server/test/services/correction/test_all.dart index 4183ef1..e098648 100644 --- a/pkg/analysis_server/test/services/correction/test_all.dart +++ b/pkg/analysis_server/test/services/correction/test_all.dart
@@ -1,12 +1,10 @@ -// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file +// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. import 'package:test_reflective_loader/test_reflective_loader.dart'; -import 'assist_test.dart' as assist_test; import 'change_test.dart' as change_test; -import 'fix_test.dart' as fix_test; import 'levenshtein_test.dart' as levenshtein_test; import 'name_suggestion_test.dart' as name_suggestion_test; import 'organize_directives_test.dart' as organize_directives_test; @@ -18,9 +16,7 @@ /// Utility for manually running all tests. main() { defineReflectiveSuite(() { - assist_test.main(); change_test.main(); - fix_test.main(); levenshtein_test.main(); name_suggestion_test.main(); organize_directives_test.main();
diff --git a/pkg/analysis_server/test/services/correction/util_test.dart b/pkg/analysis_server/test/services/correction/util_test.dart index 3e1981c..53eaa7c 100644 --- a/pkg/analysis_server/test/services/correction/util_test.dart +++ b/pkg/analysis_server/test/services/correction/util_test.dart
@@ -35,7 +35,8 @@ '''); IfStatement ifStatement = findNodeAtString('if ('); Expression condition = ifStatement.condition; - String result = new CorrectionUtils(testUnit).invertCondition(condition); + String result = + new CorrectionUtils(testAnalysisResult).invertCondition(condition); expect(result, expected); } @@ -45,7 +46,7 @@ import 'dart:math'; '''); Source newLibrary = _getDartSource('dart:collection'); - _assertAddLibraryImport(<Source>[newLibrary], ''' + await _assertAddLibraryImport(<Source>[newLibrary], ''' import 'dart:async'; import 'dart:collection'; import 'dart:math'; @@ -58,7 +59,7 @@ import 'dart:math'; '''); Source newLibrary = _getDartSource('dart:async'); - _assertAddLibraryImport(<Source>[newLibrary], ''' + await _assertAddLibraryImport(<Source>[newLibrary], ''' import 'dart:async'; import 'dart:collection'; import 'dart:math'; @@ -71,7 +72,7 @@ import 'dart:collection'; '''); Source newLibrary = _getDartSource('dart:math'); - _assertAddLibraryImport(<Source>[newLibrary], ''' + await _assertAddLibraryImport(<Source>[newLibrary], ''' import 'dart:async'; import 'dart:collection'; import 'dart:math'; @@ -85,7 +86,7 @@ '''); Source newLibrary1 = _getDartSource('dart:async'); Source newLibrary2 = _getDartSource('dart:html'); - _assertAddLibraryImport(<Source>[newLibrary1, newLibrary2], ''' + await _assertAddLibraryImport(<Source>[newLibrary1, newLibrary2], ''' import 'dart:async'; import 'dart:collection'; import 'dart:html'; @@ -100,7 +101,7 @@ '''); Source newLibrary1 = _getDartSource('dart:async'); Source newLibrary2 = _getDartSource('dart:collection'); - _assertAddLibraryImport(<Source>[newLibrary1, newLibrary2], ''' + await _assertAddLibraryImport(<Source>[newLibrary1, newLibrary2], ''' import 'dart:async'; import 'dart:collection'; import 'dart:html'; @@ -115,7 +116,7 @@ '''); Source newLibrary1 = _getDartSource('dart:html'); Source newLibrary2 = _getDartSource('dart:math'); - _assertAddLibraryImport(<Source>[newLibrary1, newLibrary2], ''' + await _assertAddLibraryImport(<Source>[newLibrary1, newLibrary2], ''' import 'dart:async'; import 'dart:collection'; import 'dart:html'; @@ -131,7 +132,7 @@ '''); Source newLibrary1 = _getDartSource('dart:math'); Source newLibrary2 = _getDartSource('dart:async'); - _assertAddLibraryImport(<Source>[newLibrary1, newLibrary2], ''' + await _assertAddLibraryImport(<Source>[newLibrary1, newLibrary2], ''' library test; import 'dart:async'; @@ -149,7 +150,7 @@ '''); Source newLibrary1 = _getDartSource('dart:math'); Source newLibrary2 = _getDartSource('dart:async'); - _assertAddLibraryImport(<Source>[newLibrary1, newLibrary2], ''' + await _assertAddLibraryImport(<Source>[newLibrary1, newLibrary2], ''' /// Comment. import 'dart:async'; @@ -167,7 +168,7 @@ '''); Source newLibrary1 = _getDartSource('dart:math'); Source newLibrary2 = _getDartSource('dart:async'); - _assertAddLibraryImport(<Source>[newLibrary1, newLibrary2], ''' + await _assertAddLibraryImport(<Source>[newLibrary1, newLibrary2], ''' #!/bin/dart import 'dart:async'; @@ -183,7 +184,7 @@ '''); Source newLibrary1 = _getDartSource('dart:math'); Source newLibrary2 = _getDartSource('dart:async'); - _assertAddLibraryImport(<Source>[newLibrary1, newLibrary2], ''' + await _assertAddLibraryImport(<Source>[newLibrary1, newLibrary2], ''' import 'dart:async'; import 'dart:math'; @@ -192,14 +193,14 @@ } test_addLibraryImports_package_hasDart_hasPackages_insertAfter() async { - addPackageSource('aaa', 'aaa.dart', ''); + addPackageFile('aaa', 'aaa.dart', ''); await resolveTestUnit(''' import 'dart:async'; import 'package:aaa/aaa.dart'; '''); Source newLibrary = _getSource('/lib/bbb.dart', 'package:bbb/bbb.dart'); - _assertAddLibraryImport(<Source>[newLibrary], ''' + await _assertAddLibraryImport(<Source>[newLibrary], ''' import 'dart:async'; import 'package:aaa/aaa.dart'; @@ -208,14 +209,14 @@ } test_addLibraryImports_package_hasDart_hasPackages_insertBefore() async { - addPackageSource('bbb', 'bbb.dart', ''); + addPackageFile('bbb', 'bbb.dart', ''); await resolveTestUnit(''' import 'dart:async'; import 'package:bbb/bbb.dart'; '''); Source newLibrary = _getSource('/lib/aaa.dart', 'package:aaa/aaa.dart'); - _assertAddLibraryImport(<Source>[newLibrary], ''' + await _assertAddLibraryImport(<Source>[newLibrary], ''' import 'dart:async'; import 'package:aaa/aaa.dart'; @@ -224,15 +225,15 @@ } test_addLibraryImports_package_hasImports_between() async { - addPackageSource('aaa', 'aaa.dart', ''); - addPackageSource('ddd', 'ddd.dart', ''); + addPackageFile('aaa', 'aaa.dart', ''); + addPackageFile('ddd', 'ddd.dart', ''); await resolveTestUnit(''' import 'package:aaa/aaa.dart'; import 'package:ddd/ddd.dart'; '''); Source newLibrary1 = _getSource('/lib/bbb.dart', 'package:bbb/bbb.dart'); Source newLibrary2 = _getSource('/lib/ccc.dart', 'package:ccc/ccc.dart'); - _assertAddLibraryImport(<Source>[newLibrary1, newLibrary2], ''' + await _assertAddLibraryImport(<Source>[newLibrary1, newLibrary2], ''' import 'package:aaa/aaa.dart'; import 'package:bbb/bbb.dart'; import 'package:ccc/ccc.dart'; @@ -285,10 +286,11 @@ await assert_invertCondition('(((b1)))', '!b1'); } - void _assertAddLibraryImport(List<Source> newLibraries, String expectedCode) { + Future<void> _assertAddLibraryImport( + List<Source> newLibraries, String expectedCode) async { SourceChange change = new SourceChange(''); - addLibraryImports(resourceProvider.pathContext, change, testLibraryElement, - newLibraries.toSet()); + await addLibraryImports(testAnalysisResult.session, change, + testLibraryElement, newLibraries.toSet()); SourceFileEdit testEdit = change.getFileEdit(testFile); expect(testEdit, isNotNull); String resultCode = SourceEdit.applySequence(testCode, testEdit.edits);
diff --git a/pkg/analysis_server/test/services/linter/linter_test.dart b/pkg/analysis_server/test/services/linter/linter_test.dart index 19272d8..3965bba 100644 --- a/pkg/analysis_server/test/services/linter/linter_test.dart +++ b/pkg/analysis_server/test/services/linter/linter_test.dart
@@ -1,8 +1,9 @@ -// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file +// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. -import 'package:analyzer/analyzer.dart'; +import 'package:analyzer/error/error.dart'; +import 'package:analyzer/error/listener.dart'; import 'package:analyzer/src/analysis_options/analysis_options_provider.dart'; import 'package:analyzer/src/generated/engine.dart'; import 'package:analyzer/src/generated/source.dart';
diff --git a/pkg/analysis_server/test/services/refactoring/abstract_refactoring.dart b/pkg/analysis_server/test/services/refactoring/abstract_refactoring.dart index 7acb0ce..213972f 100644 --- a/pkg/analysis_server/test/services/refactoring/abstract_refactoring.dart +++ b/pkg/analysis_server/test/services/refactoring/abstract_refactoring.dart
@@ -8,11 +8,7 @@ import 'package:analysis_server/src/services/refactoring/refactoring.dart'; import 'package:analysis_server/src/services/search/search_engine.dart'; import 'package:analysis_server/src/services/search/search_engine_internal.dart'; -import 'package:analyzer/dart/ast/ast.dart'; -import 'package:analyzer/dart/element/element.dart' show Element; import 'package:analyzer/file_system/file_system.dart'; -import 'package:analyzer/src/dart/analysis/ast_provider_driver.dart'; -import 'package:analyzer/src/dart/element/ast_provider.dart'; import 'package:analyzer/src/generated/source.dart'; import 'package:analyzer_plugin/protocol/protocol_common.dart' show @@ -44,7 +40,6 @@ */ abstract class RefactoringTest extends AbstractSingleUnitTest { SearchEngine searchEngine; - AstProvider astProvider; SourceChange refactoringChange; @@ -151,14 +146,6 @@ expect(actualCode, expectedCode); } - /** - * Completes with a fully resolved unit that contains the [element]. - */ - Future<CompilationUnit> getResolvedUnitWithElement(Element element) async { - return element.context - .resolveCompilationUnit(element.source, element.library); - } - Future<void> indexTestUnit(String code) async { await resolveTestUnit(code); } @@ -170,6 +157,5 @@ void setUp() { super.setUp(); searchEngine = new SearchEngineImpl([driver]); - astProvider = new AstProviderForDriver(driver); } }
diff --git a/pkg/analysis_server/test/services/refactoring/abstract_rename.dart b/pkg/analysis_server/test/services/refactoring/abstract_rename.dart index 400bb3d..fec6d34 100644 --- a/pkg/analysis_server/test/services/refactoring/abstract_rename.dart +++ b/pkg/analysis_server/test/services/refactoring/abstract_rename.dart
@@ -56,7 +56,8 @@ */ void createRenameRefactoringForElement(Element element) { var workspace = new RefactoringWorkspace([driver], searchEngine); - refactoring = new RenameRefactoring(workspace, astProvider, element); + var session = testAnalysisResult.session; + refactoring = new RenameRefactoring(workspace, session, element); expect(refactoring, isNotNull, reason: "No refactoring for '$element'."); }
diff --git a/pkg/analysis_server/test/services/refactoring/convert_getter_to_method_test.dart b/pkg/analysis_server/test/services/refactoring/convert_getter_to_method_test.dart index 6702055..abac0c8 100644 --- a/pkg/analysis_server/test/services/refactoring/convert_getter_to_method_test.dart +++ b/pkg/analysis_server/test/services/refactoring/convert_getter_to_method_test.dart
@@ -87,7 +87,7 @@ } test_change_multipleFiles() async { - await indexUnit('/project/other.dart', r''' + await indexUnit('/home/test/lib/other.dart', r''' class A { int get test => 1; } @@ -153,7 +153,7 @@ void _createRefactoringForElement(ExecutableElement element) { refactoring = new ConvertGetterToMethodRefactoring( - searchEngine, astProvider, element); + searchEngine, testAnalysisResult.session, element); } void _createRefactoringForString(String search) {
diff --git a/pkg/analysis_server/test/services/refactoring/convert_method_to_getter_test.dart b/pkg/analysis_server/test/services/refactoring/convert_method_to_getter_test.dart index 60f38f8..129cf15 100644 --- a/pkg/analysis_server/test/services/refactoring/convert_method_to_getter_test.dart +++ b/pkg/analysis_server/test/services/refactoring/convert_method_to_getter_test.dart
@@ -89,7 +89,7 @@ } test_change_multipleFiles() async { - await indexUnit('/project/other.dart', r''' + await indexUnit('/home/test/lib/other.dart', r''' class A { int test() => 1; } @@ -205,7 +205,7 @@ void _createRefactoringForElement(ExecutableElement element) { refactoring = new ConvertMethodToGetterRefactoring( - searchEngine, astProvider, element); + searchEngine, testAnalysisResult.session, element); } void _createRefactoringForString(String search) {
diff --git a/pkg/analysis_server/test/services/refactoring/extract_method_test.dart b/pkg/analysis_server/test/services/refactoring/extract_method_test.dart index 35a31ee..420f69a 100644 --- a/pkg/analysis_server/test/services/refactoring/extract_method_test.dart +++ b/pkg/analysis_server/test/services/refactoring/extract_method_test.dart
@@ -1,4 +1,4 @@ -// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file +// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. @@ -1516,10 +1516,10 @@ await indexTestUnit(''' import 'asyncLib.dart'; main() { - var a = newFuture(); + var a = newCompleter(); } '''); - _createRefactoringForString('newFuture()'); + _createRefactoringForString('newCompleter()'); // apply refactoring return _assertSuccessfulRefactoring(''' import 'asyncLib.dart'; @@ -1528,7 +1528,7 @@ var a = res(); } -Future<int> res() => newFuture(); +Completer<int> res() => newCompleter(); '''); } @@ -2527,7 +2527,7 @@ await indexTestUnit(''' import 'asyncLib.dart'; main() { - var v = newFuture(); + var v = newCompleter(); // start print(v); // end @@ -2539,20 +2539,19 @@ import 'asyncLib.dart'; import 'dart:async'; main() { - var v = newFuture(); + var v = newCompleter(); // start res(v); // end } -void res(Future<int> v) { +void res(Completer<int> v) { print(v); } '''); } test_statements_parameters_localFunction() async { - _addLibraryReturningAsync(); await indexTestUnit(''' class C { int f(int a) { @@ -2837,10 +2836,10 @@ } void _addLibraryReturningAsync() { - addSource('/project/asyncLib.dart', r''' -library asyncLib; + addSource('/home/test/lib/asyncLib.dart', r''' import 'dart:async'; -Future<int> newFuture() => null; + +Completer<int> newCompleter() => null; '''); } @@ -2880,7 +2879,7 @@ void _createRefactoring(int offset, int length) { refactoring = new ExtractMethodRefactoring( - searchEngine, astProvider, testAnalysisResult, offset, length); + searchEngine, testAnalysisResult, offset, length); refactoring.name = 'res'; }
diff --git a/pkg/analysis_server/test/services/refactoring/inline_local_test.dart b/pkg/analysis_server/test/services/refactoring/inline_local_test.dart index 0c4ac76..41e32b8 100644 --- a/pkg/analysis_server/test/services/refactoring/inline_local_test.dart +++ b/pkg/analysis_server/test/services/refactoring/inline_local_test.dart
@@ -634,6 +634,9 @@ void _createRefactoring(String search) { int offset = findOffset(search); refactoring = new InlineLocalRefactoring( - searchEngine, astProvider, testAnalysisResult, offset); + searchEngine, + testAnalysisResult, + offset, + ); } }
diff --git a/pkg/analysis_server/test/services/refactoring/inline_method_test.dart b/pkg/analysis_server/test/services/refactoring/inline_method_test.dart index a508984..077035c 100644 --- a/pkg/analysis_server/test/services/refactoring/inline_method_test.dart +++ b/pkg/analysis_server/test/services/refactoring/inline_method_test.dart
@@ -1756,6 +1756,9 @@ void _createRefactoring(String search) { int offset = findOffset(search); refactoring = new InlineMethodRefactoring( - searchEngine, astProvider, testAnalysisResult, offset); + searchEngine, + testAnalysisResult, + offset, + ); } }
diff --git a/pkg/analysis_server/test/services/refactoring/move_file_test.dart b/pkg/analysis_server/test/services/refactoring/move_file_test.dart index 2616261..dd52924 100644 --- a/pkg/analysis_server/test/services/refactoring/move_file_test.dart +++ b/pkg/analysis_server/test/services/refactoring/move_file_test.dart
@@ -23,10 +23,10 @@ MoveFileRefactoring refactoring; test_file_containing_imports_exports_parts() async { - String pathA = '/project/000/1111/a.dart'; - String pathB = '/project/000/1111/b.dart'; - String pathC = '/project/000/1111/22/c.dart'; - testFile = '/project/000/1111/test.dart'; + String pathA = '/home/test/000/1111/a.dart'; + String pathB = '/home/test/000/1111/b.dart'; + String pathC = '/home/test/000/1111/22/c.dart'; + testFile = '/home/test/000/1111/test.dart'; addSource('/absolute/uri.dart', ''); addSource(pathA, 'part of lib;'); addSource(pathB, "import 'test.dart';"); @@ -40,7 +40,7 @@ part '${convertAbsolutePathToUri('/absolute/uri.dart')}'; '''); // perform refactoring - _createRefactoring('/project/000/1111/22/new_name.dart'); + _createRefactoring('/home/test/000/1111/22/new_name.dart'); await _assertSuccessfulRefactoring(); assertNoFileChange(pathA); assertFileChangeResult(pathB, "import '22/new_name.dart';"); @@ -55,15 +55,30 @@ '''); } + test_file_imported_with_package_uri() async { + newFile('/home/test/lib/old_name.dart', content: ''); + addTestSource(r''' +import 'package:test/old_name.dart'; +'''); + + _createRefactoring('/home/test/lib/222/new_name.dart', + oldName: '/home/test/lib/old_name.dart'); + await _assertSuccessfulRefactoring(); + + assertFileChangeResult(testFile, ''' +import 'package:test/222/new_name.dart'; +'''); + } + test_file_importedLibrary_down() async { - String pathA = '/project/000/1111/a.dart'; - testFile = '/project/000/1111/test.dart'; + String pathA = '/home/test/000/1111/a.dart'; + testFile = '/home/test/000/1111/test.dart'; addSource(pathA, ''' import 'test.dart'; '''); addTestSource(''); // perform refactoring - _createRefactoring('/project/000/1111/22/new_name.dart'); + _createRefactoring('/home/test/000/1111/22/new_name.dart'); await _assertSuccessfulRefactoring(); assertFileChangeResult(pathA, ''' import '22/new_name.dart'; @@ -72,14 +87,14 @@ } test_file_importedLibrary_sideways() async { - String pathA = '/project/000/1111/a.dart'; - testFile = '/project/000/1111/sub/folder/test.dart'; + String pathA = '/home/test/000/1111/a.dart'; + testFile = '/home/test/000/1111/sub/folder/test.dart'; addSource(pathA, ''' import 'sub/folder/test.dart'; '''); addTestSource(''); // perform refactoring - _createRefactoring('/project/000/new/folder/name/new_name.dart'); + _createRefactoring('/home/test/000/new/folder/name/new_name.dart'); await _assertSuccessfulRefactoring(); assertFileChangeResult(pathA, ''' import '../new/folder/name/new_name.dart'; @@ -88,14 +103,14 @@ } test_file_importedLibrary_up() async { - String pathA = '/project/000/1111/a.dart'; - testFile = '/project/000/1111/22/test.dart'; + String pathA = '/home/test/000/1111/a.dart'; + testFile = '/home/test/000/1111/22/test.dart'; addSource(pathA, ''' import '22/test.dart'; '''); addTestSource(''); // perform refactoring - _createRefactoring('/project/000/1111/new_name.dart'); + _createRefactoring('/home/test/000/1111/new_name.dart'); await _assertSuccessfulRefactoring(); assertFileChangeResult(pathA, ''' import 'new_name.dart'; @@ -103,33 +118,13 @@ assertNoFileChange(testFile); } - test_file_imported_with_package_uri() async { - // Set up package uri resolution for local package. - packageMap['my_package'] = [getFolder('/project/lib')]; - configureDriver(); - - String pathA = '/project/000/1111/a.dart'; - testFile = '/project/lib/test.dart'; - addSource(pathA, ''' - import 'package:my_package/test.dart'; - '''); - addTestSource(''); - // perform refactoring - _createRefactoring('/project/lib/222/new_name.dart'); - await _assertSuccessfulRefactoring(); - assertFileChangeResult(pathA, ''' - import 'package:my_package/222/new_name.dart'; - '''); - assertNoFileChange(testFile); - } - @failingTest test_file_referenced_by_multiple_libraries() async { // This test fails because the search index doesn't support multiple uris for // a library, so only one of them is updated. - String pathA = '/project/000/1111/a.dart'; - String pathB = '/project/000/b.dart'; - testFile = '/project/000/1111/22/test.dart'; + String pathA = '/home/test/000/1111/a.dart'; + String pathB = '/home/test/000/b.dart'; + testFile = '/home/test/000/1111/22/test.dart'; addSource(pathA, ''' library lib; part '22/test.dart'; @@ -142,7 +137,7 @@ part of lib; '''); // perform refactoring - _createRefactoring('/project/000/1111/22/new_name.dart'); + _createRefactoring('/home/test/000/1111/22/new_name.dart'); await _assertSuccessfulRefactoring(); assertFileChangeResult(pathA, ''' library lib; @@ -156,8 +151,8 @@ } test_file_referenced_by_part() async { - String pathA = '/project/000/1111/a.dart'; - testFile = '/project/000/1111/22/test.dart'; + String pathA = '/home/test/000/1111/a.dart'; + testFile = '/home/test/000/1111/22/test.dart'; addSource(pathA, ''' library lib; part '22/test.dart'; @@ -166,7 +161,7 @@ part of lib; '''); // perform refactoring - _createRefactoring('/project/000/1111/22/new_name.dart'); + _createRefactoring('/home/test/000/1111/22/new_name.dart'); await _assertSuccessfulRefactoring(); assertFileChangeResult(pathA, ''' library lib; @@ -190,11 +185,11 @@ } test_nonexistent_file_returns_failure() async { - _createRefactoring(convertPath('/project/test_missing_new.dart'), - oldName: convertPath('/project/test_missing.dart')); + _createRefactoring(convertPath('/home/test/test_missing_new.dart'), + oldName: convertPath('/home/test/test_missing.dart')); await _assertFailedRefactoring(RefactoringProblemSeverity.FATAL, expectedMessage: - '${convertPath('/project/test_missing.dart')} does not exist.'); + '${convertPath('/home/test/test_missing.dart')} does not exist.'); } @failingTest @@ -205,18 +200,18 @@ } test_projectFolder() async { - _createRefactoring('/project2', oldName: '/project'); + _createRefactoring('/home/test2', oldName: '/home/test'); await _assertFailedRefactoring(RefactoringProblemSeverity.FATAL, - expectedMessage: - 'Renaming an analysis root is not supported (${convertPath('/project')})'); + expectedMessage: 'Renaming an analysis root is not supported ' + '(${convertPath('/home/test')})'); } test_renaming_part_that_uses_uri_in_part_of() async { // If the file is a part in a library, and the part-of directive uses a URI // rather than a library name, that will need updating too (if the relative // path to the parent changes). - String pathA = '/project/000/1111/a.dart'; - testFile = '/project/000/1111/22/test.dart'; + String pathA = '/home/test/000/1111/a.dart'; + testFile = '/home/test/000/1111/22/test.dart'; addSource(pathA, ''' library lib; part '22/test.dart'; @@ -225,7 +220,7 @@ part of '../a.dart'; '''); // perform refactoring - _createRefactoring('/project/000/1111/22/33/test.dart'); + _createRefactoring('/home/test/000/1111/22/33/test.dart'); await _assertSuccessfulRefactoring(); assertFileChangeResult(pathA, ''' library lib; @@ -236,6 +231,13 @@ '''); } + Future _assertFailedRefactoring(RefactoringProblemSeverity expectedSeverity, + {String expectedMessage}) async { + RefactoringStatus status = await refactoring.checkAllConditions(); + assertRefactoringStatus(status, expectedSeverity, + expectedMessage: expectedMessage); + } + /** * Checks that all conditions are OK. */ @@ -257,11 +259,4 @@ } refactoring.newFile = convertPath(newName); } - - Future _assertFailedRefactoring(RefactoringProblemSeverity expectedSeverity, - {String expectedMessage}) async { - RefactoringStatus status = await refactoring.checkAllConditions(); - assertRefactoringStatus(status, expectedSeverity, - expectedMessage: expectedMessage); - } }
diff --git a/pkg/analysis_server/test/services/refactoring/rename_class_member_test.dart b/pkg/analysis_server/test/services/refactoring/rename_class_member_test.dart index a7e9148..90957df 100644 --- a/pkg/analysis_server/test/services/refactoring/rename_class_member_test.dart +++ b/pkg/analysis_server/test/services/refactoring/rename_class_member_test.dart
@@ -157,7 +157,7 @@ test() {} } '''); - await indexUnit('/project/lib.dart', ''' + await indexUnit('/home/test/lib/lib.dart', ''' library my.lib; import 'test.dart'; @@ -356,7 +356,7 @@ newName() {} // marker } '''; - await indexUnit('/project/lib.dart', libCode); + await indexUnit('/home/test/lib/lib.dart', libCode); await indexTestUnit(''' import 'lib.dart'; class B extends A { @@ -715,17 +715,18 @@ } test_createChange_MethodElement_potential_inPubCache() async { - String pkgLib = '/.pub-cache/lib.dart'; - await indexUnit(pkgLib, r''' + var externalPath = addPackageFile('aaa', 'lib.dart', r''' processObj(p) { p.test(); } -'''); +''').path; await indexTestUnit(''' -import '${convertAbsolutePathToUri(pkgLib)}'; +import 'package:aaa/lib.dart'; + class A { test() {} } + main(var a) { a.test(); } @@ -737,15 +738,17 @@ refactoring.newName = 'newName'; // validate change await assertSuccessfulRefactoring(''' -import '${convertAbsolutePathToUri('/.pub-cache/lib.dart')}'; +import 'package:aaa/lib.dart'; + class A { newName() {} } + main(var a) { a.newName(); } '''); - SourceFileEdit fileEdit = refactoringChange.getFileEdit(pkgLib); + SourceFileEdit fileEdit = refactoringChange.getFileEdit(externalPath); expect(fileEdit, isNull); } @@ -783,6 +786,94 @@ assertNoFileChange('/lib.dart'); } + test_createChange_outsideOfProject_declarationInPackage() async { + addPackageFile('aaa', 'aaa.dart', r''' +class A { + void test() {} +} + +void foo(A a) { + a.test(); +} +'''); + await indexTestUnit(''' +import 'package:aaa/aaa.dart'; + +class B extends A { + void test() {} +} + +main(A a, B b) { + a.test(); + b.test(); +} +'''); + createRenameRefactoringAtString('test() {}'); + refactoring.newName = 'newName'; + + await assertSuccessfulRefactoring(''' +import 'package:aaa/aaa.dart'; + +class B extends A { + void newName() {} +} + +main(A a, B b) { + a.newName(); + b.newName(); +} +'''); + + expect(refactoringChange.edits, hasLength(1)); + expect(refactoringChange.edits[0].file, testFile); + } + + test_createChange_outsideOfProject_referenceInPart() async { + newFile('/home/part.dart', content: r''' +part of test; + +void foo(A a) { + a.test(); +} +'''); + + // To use file:// URI. + testFile = convertPath('/home/test/bin/test.dart'); + + await indexTestUnit(''' +library test; + +part '../../part.dart'; + +class A { + void test() {} +} + +main(A a) { + a.test(); +} +'''); + createRenameRefactoringAtString('test() {}'); + refactoring.newName = 'newName'; + + await assertSuccessfulRefactoring(''' +library test; + +part '../../part.dart'; + +class A { + void newName() {} +} + +main(A a) { + a.newName(); +} +'''); + + expect(refactoringChange.edits, hasLength(1)); + expect(refactoringChange.edits[0].file, testFile); + } + test_createChange_PropertyAccessorElement_getter() async { await indexTestUnit(''' class A {
diff --git a/pkg/analysis_server/test/services/refactoring/rename_library_test.dart b/pkg/analysis_server/test/services/refactoring/rename_library_test.dart index 19d2a4d..dc1df38 100644 --- a/pkg/analysis_server/test/services/refactoring/rename_library_test.dart +++ b/pkg/analysis_server/test/services/refactoring/rename_library_test.dart
@@ -40,7 +40,7 @@ } test_createChange() async { - addSource('/project/part.dart', ''' + addSource('/home/test/lib/part.dart', ''' part of my.app; '''); await indexTestUnit(''' @@ -57,13 +57,13 @@ library the.new.name; part 'part.dart'; '''); - assertFileChangeResult('/project/part.dart', ''' + assertFileChangeResult('/home/test/lib/part.dart', ''' part of the.new.name; '''); } test_createChange_hasWhitespaces() async { - addSource('/project/part.dart', ''' + addSource('/home/test/lib/part.dart', ''' part of my . app; '''); await indexTestUnit(''' @@ -80,7 +80,7 @@ library the.new.name; part 'part.dart'; '''); - assertFileChangeResult('/project/part.dart', ''' + assertFileChangeResult('/home/test/lib/part.dart', ''' part of the.new.name; '''); }
diff --git a/pkg/analysis_server/test/services/refactoring/rename_local_test.dart b/pkg/analysis_server/test/services/refactoring/rename_local_test.dart index 6b8c273..25359cd 100644 --- a/pkg/analysis_server/test/services/refactoring/rename_local_test.dart +++ b/pkg/analysis_server/test/services/refactoring/rename_local_test.dart
@@ -442,29 +442,42 @@ } test_createChange_parameter_named_inOtherFile() async { - await indexTestUnit(''' + var a = convertPath('/home/test/lib/a.dart'); + var b = convertPath('/home/test/lib/b.dart'); + + newFile(a, content: r''' class A { A({test}); } '''); - await indexUnit('/project/test2.dart', ''' -import 'test.dart'; + newFile(b, content: r''' +import 'a.dart'; + main() { new A(test: 2); } '''); - // configure refactoring + driver.addFile(a); + driver.addFile(b); + + var session = driver.currentSession; + testAnalysisResult = await session.getResolvedUnit(a); + testFile = testAnalysisResult.path; + testCode = testAnalysisResult.content; + testUnit = testAnalysisResult.unit; + createRenameRefactoringAtString('test});'); expect(refactoring.refactoringName, 'Rename Parameter'); refactoring.newName = 'newName'; - // validate change + await assertSuccessfulRefactoring(''' class A { A({newName}); } '''); - assertFileChangeResult('/project/test2.dart', ''' -import 'test.dart'; + assertFileChangeResult(b, ''' +import 'a.dart'; + main() { new A(newName: 2); } @@ -472,7 +485,7 @@ } test_createChange_parameter_named_updateHierarchy() async { - await indexUnit('/project/test2.dart', ''' + await indexUnit('/home/test/lib/test2.dart', ''' library test2; class A { void foo({int test: 1}) { @@ -516,7 +529,7 @@ } } '''); - assertFileChangeResult('/project/test2.dart', ''' + assertFileChangeResult('/home/test/lib/test2.dart', ''' library test2; class A { void foo({int newName: 1}) {
diff --git a/pkg/analysis_server/test/services/refactoring/rename_unit_member_test.dart b/pkg/analysis_server/test/services/refactoring/rename_unit_member_test.dart index 7ace7de..1f23392 100644 --- a/pkg/analysis_server/test/services/refactoring/rename_unit_member_test.dart +++ b/pkg/analysis_server/test/services/refactoring/rename_unit_member_test.dart
@@ -69,7 +69,7 @@ await indexTestUnit(''' class Test {} '''); - await indexUnit(convertPath('/project/lib.dart'), ''' + await indexUnit('/home/test/lib/lib.dart', ''' library my.lib; import 'test.dart'; @@ -109,7 +109,7 @@ await indexTestUnit(''' class Test {} '''); - await indexUnit(convertPath('/project/lib.dart'), ''' + await indexUnit('/home/test/lib/lib.dart', ''' library my.lib; import 'test.dart'; class A { @@ -230,11 +230,11 @@ } test_checkInitialConditions_outsideOfProject() async { - addSource('/other/lib.dart', r''' + addPackageFile('aaa', 'lib.dart', r''' class A {} '''); await indexTestUnit(''' -import "${convertAbsolutePathToUri('/other/lib.dart')}"; +import "package:aaa/lib.dart"; main() { A a; } @@ -587,7 +587,7 @@ } test_createChange_FunctionElement_imported() async { - await indexUnit('/project/foo.dart', r''' + await indexUnit('/home/test/lib/foo.dart', r''' test() {} foo() {} '''); @@ -614,7 +614,7 @@ foo(); } '''); - assertFileChangeResult('/project/foo.dart', ''' + assertFileChangeResult('/home/test/lib/foo.dart', ''' newName() {} foo() {} '''); @@ -644,6 +644,42 @@ '''); } + test_createChange_outsideOfProject_referenceInPart() async { + newFile('/home/part.dart', content: r''' +part of test; + +Test test2; +'''); + + // To use file:// URI. + testFile = convertPath('/home/test/bin/test.dart'); + + await indexTestUnit(''' +library test; + +part '../../part.dart'; + +class Test {} + +Test test; +'''); + createRenameRefactoringAtString('Test {}'); + refactoring.newName = 'NewName'; + + await assertSuccessfulRefactoring(''' +library test; + +part '../../part.dart'; + +class NewName {} + +NewName test; +'''); + + expect(refactoringChange.edits, hasLength(1)); + expect(refactoringChange.edits[0].file, testFile); + } + test_createChange_PropertyAccessorElement_getter_declaration() async { await _test_createChange_PropertyAccessorElement("test {}"); }
diff --git a/pkg/analysis_server/test/services/search/search_engine_test.dart b/pkg/analysis_server/test/services/search/search_engine_test.dart index 009e5fc..16488d7 100644 --- a/pkg/analysis_server/test/services/search/search_engine_test.dart +++ b/pkg/analysis_server/test/services/search/search_engine_test.dart
@@ -1,4 +1,4 @@ -// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file +// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. @@ -7,21 +7,20 @@ import 'package:analysis_server/src/services/search/search_engine.dart'; import 'package:analysis_server/src/services/search/search_engine_internal.dart'; import 'package:analyzer/dart/element/element.dart'; +import 'package:analyzer/src/dart/analysis/byte_store.dart'; import 'package:analyzer/src/dart/analysis/driver.dart'; import 'package:analyzer/src/dart/analysis/file_state.dart'; +import 'package:analyzer/src/dart/analysis/performance_logger.dart'; import 'package:analyzer/src/file_system/file_system.dart'; import 'package:analyzer/src/generated/engine.dart'; import 'package:analyzer/src/generated/sdk.dart'; import 'package:analyzer/src/generated/source.dart'; import 'package:analyzer/src/source/package_map_resolver.dart'; +import 'package:analyzer/src/test_utilities/mock_sdk.dart'; import 'package:analyzer/src/test_utilities/resource_provider_mixin.dart'; -import 'package:analyzer/src/dart/analysis/byte_store.dart'; -import 'package:analyzer/src/dart/analysis/performance_logger.dart'; import 'package:test/test.dart'; import 'package:test_reflective_loader/test_reflective_loader.dart'; -import '../../mock_sdk.dart'; - main() { defineReflectiveSuite(() { defineReflectiveTests(SearchEngineImplTest); @@ -29,7 +28,7 @@ } @reflectiveTest -class SearchEngineImplTest extends Object with ResourceProviderMixin { +class SearchEngineImplTest with ResourceProviderMixin { DartSdk sdk; final ByteStore byteStore = new MemoryByteStore(); final FileContentOverlay contentOverlay = new FileContentOverlay(); @@ -496,7 +495,8 @@ contentOverlay, null, new SourceFactory(resolvers, null, resourceProvider), - new AnalysisOptionsImpl()); + new AnalysisOptionsImpl(), + enableIndex: true); } static void _assertContainsClass(Set<ClassElement> subtypes, String name) {
diff --git a/pkg/analysis_server/test/src/computer/closingLabels_computer_test.dart b/pkg/analysis_server/test/src/computer/closingLabels_computer_test.dart index 1c5ec8d..f748909 100644 --- a/pkg/analysis_server/test/src/computer/closingLabels_computer_test.dart +++ b/pkg/analysis_server/test/src/computer/closingLabels_computer_test.dart
@@ -24,7 +24,7 @@ setUp() { super.setUp(); - sourcePath = resourceProvider.convertPath('/p/lib/source.dart'); + sourcePath = convertPath('/home/test/lib/test.dart'); } test_adjacentLinesExcluded() async { @@ -400,7 +400,7 @@ Future<List<ClosingLabel>> _computeElements(String sourceContent) async { newFile(sourcePath, content: sourceContent); - ResolveResult result = await driver.getResult(sourcePath); + ResolvedUnitResult result = await session.getResolvedUnit(sourcePath); DartUnitClosingLabelsComputer computer = new DartUnitClosingLabelsComputer(result.lineInfo, result.unit); return computer.compute();
diff --git a/pkg/analysis_server/test/src/computer/folding_computer_test.dart b/pkg/analysis_server/test/src/computer/folding_computer_test.dart index dee139a..8fcde2d 100644 --- a/pkg/analysis_server/test/src/computer/folding_computer_test.dart +++ b/pkg/analysis_server/test/src/computer/folding_computer_test.dart
@@ -24,7 +24,7 @@ setUp() { super.setUp(); - sourcePath = resourceProvider.convertPath('/p/lib/source.dart'); + sourcePath = convertPath('/home/test/lib/test.dart'); } test_annotations() async { @@ -449,7 +449,7 @@ Future<List<FoldingRegion>> _computeRegions(String sourceContent) async { newFile(sourcePath, content: sourceContent); - ResolveResult result = await driver.getResult(sourcePath); + ResolvedUnitResult result = await session.getResolvedUnit(sourcePath); DartUnitFoldingComputer computer = new DartUnitFoldingComputer(result.lineInfo, result.unit); return computer.compute();
diff --git a/pkg/analysis_server/test/src/computer/import_elements_computer_test.dart b/pkg/analysis_server/test/src/computer/import_elements_computer_test.dart index 3d5f23b..731ca5f 100644 --- a/pkg/analysis_server/test/src/computer/import_elements_computer_test.dart +++ b/pkg/analysis_server/test/src/computer/import_elements_computer_test.dart
@@ -6,9 +6,8 @@ import 'package:analysis_server/protocol/protocol_generated.dart'; import 'package:analysis_server/src/computer/import_elements_computer.dart'; -import 'package:analyzer/src/dart/analysis/driver.dart'; +import 'package:analyzer/dart/analysis/results.dart'; import 'package:analyzer_plugin/protocol/protocol_common.dart'; -import 'package:analyzer/src/generated/source.dart'; import 'package:test/test.dart'; import 'package:test_reflective_loader/test_reflective_loader.dart'; @@ -52,13 +51,13 @@ Future<void> createBuilder(String content) async { originalContent = content; newFile(path, content: content); - AnalysisResult result = await driver.getResult(path); + ResolvedUnitResult result = await session.getResolvedUnit(path); computer = new ImportElementsComputer(resourceProvider, result); } void setUp() { super.setUp(); - path = resourceProvider.convertPath('/test.dart'); + path = convertPath('/home/test/lib/test.dart'); } test_createEdits_addImport_noDirectives() async { @@ -69,7 +68,7 @@ '''); await computeChanges(<ImportedElements>[ new ImportedElements( - convertPath('/lib/math/math.dart'), '', <String>['Random']) + convertPath('/sdk/lib/math/math.dart'), '', <String>['Random']) ]); assertChanges(''' import 'dart:math'; @@ -81,12 +80,12 @@ } test_createEdits_addImport_noPrefix() async { - Source fooSource = addPackageSource('pkg', 'foo.dart', ''); + var fooFile = addPackageFile('pkg', 'foo.dart', ''); await createBuilder(''' import 'package:pkg/foo.dart' as foo; '''); await computeChanges(<ImportedElements>[ - new ImportedElements(fooSource.fullName, '', <String>['A']) + new ImportedElements(fooFile.path, '', <String>['A']) ]); assertChanges(''' import 'package:pkg/foo.dart' as foo; @@ -95,12 +94,12 @@ } test_createEdits_addImport_prefix() async { - Source fooSource = addPackageSource('pkg', 'foo.dart', ''); + var fooFile = addPackageFile('pkg', 'foo.dart', ''); await createBuilder(''' import 'package:pkg/foo.dart'; '''); await computeChanges(<ImportedElements>[ - new ImportedElements(fooSource.fullName, 'foo', <String>['A']) + new ImportedElements(fooFile.path, 'foo', <String>['A']) ]); assertChanges(''' import 'package:pkg/foo.dart'; @@ -109,13 +108,13 @@ } test_createEdits_addShow_multipleNames() async { - Source fooSource = addPackageSource('pkg', 'foo.dart', ''); + var fooFile = addPackageFile('pkg', 'foo.dart', ''); await createBuilder(''' import 'package:pkg/foo.dart' show B; import 'package:pkg/foo.dart' as foo; '''); await computeChanges(<ImportedElements>[ - new ImportedElements(fooSource.fullName, '', <String>['A', 'C']) + new ImportedElements(fooFile.path, '', <String>['A', 'C']) ]); assertChanges(''' import 'package:pkg/foo.dart' show B, A, C; @@ -124,12 +123,12 @@ } test_createEdits_addShow_removeHide() async { - Source fooSource = addPackageSource('pkg', 'foo.dart', ''); + var fooFile = addPackageFile('pkg', 'foo.dart', ''); await createBuilder(''' import 'package:pkg/foo.dart' show A, B hide C, D; '''); await computeChanges(<ImportedElements>[ - new ImportedElements(fooSource.fullName, '', <String>['C']) + new ImportedElements(fooFile.path, '', <String>['C']) ]); assertChanges(''' import 'package:pkg/foo.dart' show A, B, C hide D; @@ -137,12 +136,12 @@ } test_createEdits_addShow_singleName_noPrefix() async { - Source fooSource = addPackageSource('pkg', 'foo.dart', ''); + var fooFile = addPackageFile('pkg', 'foo.dart', ''); await createBuilder(''' import 'package:pkg/foo.dart' show B; '''); await computeChanges(<ImportedElements>[ - new ImportedElements(fooSource.fullName, '', <String>['A']) + new ImportedElements(fooFile.path, '', <String>['A']) ]); assertChanges(''' import 'package:pkg/foo.dart' show B, A; @@ -150,13 +149,13 @@ } test_createEdits_addShow_singleName_prefix() async { - Source fooSource = addPackageSource('pkg', 'foo.dart', ''); + var fooFile = addPackageFile('pkg', 'foo.dart', ''); await createBuilder(''' import 'package:pkg/foo.dart' show C; import 'package:pkg/foo.dart' as foo show B; '''); await computeChanges(<ImportedElements>[ - new ImportedElements(fooSource.fullName, 'foo', <String>['A']) + new ImportedElements(fooFile.path, 'foo', <String>['A']) ]); assertChanges(''' import 'package:pkg/foo.dart' show C; @@ -165,34 +164,34 @@ } test_createEdits_alreadyImported_noCombinators() async { - Source fooSource = addPackageSource('pkg', 'foo.dart', ''); + var fooFile = addPackageFile('pkg', 'foo.dart', ''); await createBuilder(''' import 'package:pkg/foo.dart'; '''); await computeChanges(<ImportedElements>[ - new ImportedElements(fooSource.fullName, '', <String>['A', 'B']) + new ImportedElements(fooFile.path, '', <String>['A', 'B']) ]); assertNoChanges(); } test_createEdits_alreadyImported_withPrefix() async { - Source fooSource = addPackageSource('pkg', 'foo.dart', ''); + var fooFile = addPackageFile('pkg', 'foo.dart', ''); await createBuilder(''' import 'package:pkg/foo.dart' as foo; '''); await computeChanges(<ImportedElements>[ - new ImportedElements(fooSource.fullName, 'foo', <String>['A', 'B']) + new ImportedElements(fooFile.path, 'foo', <String>['A', 'B']) ]); assertNoChanges(); } test_createEdits_alreadyImported_withShow() async { - Source fooSource = addPackageSource('pkg', 'foo.dart', ''); + var fooFile = addPackageFile('pkg', 'foo.dart', ''); await createBuilder(''' import 'package:pkg/foo.dart' show A; '''); await computeChanges(<ImportedElements>[ - new ImportedElements(fooSource.fullName, '', <String>['A']) + new ImportedElements(fooFile.path, '', <String>['A']) ]); assertNoChanges(); } @@ -210,12 +209,12 @@ } test_createEdits_invalidUri() async { - Source fooSource = addPackageSource('pkg', 'foo.dart', ''); + var fooFile = addPackageFile('pkg', 'foo.dart', ''); await createBuilder(''' import 'pakage:pkg/foo.dart'; '''); await computeChanges(<ImportedElements>[ - new ImportedElements(fooSource.fullName, '', <String>['A']) + new ImportedElements(fooFile.path, '', <String>['A']) ]); assertChanges(''' import 'pakage:pkg/foo.dart'; @@ -230,12 +229,12 @@ } test_createEdits_removeHide_firstInCombinator() async { - Source fooSource = addPackageSource('pkg', 'foo.dart', ''); + var fooFile = addPackageFile('pkg', 'foo.dart', ''); await createBuilder(''' import 'package:pkg/foo.dart' hide A, B, C; '''); await computeChanges(<ImportedElements>[ - new ImportedElements(fooSource.fullName, '', <String>['A']) + new ImportedElements(fooFile.path, '', <String>['A']) ]); assertChanges(''' import 'package:pkg/foo.dart' hide B, C; @@ -243,12 +242,12 @@ } test_createEdits_removeHide_lastInCombinator() async { - Source fooSource = addPackageSource('pkg', 'foo.dart', ''); + var fooFile = addPackageFile('pkg', 'foo.dart', ''); await createBuilder(''' import 'package:pkg/foo.dart' hide A, B, C; '''); await computeChanges(<ImportedElements>[ - new ImportedElements(fooSource.fullName, '', <String>['C']) + new ImportedElements(fooFile.path, '', <String>['C']) ]); assertChanges(''' import 'package:pkg/foo.dart' hide A, B; @@ -256,12 +255,12 @@ } test_createEdits_removeHide_middleInCombinator() async { - Source fooSource = addPackageSource('pkg', 'foo.dart', ''); + var fooFile = addPackageFile('pkg', 'foo.dart', ''); await createBuilder(''' import 'package:pkg/foo.dart' hide A, B, C; '''); await computeChanges(<ImportedElements>[ - new ImportedElements(fooSource.fullName, '', <String>['B']) + new ImportedElements(fooFile.path, '', <String>['B']) ]); assertChanges(''' import 'package:pkg/foo.dart' hide A, C; @@ -269,12 +268,12 @@ } test_createEdits_removeHide_multipleCombinators() async { - Source fooSource = addPackageSource('pkg', 'foo.dart', ''); + var fooFile = addPackageFile('pkg', 'foo.dart', ''); await createBuilder(''' import 'package:pkg/foo.dart' hide A, B, C hide A, B, C; '''); await computeChanges(<ImportedElements>[ - new ImportedElements(fooSource.fullName, '', <String>['B']) + new ImportedElements(fooFile.path, '', <String>['B']) ]); assertChanges(''' import 'package:pkg/foo.dart' hide A, C hide A, C; @@ -282,12 +281,12 @@ } test_createEdits_removeHide_multipleNames() async { - Source fooSource = addPackageSource('pkg', 'foo.dart', ''); + var fooFile = addPackageFile('pkg', 'foo.dart', ''); await createBuilder(''' import 'package:pkg/foo.dart' hide A, B, C hide D, E, F hide G, H, I; '''); await computeChanges(<ImportedElements>[ - new ImportedElements(fooSource.fullName, '', <String>['A', 'E', 'I']) + new ImportedElements(fooFile.path, '', <String>['A', 'E', 'I']) ]); assertChanges(''' import 'package:pkg/foo.dart' hide B, C hide D, F hide G, H; @@ -295,12 +294,12 @@ } test_createEdits_removeHideCombinator_first() async { - Source fooSource = addPackageSource('pkg', 'foo.dart', ''); + var fooFile = addPackageFile('pkg', 'foo.dart', ''); await createBuilder(''' import 'package:pkg/foo.dart' hide A hide B hide C; '''); await computeChanges(<ImportedElements>[ - new ImportedElements(fooSource.fullName, '', <String>['A']) + new ImportedElements(fooFile.path, '', <String>['A']) ]); assertChanges(''' import 'package:pkg/foo.dart' hide B hide C; @@ -308,12 +307,12 @@ } test_createEdits_removeHideCombinator_last() async { - Source fooSource = addPackageSource('pkg', 'foo.dart', ''); + var fooFile = addPackageFile('pkg', 'foo.dart', ''); await createBuilder(''' import 'package:pkg/foo.dart' hide A hide B hide C; '''); await computeChanges(<ImportedElements>[ - new ImportedElements(fooSource.fullName, '', <String>['C']) + new ImportedElements(fooFile.path, '', <String>['C']) ]); assertChanges(''' import 'package:pkg/foo.dart' hide A hide B; @@ -321,12 +320,12 @@ } test_createEdits_removeHideCombinator_middle() async { - Source fooSource = addPackageSource('pkg', 'foo.dart', ''); + var fooFile = addPackageFile('pkg', 'foo.dart', ''); await createBuilder(''' import 'package:pkg/foo.dart' hide A hide B hide C; '''); await computeChanges(<ImportedElements>[ - new ImportedElements(fooSource.fullName, '', <String>['B']) + new ImportedElements(fooFile.path, '', <String>['B']) ]); assertChanges(''' import 'package:pkg/foo.dart' hide A hide C; @@ -334,12 +333,12 @@ } test_createEdits_removeHideCombinator_only() async { - Source fooSource = addPackageSource('pkg', 'foo.dart', ''); + var fooFile = addPackageFile('pkg', 'foo.dart', ''); await createBuilder(''' import 'package:pkg/foo.dart' hide A; '''); await computeChanges(<ImportedElements>[ - new ImportedElements(fooSource.fullName, '', <String>['A']) + new ImportedElements(fooFile.path, '', <String>['A']) ]); assertChanges(''' import 'package:pkg/foo.dart'; @@ -347,12 +346,12 @@ } test_createEdits_removeHideCombinator_only_multiple() async { - Source fooSource = addPackageSource('pkg', 'foo.dart', ''); + var fooFile = addPackageFile('pkg', 'foo.dart', ''); await createBuilder(''' import 'package:pkg/foo.dart' hide A, B; '''); await computeChanges(<ImportedElements>[ - new ImportedElements(fooSource.fullName, '', <String>['A', 'B']) + new ImportedElements(fooFile.path, '', <String>['A', 'B']) ]); assertChanges(''' import 'package:pkg/foo.dart';
diff --git a/pkg/analysis_server/test/src/computer/imported_elements_computer_test.dart b/pkg/analysis_server/test/src/computer/imported_elements_computer_test.dart index 55c106b..8a5dad4 100644 --- a/pkg/analysis_server/test/src/computer/imported_elements_computer_test.dart +++ b/pkg/analysis_server/test/src/computer/imported_elements_computer_test.dart
@@ -24,7 +24,7 @@ setUp() { super.setUp(); - sourcePath = resourceProvider.convertPath('/p/lib/source.dart'); + sourcePath = convertPath('/home/test/lib/test.dart'); } test_dartAsync_noPrefix() async { @@ -43,7 +43,7 @@ ImportedElements elements2 = elementsList[1]; ImportedElements asyncElements; ImportedElements coreElements; - if (elements1.path == convertPath('/lib/core/core.dart')) { + if (elements1.path == convertPath('/sdk/lib/core/core.dart')) { coreElements = elements1; asyncElements = elements2; } else { @@ -51,12 +51,12 @@ asyncElements = elements1; } expect(coreElements, isNotNull); - expect(coreElements.path, convertPath('/lib/core/core.dart')); + expect(coreElements.path, convertPath('/sdk/lib/core/core.dart')); expect(coreElements.prefix, ''); expect(coreElements.elements, unorderedEquals(['String'])); expect(asyncElements, isNotNull); - expect(asyncElements.path, convertPath('/lib/async/async.dart')); + expect(asyncElements.path, convertPath('/sdk/lib/async/async.dart')); expect(asyncElements.prefix, ''); expect(asyncElements.elements, unorderedEquals(['Future'])); } @@ -77,7 +77,7 @@ ImportedElements elements2 = elementsList[1]; ImportedElements asyncElements; ImportedElements coreElements; - if (elements1.path == convertPath('/lib/core/core.dart')) { + if (elements1.path == convertPath('/sdk/lib/core/core.dart')) { coreElements = elements1; asyncElements = elements2; } else { @@ -85,12 +85,12 @@ asyncElements = elements1; } expect(coreElements, isNotNull); - expect(coreElements.path, convertPath('/lib/core/core.dart')); + expect(coreElements.path, convertPath('/sdk/lib/core/core.dart')); expect(coreElements.prefix, ''); expect(coreElements.elements, unorderedEquals(['String'])); expect(asyncElements, isNotNull); - expect(asyncElements.path, convertPath('/lib/async/async.dart')); + expect(asyncElements.path, convertPath('/sdk/lib/async/async.dart')); expect(asyncElements.prefix, 'a'); expect(asyncElements.elements, unorderedEquals(['Future'])); } @@ -108,7 +108,7 @@ expect(elementsList, hasLength(1)); ImportedElements elements = elementsList[0]; expect(elements, isNotNull); - expect(elements.path, convertPath('/lib/core/core.dart')); + expect(elements.path, convertPath('/sdk/lib/core/core.dart')); expect(elements.prefix, ''); expect(elements.elements, unorderedEquals(['String'])); } @@ -127,7 +127,7 @@ expect(elementsList, hasLength(1)); ImportedElements elements = elementsList[0]; expect(elements, isNotNull); - expect(elements.path, convertPath('/lib/core/core.dart')); + expect(elements.path, convertPath('/sdk/lib/core/core.dart')); expect(elements.prefix, 'core'); expect(elements.elements, unorderedEquals(['String'])); } @@ -146,7 +146,7 @@ expect(elementsList, hasLength(1)); ImportedElements elements = elementsList[0]; expect(elements, isNotNull); - expect(elements.path, convertPath('/lib/math/math.dart')); + expect(elements.path, convertPath('/sdk/lib/math/math.dart')); expect(elements.prefix, ''); expect(elements.elements, unorderedEquals(['Random'])); } @@ -170,13 +170,13 @@ ImportedElements mathElements = elementsList[0]; expect(mathElements, isNotNull); - expect(mathElements.path, convertPath('/lib/math/math.dart')); + expect(mathElements.path, convertPath('/sdk/lib/math/math.dart')); expect(mathElements.prefix, ''); expect(mathElements.elements, unorderedEquals(['Random'])); ImportedElements coreElements = elementsList[1]; expect(coreElements, isNotNull); - expect(coreElements.path, convertPath('/lib/core/core.dart')); + expect(coreElements.path, convertPath('/sdk/lib/core/core.dart')); expect(coreElements.prefix, ''); expect(coreElements.elements, unorderedEquals(['String', 'print'])); } @@ -236,7 +236,7 @@ } test_package_multipleInSame() async { - addPackageSource('foo', 'foo.dart', ''' + addPackageFile('foo', 'foo.dart', ''' class A { static String a = ''; } @@ -256,13 +256,13 @@ expect(elementsList, hasLength(1)); ImportedElements elements = elementsList[0]; expect(elements, isNotNull); - expect(elements.path, convertPath('/pubcache/foo/lib/foo.dart')); + expect(elements.path, convertPath('/.pub-cache/foo/lib/foo.dart')); expect(elements.prefix, ''); expect(elements.elements, unorderedEquals(['A', 'B'])); } test_package_noPrefix() async { - addPackageSource('foo', 'foo.dart', ''' + addPackageFile('foo', 'foo.dart', ''' class Foo { static String first = ''; } @@ -279,13 +279,13 @@ expect(elementsList, hasLength(1)); ImportedElements elements = elementsList[0]; expect(elements, isNotNull); - expect(elements.path, convertPath('/pubcache/foo/lib/foo.dart')); + expect(elements.path, convertPath('/.pub-cache/foo/lib/foo.dart')); expect(elements.prefix, ''); expect(elements.elements, unorderedEquals(['Foo'])); } test_package_prefix_selected() async { - addPackageSource('foo', 'foo.dart', ''' + addPackageFile('foo', 'foo.dart', ''' class Foo { static String first = ''; } @@ -302,13 +302,13 @@ expect(elementsList, hasLength(1)); ImportedElements elements = elementsList[0]; expect(elements, isNotNull); - expect(elements.path, convertPath('/pubcache/foo/lib/foo.dart')); + expect(elements.path, convertPath('/.pub-cache/foo/lib/foo.dart')); expect(elements.prefix, 'f'); expect(elements.elements, unorderedEquals(['Foo'])); } test_package_prefix_unselected() async { - addPackageSource('foo', 'foo.dart', ''' + addPackageFile('foo', 'foo.dart', ''' class Foo { static String first = ''; } @@ -325,13 +325,13 @@ expect(elementsList, hasLength(1)); ImportedElements elements = elementsList[0]; expect(elements, isNotNull); - expect(elements.path, convertPath('/pubcache/foo/lib/foo.dart')); + expect(elements.path, convertPath('/.pub-cache/foo/lib/foo.dart')); expect(elements.prefix, ''); expect(elements.elements, unorderedEquals(['Foo'])); } test_package_prefixedAndNot() async { - addPackageSource('foo', 'foo.dart', ''' + addPackageFile('foo', 'foo.dart', ''' class Foo { static String first = ''; static String second = ''; @@ -362,12 +362,13 @@ } expect(notPrefixedElements, isNotNull); - expect(notPrefixedElements.path, convertPath('/pubcache/foo/lib/foo.dart')); + expect( + notPrefixedElements.path, convertPath('/.pub-cache/foo/lib/foo.dart')); expect(notPrefixedElements.prefix, ''); expect(notPrefixedElements.elements, unorderedEquals(['Foo'])); expect(prefixedElements, isNotNull); - expect(prefixedElements.path, convertPath('/pubcache/foo/lib/foo.dart')); + expect(prefixedElements.path, convertPath('/.pub-cache/foo/lib/foo.dart')); expect(prefixedElements.prefix, 'f'); expect(prefixedElements.elements, unorderedEquals(['Foo'])); } @@ -392,7 +393,7 @@ Future<List<ImportedElements>> _computeElements( String sourceContent, int offset, int length) async { newFile(sourcePath, content: sourceContent); - ResolveResult result = await driver.getResult(sourcePath); + ResolvedUnitResult result = await session.getResolvedUnit(sourcePath); ImportedElementsComputer computer = new ImportedElementsComputer(result.unit, offset, length); return computer.compute();
diff --git a/pkg/analysis_server/test/src/computer/outline_computer_test.dart b/pkg/analysis_server/test/src/computer/outline_computer_test.dart index 340045a..eb45aad 100644 --- a/pkg/analysis_server/test/src/computer/outline_computer_test.dart +++ b/pkg/analysis_server/test/src/computer/outline_computer_test.dart
@@ -5,7 +5,6 @@ import 'dart:async'; import 'package:analysis_server/src/computer/computer_outline.dart'; -import 'package:analyzer/src/dart/analysis/driver.dart'; import 'package:analyzer_plugin/protocol/protocol_common.dart'; import 'package:meta/meta.dart'; import 'package:test/test.dart'; @@ -27,15 +26,15 @@ @override void setUp() { super.setUp(); - testPath = resourceProvider.convertPath('/test.dart'); + testPath = convertPath('/home/test/lib/test.dart'); } Future<Outline> _computeOutline(String code) async { testCode = code; newFile(testPath, content: code); - AnalysisResult analysisResult = await driver.getResult(testPath); + var resolveResult = await session.getResolvedUnit(testPath); return new DartUnitOutlineComputer( - testPath, analysisResult.lineInfo, analysisResult.unit, + testPath, resolveResult.lineInfo, resolveResult.unit, withBasicFlutter: true) .compute(); } @@ -558,7 +557,7 @@ } test_isTest_isTestGroup() async { - addMetaPackageSource(); + addMetaPackage(); Outline outline = await _computeOutline(''' import 'package:meta/meta.dart'; @@ -1057,6 +1056,7 @@ Outline unitOutline = await _computeOutline(''' typedef String FTA<K, V>(int i, String s); typedef FTB(int p); +typedef GTAF<T> = void Function<S>(T t, S s); class A<T> {} class B {} class CTA<T> = A<T> with B; @@ -1067,7 +1067,7 @@ set propB(int v) {} '''); List<Outline> topOutlines = unitOutline.children; - expect(topOutlines, hasLength(10)); + expect(topOutlines, hasLength(11)); // FTA { Outline outline = topOutlines[0]; @@ -1098,9 +1098,24 @@ expect(element.parameters, "(int p)"); expect(element.returnType, ""); } + // GenericTypeAlias - function + { + Outline outline = topOutlines[2]; + Element element = outline.element; + expect(element.kind, ElementKind.FUNCTION_TYPE_ALIAS); + expect(element.name, "GTAF"); + expect(element.typeParameters, '<T>'); + { + Location location = element.location; + expect(location.offset, testCode.indexOf("GTAF<T> =")); + expect(location.length, "GTAF".length); + } + expect(element.parameters, "(T t, S s)"); + expect(element.returnType, "void"); + } // CTA { - Outline outline = topOutlines[4]; + Outline outline = topOutlines[5]; Element element = outline.element; expect(element.kind, ElementKind.CLASS_TYPE_ALIAS); expect(element.name, "CTA"); @@ -1115,7 +1130,7 @@ } // CTB { - Outline outline = topOutlines[5]; + Outline outline = topOutlines[6]; Element element = outline.element; expect(element.kind, ElementKind.CLASS_TYPE_ALIAS); expect(element.name, 'CTB'); @@ -1124,7 +1139,7 @@ } // fA { - Outline outline = topOutlines[6]; + Outline outline = topOutlines[7]; Element element = outline.element; expect(element.kind, ElementKind.FUNCTION); expect(element.name, "fA"); @@ -1138,7 +1153,7 @@ } // fB { - Outline outline = topOutlines[7]; + Outline outline = topOutlines[8]; Element element = outline.element; expect(element.kind, ElementKind.FUNCTION); expect(element.name, "fB"); @@ -1152,7 +1167,7 @@ } // propA { - Outline outline = topOutlines[8]; + Outline outline = topOutlines[9]; Element element = outline.element; expect(element.kind, ElementKind.GETTER); expect(element.name, "propA"); @@ -1166,7 +1181,7 @@ } // propB { - Outline outline = topOutlines[9]; + Outline outline = topOutlines[10]; Element element = outline.element; expect(element.kind, ElementKind.SETTER); expect(element.name, "propB");
diff --git a/pkg/analysis_server/test/src/domains/execution/completion_test.dart b/pkg/analysis_server/test/src/domains/execution/completion_test.dart index 4ba0ecd..41529c6 100644 --- a/pkg/analysis_server/test/src/domains/execution/completion_test.dart +++ b/pkg/analysis_server/test/src/domains/execution/completion_test.dart
@@ -25,7 +25,7 @@ RuntimeCompletionResult result; void addContextFile(String content) { - contextFile = convertPath('/test/lib/context.dart'); + contextFile = convertPath('/home/test/lib/context.dart'); addSource(contextFile, content); contextOffset = content.indexOf('// context line'); @@ -131,13 +131,13 @@ } test_inPart() async { - addSource('/test/lib/a.dart', r''' + addSource('/home/test/lib/a.dart', r''' part 'b.dart'; part 'context.dart'; int a; '''); - addSource('/test/lib/b.dart', r''' + addSource('/home/test/lib/b.dart', r''' part of 'a.dart'; double b;
diff --git a/pkg/analysis_server/test/src/domains/execution/test_all.dart b/pkg/analysis_server/test/src/domains/execution/test_all.dart new file mode 100644 index 0000000..20e6141 --- /dev/null +++ b/pkg/analysis_server/test/src/domains/execution/test_all.dart
@@ -0,0 +1,13 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:test_reflective_loader/test_reflective_loader.dart'; + +import 'completion_test.dart' as completion_test; + +main() { + defineReflectiveSuite(() { + completion_test.main(); + }); +}
diff --git a/pkg/analysis_server/test/src/domains/test_all.dart b/pkg/analysis_server/test/src/domains/test_all.dart new file mode 100644 index 0000000..81a4c82 --- /dev/null +++ b/pkg/analysis_server/test/src/domains/test_all.dart
@@ -0,0 +1,13 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:test_reflective_loader/test_reflective_loader.dart'; + +import 'execution/test_all.dart' as execution_test; + +main() { + defineReflectiveSuite(() { + execution_test.main(); + }); +}
diff --git a/pkg/analysis_server/test/src/flutter/flutter_correction_test.dart b/pkg/analysis_server/test/src/flutter/flutter_correction_test.dart index 4501d68..1d7ba263 100644 --- a/pkg/analysis_server/test/src/flutter/flutter_correction_test.dart +++ b/pkg/analysis_server/test/src/flutter/flutter_correction_test.dart
@@ -125,11 +125,9 @@ void _createCorrections() { corrections = new FlutterCorrections( - file: testFile, - fileContent: testCode, - selectionOffset: offset, - selectionLength: length, - session: testAnalysisResult.session, - unit: testUnit); + resolveResult: testAnalysisResult, + selectionOffset: offset, + selectionLength: length, + ); } }
diff --git a/pkg/analysis_server/test/src/flutter/flutter_outline_computer_test.dart b/pkg/analysis_server/test/src/flutter/flutter_outline_computer_test.dart index e4b62c4..947fb79 100644 --- a/pkg/analysis_server/test/src/flutter/flutter_outline_computer_test.dart +++ b/pkg/analysis_server/test/src/flutter/flutter_outline_computer_test.dart
@@ -6,7 +6,7 @@ import 'package:analysis_server/src/flutter/flutter_outline_computer.dart'; import 'package:analysis_server/src/protocol_server.dart'; -import 'package:analyzer/src/dart/analysis/driver.dart'; +import 'package:analyzer/dart/analysis/results.dart'; import 'package:test/test.dart'; import 'package:test_reflective_loader/test_reflective_loader.dart'; @@ -22,13 +22,13 @@ class FlutterOutlineComputerTest extends AbstractContextTest { String testPath; String testCode; - AnalysisResult analysisResult; + ResolvedUnitResult resolveResult; FlutterOutlineComputer computer; @override void setUp() { super.setUp(); - testPath = resourceProvider.convertPath('/test.dart'); + testPath = convertPath('/home/test/lib/test.dart'); addFlutterPackage(); } @@ -288,7 +288,7 @@ } test_parentAssociationLabel() async { - newFile('/a.dart', content: r''' + newFile('/home/test/lib/a.dart', content: r''' import 'package:flutter/widgets.dart'; class WidgetA extends StatelessWidget { @@ -359,7 +359,7 @@ test_render_BAD_part() async { // Use test.dart as a part of a library. // Add the library to the driver so that it is analyzed before the part. - var libPath = newFile('/test_lib.dart', content: r''' + var libPath = newFile('/home/test/lib/test_lib.dart', content: r''' part 'test.dart'; import 'package:flutter/widgets.dart'; ''').path; @@ -379,7 +379,7 @@ '''); // Analysis is successful, no errors. - expect(analysisResult.errors, isEmpty); + expect(resolveResult.errors, isEmpty); // No instrumentation, because not a library. expect(computer.instrumentedCode, isNull); @@ -431,8 +431,7 @@ } test_render_instrumentedCode_rewriteUri_file() async { - testPath = resourceProvider.convertPath('/home/user/test/test.dart'); - var libFile = newFile('/home/user/test/my_lib.dart', content: ''); + newFile('/home/test/lib/my_lib.dart'); await _computeOutline(''' import 'package:flutter/widgets.dart'; @@ -451,7 +450,7 @@ computer.instrumentedCode, ''' import 'package:flutter/widgets.dart'; -import '${libFile.toUri()}'; +import 'package:test/my_lib.dart'; class MyWidget extends StatelessWidget { MyWidget.forDesignTime(); @@ -466,11 +465,7 @@ } test_render_instrumentedCode_rewriteUri_package() async { - packageMap['test'] = [newFolder('/home/user/test/lib')]; - - testPath = resourceProvider.convertPath('/home/user/test/lib/test.dart'); - newFile('/home/user/test/lib/my_lib.dart', content: ''); - configureDriver(); + newFile('/home/test/lib/my_lib.dart'); await _computeOutline(''' import 'package:flutter/widgets.dart'; @@ -630,9 +625,9 @@ Future<FlutterOutline> _computeOutline(String code) async { testCode = code; newFile(testPath, content: code); - analysisResult = await driver.getResult(testPath); - computer = new FlutterOutlineComputer( - testPath, testCode, analysisResult.lineInfo, analysisResult.unit); + resolveResult = await session.getResolvedUnit(testPath); + computer = new FlutterOutlineComputer(testPath, testCode, + resolveResult.lineInfo, resolveResult.unit, resolveResult.typeProvider); return computer.compute(); }
diff --git a/pkg/analysis_server/test/src/lsp/lsp_packet_transformer_test.dart b/pkg/analysis_server/test/src/lsp/lsp_packet_transformer_test.dart new file mode 100644 index 0000000..884a8cf --- /dev/null +++ b/pkg/analysis_server/test/src/lsp/lsp_packet_transformer_test.dart
@@ -0,0 +1,53 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'dart:convert'; + +import 'package:analysis_server/src/lsp/lsp_packet_transformer.dart'; +import 'package:test/test.dart'; + +main() { + group('lsp_packet_transformer', () { + test('transforms data received as individual bytes', () async { + final payload = '{ json payload }'; + final lspPacket = makeLspPacket(payload); + final output = await new Stream.fromIterable([lspPacket]) + .transform(new LspPacketTransformer()) + .toList(); + expect(output, equals([payload])); + }); + + test('transforms data received in chunks', () async { + final payload = '{ json\n payload\n }'; + final lspPacket = makeLspPacket(payload); + // Separate each byte into it's own "packet" to simulate chunked data + // where all the bytes for a single LSP packet don't arrive in one + // item to the stream. + final dataPackets = lspPacket.map((b) => [b]); + final output = await new Stream.fromIterable(dataPackets) + .transform(new LspPacketTransformer()) + .toList(); + expect(output, equals([payload])); + }); + + test('handles unicode characters', () async { + // This file is saved as UTF8. + final payload = '{ json payload 🎉 }'; + final lspPacket = makeLspPacket(payload); + final output = await new Stream.fromIterable([lspPacket]) + .transform(new LspPacketTransformer()) + .toList(); + expect(output, equals([payload])); + }); + }); +} + +List<int> makeLspPacket(String json, [String contentType]) { + final utf8EncodedBody = utf8.encode(json); + final header = 'Content-Length: ${utf8EncodedBody.length}\r\n' + 'Content-Type: application/vscode-jsonrpc; charset=utf-8\r\n\r\n'; + final asciiEncodedHeader = ascii.encode(header); + + return asciiEncodedHeader.followedBy(utf8EncodedBody).toList(); +}
diff --git a/pkg/analysis_server/test/src/plugin/plugin_locator_test.dart b/pkg/analysis_server/test/src/plugin/plugin_locator_test.dart index db3d3f9..a01ca1f 100644 --- a/pkg/analysis_server/test/src/plugin/plugin_locator_test.dart +++ b/pkg/analysis_server/test/src/plugin/plugin_locator_test.dart
@@ -1,4 +1,4 @@ -// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file +// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. @@ -14,7 +14,7 @@ } @reflectiveTest -class PluginLocatorTest extends Object with ResourceProviderMixin { +class PluginLocatorTest with ResourceProviderMixin { String packageRoot; String pubspecPath; String defaultDirPath;
diff --git a/pkg/analysis_server/test/src/plugin/plugin_manager_test.dart b/pkg/analysis_server/test/src/plugin/plugin_manager_test.dart index 6837470..186e284 100644 --- a/pkg/analysis_server/test/src/plugin/plugin_manager_test.dart +++ b/pkg/analysis_server/test/src/plugin/plugin_manager_test.dart
@@ -1,4 +1,4 @@ -// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file +// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. @@ -405,7 +405,7 @@ } @reflectiveTest -class PluginManagerTest extends Object with ResourceProviderMixin { +class PluginManagerTest with ResourceProviderMixin { String byteStorePath; String sdkPath; TestNotificationManager notificationManager; @@ -535,7 +535,7 @@ } @reflectiveTest -class PluginSessionTest extends Object with ResourceProviderMixin { +class PluginSessionTest with ResourceProviderMixin { TestNotificationManager notificationManager; String pluginPath; String executionPath;
diff --git a/pkg/analysis_server/test/src/plugin/plugin_watcher_test.dart b/pkg/analysis_server/test/src/plugin/plugin_watcher_test.dart index 058ee15..ca02919 100644 --- a/pkg/analysis_server/test/src/plugin/plugin_watcher_test.dart +++ b/pkg/analysis_server/test/src/plugin/plugin_watcher_test.dart
@@ -1,4 +1,4 @@ -// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file +// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. @@ -8,24 +8,24 @@ import 'package:analysis_server/src/plugin/plugin_locator.dart'; import 'package:analysis_server/src/plugin/plugin_manager.dart'; import 'package:analysis_server/src/plugin/plugin_watcher.dart'; +import 'package:analyzer/dart/analysis/results.dart'; import 'package:analyzer/dart/analysis/session.dart'; import 'package:analyzer/file_system/memory_file_system.dart'; import 'package:analyzer/src/context/context_root.dart'; +import 'package:analyzer/src/dart/analysis/byte_store.dart'; import 'package:analyzer/src/dart/analysis/driver.dart'; import 'package:analyzer/src/dart/analysis/file_state.dart'; +import 'package:analyzer/src/dart/analysis/performance_logger.dart'; import 'package:analyzer/src/dart/analysis/session.dart'; import 'package:analyzer/src/generated/engine.dart' show AnalysisOptionsImpl; import 'package:analyzer/src/generated/source.dart'; import 'package:analyzer/src/source/package_map_resolver.dart'; +import 'package:analyzer/src/test_utilities/mock_sdk.dart'; import 'package:analyzer/src/test_utilities/resource_provider_mixin.dart'; -import 'package:analyzer/src/dart/analysis/byte_store.dart'; -import 'package:analyzer/src/dart/analysis/performance_logger.dart'; import 'package:path/path.dart' as path; import 'package:test/test.dart'; import 'package:test_reflective_loader/test_reflective_loader.dart'; -import '../../mock_sdk.dart'; - main() { defineReflectiveSuite(() { defineReflectiveTests(PluginWatcherTest); @@ -33,7 +33,7 @@ } @reflectiveTest -class PluginWatcherTest extends Object with ResourceProviderMixin { +class PluginWatcherTest with ResourceProviderMixin { TestPluginManager manager; PluginWatcher watcher; @@ -119,7 +119,7 @@ AnalysisSession currentSession; AnalysisOptionsImpl analysisOptions = new AnalysisOptionsImpl(); - final _resultController = new StreamController<AnalysisResult>(); + final _resultController = new StreamController<ResolvedUnitResult>(); TestDriver(this.resourceProvider, ContextRoot contextRoot) { path.Context pathContext = resourceProvider.pathContext; @@ -147,12 +147,11 @@ currentSession = new AnalysisSessionImpl(this); } - Stream<AnalysisResult> get results => _resultController.stream; + Stream<ResolvedUnitResult> get results => _resultController.stream; Future<void> computeResult(String uri) { FileState file = fsState.getFileForUri(Uri.parse(uri)); - AnalysisResult result = new AnalysisResult(this, null, file.path, null, - true, null, null, false, null, null, null, null); + var result = new _ResolvedUnitResultMock(currentSession, file.path); _resultController.add(result); return new Future.delayed(new Duration(milliseconds: 1)); } @@ -182,3 +181,15 @@ removedContextRoots.add(contextRoot); } } + +class _ResolvedUnitResultMock implements ResolvedUnitResult { + @override + final AnalysisSession session; + + @override + final String path; + + _ResolvedUnitResultMock(this.session, this.path); + + noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation); +}
diff --git a/pkg/analysis_server/test/src/services/correction/assist/add_type_annotation_test.dart b/pkg/analysis_server/test/src/services/correction/assist/add_type_annotation_test.dart new file mode 100644 index 0000000..9d1e8fb --- /dev/null +++ b/pkg/analysis_server/test/src/services/correction/assist/add_type_annotation_test.dart
@@ -0,0 +1,576 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:analysis_server/src/services/correction/assist.dart'; +import 'package:analyzer_plugin/utilities/assist/assist.dart'; +import 'package:test_reflective_loader/test_reflective_loader.dart'; + +import 'assist_processor.dart'; + +main() { + defineReflectiveSuite(() { + defineReflectiveTests(AddTypeAnnotationTest); + }); +} + +@reflectiveTest +class AddTypeAnnotationTest extends AssistProcessorTest { + @override + AssistKind get kind => DartAssistKind.ADD_TYPE_ANNOTATION; + + test_classField_final() async { + await resolveTestUnit(''' +class A { + final f = 0; +} +'''); + await assertHasAssistAt('final ', ''' +class A { + final int f = 0; +} +'''); + } + + test_classField_int() async { + await resolveTestUnit(''' +class A { + var f = 0; +} +'''); + await await assertHasAssistAt('var ', ''' +class A { + int f = 0; +} +'''); + } + + test_declaredIdentifier() async { + await resolveTestUnit(''' +main(List<String> items) { + for (var item in items) { + } +} +'''); + // on identifier + await assertHasAssistAt('item in', ''' +main(List<String> items) { + for (String item in items) { + } +} +'''); + // on "for" + await assertHasAssistAt('for (', ''' +main(List<String> items) { + for (String item in items) { + } +} +'''); + } + + test_declaredIdentifier_addImport_dartUri() async { + addSource('/home/test/lib/my_lib.dart', r''' +import 'dart:collection'; +List<HashMap<String, int>> getMap() => null; +'''); + await resolveTestUnit(''' +import 'my_lib.dart'; +main() { + for (var map in getMap()) { + } +} +'''); + await assertHasAssistAt('map in', ''' +import 'dart:collection'; + +import 'my_lib.dart'; +main() { + for (HashMap<String, int> map in getMap()) { + } +} +'''); + } + + test_declaredIdentifier_final() async { + await resolveTestUnit(''' +main(List<String> items) { + for (final item in items) { + } +} +'''); + await assertHasAssistAt('item in', ''' +main(List<String> items) { + for (final String item in items) { + } +} +'''); + } + + test_declaredIdentifier_generic() async { + await resolveTestUnit(''' +class A<T> { + main(List<List<T>> items) { + for (var item in items) { + } + } +} +'''); + await assertHasAssistAt('item in', ''' +class A<T> { + main(List<List<T>> items) { + for (List<T> item in items) { + } + } +} +'''); + } + + test_declaredIdentifier_hasTypeAnnotation() async { + await resolveTestUnit(''' +main(List<String> items) { + for (String item in items) { + } +} +'''); + await assertNoAssistAt('item in'); + } + + test_declaredIdentifier_inForEachBody() async { + await resolveTestUnit(''' +main(List<String> items) { + for (var item in items) { + 42; + } +} +'''); + await assertNoAssistAt('42;'); + } + + test_declaredIdentifier_unknownType() async { + verifyNoTestUnitErrors = false; + await resolveTestUnit(''' +main() { + for (var item in unknownList) { + } +} +'''); + await assertNoAssistAt('item in'); + } + + test_local_addImport_dartUri() async { + addSource('/home/test/lib/my_lib.dart', r''' +import 'dart:collection'; +HashMap<String, int> getMap() => null; +'''); + await resolveTestUnit(''' +import 'my_lib.dart'; +main() { + var v = getMap(); +} +'''); + await assertHasAssistAt('v =', ''' +import 'dart:collection'; + +import 'my_lib.dart'; +main() { + HashMap<String, int> v = getMap(); +} +'''); + } + + test_local_addImport_notLibraryUnit() async { + addSource('/home/test/lib/my_lib.dart', r''' +import 'dart:collection'; +HashMap<String, int> getMap() => null; +'''); + + var appCode = r''' +library my_app; +import 'my_lib.dart'; +part 'test.dart'; +'''; + var partCode = r''' +part of my_app; +main() { + var /*caret*/v = getMap(); +} +'''; + + var appPath = convertPath('/home/test/lib/app.dart'); + addSource(appPath, appCode); + addSource(testFile, partCode); + await resolveTestUnit(partCode); + + await assertHasAssist(''' +part of my_app; +main() { + HashMap<String, int> /*caret*/v = getMap(); +} +''', additionallyChangedFiles: { + appPath: [ + appCode, + ''' +library my_app; +import 'dart:collection'; + +import 'my_lib.dart'; +part 'test.dart'; +''' + ] + }); + } + + test_local_addImport_relUri() async { + testFile = convertPath('/home/test/bin/test.dart'); + addSource('/home/test/bin/aa/bbb/lib_a.dart', r''' +class MyClass {} +'''); + addSource('/home/test/bin/ccc/lib_b.dart', r''' +import '../aa/bbb/lib_a.dart'; +MyClass newMyClass() => null; +'''); + await resolveTestUnit(''' +import 'ccc/lib_b.dart'; +main() { + var v = newMyClass(); +} +'''); + await assertHasAssistAt('v =', ''' +import 'aa/bbb/lib_a.dart'; +import 'ccc/lib_b.dart'; +main() { + MyClass v = newMyClass(); +} +'''); + } + + test_local_bottom() async { + await resolveTestUnit(''' +main() { + var v = throw 42; +} +'''); + await assertNoAssistAt('var '); + } + + test_local_Function() async { + await resolveTestUnit(''' +main() { + var v = () => 1; +} +'''); + await assertHasAssistAt('v =', ''' +main() { + int Function() v = () => 1; +} +'''); + } + + test_local_generic_literal() async { + await resolveTestUnit(''' +class A { + main(List<int> items) { + var v = items; + } +} +'''); + await assertHasAssistAt('v =', ''' +class A { + main(List<int> items) { + List<int> v = items; + } +} +'''); + } + + test_local_generic_local() async { + await resolveTestUnit(''' +class A<T> { + main(List<T> items) { + var v = items; + } +} +'''); + await assertHasAssistAt('v =', ''' +class A<T> { + main(List<T> items) { + List<T> v = items; + } +} +'''); + } + + test_local_hasTypeAnnotation() async { + await resolveTestUnit(''' +main() { + int v = 42; +} +'''); + await assertNoAssistAt(' = 42'); + } + + test_local_int() async { + await resolveTestUnit(''' +main() { + var v = 0; +} +'''); + await assertHasAssistAt('v =', ''' +main() { + int v = 0; +} +'''); + } + + test_local_List() async { + await resolveTestUnit(''' +main() { + var v = <String>[]; +} +'''); + await assertHasAssistAt('v =', ''' +main() { + List<String> v = <String>[]; +} +'''); + } + + test_local_localType() async { + await resolveTestUnit(''' +class C {} +C f() => null; +main() { + var x = f(); +} +'''); + await assertHasAssistAt('x =', ''' +class C {} +C f() => null; +main() { + C x = f(); +} +'''); + } + + test_local_multiple() async { + await resolveTestUnit(''' +main() { + var a = 1, b = ''; +} +'''); + await assertNoAssistAt('var '); + } + + test_local_noValue() async { + verifyNoTestUnitErrors = false; + await resolveTestUnit(''' +main() { + var v; +} +'''); + await assertNoAssistAt('var '); + } + + test_local_null() async { + await resolveTestUnit(''' +main() { + var v = null; +} +'''); + await assertNoAssistAt('var '); + } + + test_local_onInitializer() async { + await resolveTestUnit(''' +main() { + var abc = 0; +} +'''); + await assertNoAssistAt('0;'); + } + + test_local_onName() async { + await resolveTestUnit(''' +main() { + var abc = 0; +} +'''); + await assertHasAssistAt('bc', ''' +main() { + int abc = 0; +} +'''); + } + + test_local_onVar() async { + await resolveTestUnit(''' +main() { + var v = 0; +} +'''); + await assertHasAssistAt('var ', ''' +main() { + int v = 0; +} +'''); + } + + test_local_unknown() async { + verifyNoTestUnitErrors = false; + await resolveTestUnit(''' +main() { + var v = unknownVar; +} +'''); + await assertNoAssistAt('var '); + } + + test_parameter() async { + await resolveTestUnit(''' +foo(f(int p)) {} +main() { + foo((test) {}); +} +'''); + await assertHasAssistAt('test', ''' +foo(f(int p)) {} +main() { + foo((int test) {}); +} +'''); + } + + test_parameter_hasExplicitType() async { + await resolveTestUnit(''' +foo(f(int p)) {} +main() { + foo((num test) {}); +} +'''); + await assertNoAssistAt('test'); + } + + test_parameter_noPropagatedType() async { + await resolveTestUnit(''' +foo(f(p)) {} +main() { + foo((test) {}); +} +'''); + await assertNoAssistAt('test'); + } + + test_privateType_closureParameter() async { + addSource('/home/test/lib/my_lib.dart', ''' +library my_lib; +class A {} +class _B extends A {} +foo(f(_B p)) {} +'''); + await resolveTestUnit(''' +import 'my_lib.dart'; +main() { + foo((test) {}); +} + '''); + await assertNoAssistAt('test)'); + } + + test_privateType_declaredIdentifier() async { + addSource('/home/test/lib/my_lib.dart', ''' +library my_lib; +class A {} +class _B extends A {} +List<_B> getValues() => []; +'''); + await resolveTestUnit(''' +import 'my_lib.dart'; +class A<T> { + main() { + for (var item in getValues()) { + } + } +} +'''); + await assertNoAssistAt('var item'); + } + + test_privateType_list() async { + // This is now failing because we're suggesting "List" rather than nothing. + // Is it really better to produce nothing? + addSource('/home/test/lib/my_lib.dart', ''' +library my_lib; +class A {} +class _B extends A {} +List<_B> getValues() => []; +'''); + await resolveTestUnit(''' +import 'my_lib.dart'; +main() { + var v = getValues(); +} +'''); + await assertHasAssistAt('var ', ''' +import 'my_lib.dart'; +main() { + List v = getValues(); +} +'''); + } + + test_privateType_sameLibrary() async { + await resolveTestUnit(''' +class _A {} +_A getValue() => new _A(); +main() { + var v = getValue(); +} +'''); + await assertHasAssistAt('var ', ''' +class _A {} +_A getValue() => new _A(); +main() { + _A v = getValue(); +} +'''); + } + + test_privateType_variable() async { + addSource('/home/test/lib/my_lib.dart', ''' +library my_lib; +class A {} +class _B extends A {} +_B getValue() => new _B(); +'''); + await resolveTestUnit(''' +import 'my_lib.dart'; +main() { + var v = getValue(); +} +'''); + await assertNoAssistAt('var '); + } + + test_topLevelField_int() async { + await resolveTestUnit(''' +var V = 0; +'''); + await assertHasAssistAt('var ', ''' +int V = 0; +'''); + } + + test_topLevelField_multiple() async { + await resolveTestUnit(''' +var A = 1, V = ''; +'''); + await assertNoAssistAt('var '); + } + + test_topLevelField_noValue() async { + await resolveTestUnit(''' +var V; +'''); + await assertNoAssistAt('var '); + } +}
diff --git a/pkg/analysis_server/test/src/services/correction/assist/assign_to_local_variable_test.dart b/pkg/analysis_server/test/src/services/correction/assist/assign_to_local_variable_test.dart new file mode 100644 index 0000000..1668ea4 --- /dev/null +++ b/pkg/analysis_server/test/src/services/correction/assist/assign_to_local_variable_test.dart
@@ -0,0 +1,100 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:analysis_server/src/services/correction/assist.dart'; +import 'package:analyzer_plugin/protocol/protocol_common.dart'; +import 'package:analyzer_plugin/utilities/assist/assist.dart'; +import 'package:test_reflective_loader/test_reflective_loader.dart'; + +import 'assist_processor.dart'; + +main() { + defineReflectiveSuite(() { + defineReflectiveTests(AssignToLocalVariableTest); + }); +} + +@reflectiveTest +class AssignToLocalVariableTest extends AssistProcessorTest { + @override + AssistKind get kind => DartAssistKind.ASSIGN_TO_LOCAL_VARIABLE; + + test_alreadyAssignment() async { + await resolveTestUnit(''' +main() { + var vvv; + vvv = 42; +} +'''); + await assertNoAssistAt('vvv ='); + } + + test_inClosure() async { + await resolveTestUnit(r''' +main() { + print(() { + 12345; + }); +} +'''); + await assertHasAssistAt('345', ''' +main() { + print(() { + var i = 12345; + }); +} +'''); + } + + test_invocation() async { + await resolveTestUnit(''' +main() { + List<int> bytes; + readBytes(); +} +List<int> readBytes() => <int>[]; +'''); + await assertHasAssistAt('readBytes();', ''' +main() { + List<int> bytes; + var readBytes = readBytes(); +} +List<int> readBytes() => <int>[]; +'''); + assertLinkedGroup( + 0, + ['readBytes = '], + expectedSuggestions(LinkedEditSuggestionKind.VARIABLE, + ['list', 'bytes2', 'readBytes'])); + } + + test_invocationArgument() async { + await resolveTestUnit(r''' +main() { + f(12345); +} +void f(p) {} +'''); + await assertNoAssistAt('345'); + } + + test_throw() async { + await resolveTestUnit(''' +main() { + throw 42; +} +'''); + await assertNoAssistAt('throw '); + } + + test_void() async { + await resolveTestUnit(''' +main() { + f(); +} +void f() {} +'''); + await assertNoAssistAt('f();'); + } +}
diff --git a/pkg/analysis_server/test/src/services/correction/assist/assist_processor.dart b/pkg/analysis_server/test/src/services/correction/assist/assist_processor.dart new file mode 100644 index 0000000..450bc7e --- /dev/null +++ b/pkg/analysis_server/test/src/services/correction/assist/assist_processor.dart
@@ -0,0 +1,178 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'dart:async'; + +import 'package:analysis_server/plugin/edit/assist/assist_core.dart'; +import 'package:analysis_server/src/services/correction/assist.dart'; +import 'package:analysis_server/src/services/correction/assist_internal.dart'; +import 'package:analyzer_plugin/protocol/protocol_common.dart' + hide AnalysisError; +import 'package:analyzer_plugin/protocol/protocol_common.dart'; +import 'package:analyzer_plugin/utilities/assist/assist.dart'; +import 'package:test/test.dart'; + +import '../../../../abstract_single_unit.dart'; + +/// A base class defining support for writing assist processor tests. +abstract class AssistProcessorTest extends AbstractSingleUnitTest { + int _offset; + int _length; + + SourceChange _change; + String _resultCode; + + /// Return the kind of assist expected by this class. + AssistKind get kind; + + void assertExitPosition({String before, String after}) { + Position exitPosition = _change.selection; + expect(exitPosition, isNotNull); + expect(exitPosition.file, testFile); + if (before != null) { + expect(exitPosition.offset, _resultCode.indexOf(before)); + } else if (after != null) { + expect(exitPosition.offset, _resultCode.indexOf(after) + after.length); + } else { + fail("One of 'before' or 'after' expected."); + } + } + + /// Asserts that there is an assist of the given [kind] at [_offset] which + /// produces the [expected] code when applied to [testCode]. The map of + /// [additionallyChangedFiles] can be used to test assists that can modify + /// more than the test file. The keys are expected to be the paths to the + /// files that are modified (other than the test file) and the values are + /// pairs of source code: the states of the code before and after the edits + /// have been applied. + Future<void> assertHasAssist(String expected, + {Map<String, List<String>> additionallyChangedFiles}) async { + _setSelection(); + Assist assist = await _assertHasAssist(); + _change = assist.change; + expect(_change.id, kind.id); + // apply to "file" + List<SourceFileEdit> fileEdits = _change.edits; + if (additionallyChangedFiles == null) { + expect(fileEdits, hasLength(1)); + _resultCode = SourceEdit.applySequence(testCode, _change.edits[0].edits); + expect(_resultCode, expected); + } else { + expect(fileEdits, hasLength(additionallyChangedFiles.length + 1)); + _resultCode = SourceEdit.applySequence( + testCode, _change.getFileEdit(testFile).edits); + expect(_resultCode, expected); + for (String filePath in additionallyChangedFiles.keys) { + List<String> pair = additionallyChangedFiles[filePath]; + String resultCode = SourceEdit.applySequence( + pair[0], _change.getFileEdit(filePath).edits); + expect(resultCode, pair[1]); + } + } + } + + /// Asserts that there is an [Assist] of the given [kind] at the offset of the + /// given [snippet] which produces the [expected] code when applied to [testCode]. + Future<void> assertHasAssistAt(String snippet, String expected, + {int length = 0}) async { + _offset = findOffset(snippet); + _length = length; + Assist assist = await _assertHasAssist(); + _change = assist.change; + expect(_change.id, kind.id); + // apply to "file" + List<SourceFileEdit> fileEdits = _change.edits; + expect(fileEdits, hasLength(1)); + _resultCode = SourceEdit.applySequence(testCode, _change.edits[0].edits); + expect(_resultCode, expected); + } + + void assertLinkedGroup(int groupIndex, List<String> expectedStrings, + [List<LinkedEditSuggestion> expectedSuggestions]) { + LinkedEditGroup group = _change.linkedEditGroups[groupIndex]; + List<Position> expectedPositions = _findResultPositions(expectedStrings); + expect(group.positions, unorderedEquals(expectedPositions)); + if (expectedSuggestions != null) { + expect(group.suggestions, unorderedEquals(expectedSuggestions)); + } + } + + /// Asserts that there is no [Assist] of the given [kind] at [_offset]. + Future<void> assertNoAssist() async { + _setSelection(); + List<Assist> assists = await _computeAssists(); + for (Assist assist in assists) { + if (assist.kind == kind) { + fail('Unexpected assist $kind in\n${assists.join('\n')}'); + } + } + } + + /// Asserts that there is no [Assist] of the given [kind] at the offset of the + /// given [snippet]. + Future<void> assertNoAssistAt(String snippet, {int length = 0}) async { + _offset = findOffset(snippet); + _length = length; + List<Assist> assists = await _computeAssists(); + for (Assist assist in assists) { + if (assist.kind == kind) { + fail('Unexpected assist $kind in\n${assists.join('\n')}'); + } + } + } + + List<LinkedEditSuggestion> expectedSuggestions( + LinkedEditSuggestionKind kind, List<String> values) { + return values.map((value) { + return new LinkedEditSuggestion(value, kind); + }).toList(); + } + + /// Computes assists and verifies that there is an assist of the given kind. + Future<Assist> _assertHasAssist() async { + List<Assist> assists = await _computeAssists(); + for (Assist assist in assists) { + if (assist.kind == kind) { + return assist; + } + } + fail('Expected to find assist $kind in\n${assists.join('\n')}'); + } + + Future<List<Assist>> _computeAssists() async { + var context = new DartAssistContextImpl( + testAnalysisResult, + _offset, + _length, + ); + var processor = new AssistProcessor(context); + return await processor.compute(); + } + + List<Position> _findResultPositions(List<String> searchStrings) { + List<Position> positions = <Position>[]; + for (String search in searchStrings) { + int offset = _resultCode.indexOf(search); + positions.add(new Position(testFile, offset)); + } + return positions; + } + + void _setSelection() { + _offset = testCode.indexOf('/*caret*/'); + if (_offset >= 0) { + _offset += '/*caret*/'.length; + _length = 0; + } else { + _offset = testCode.indexOf('// start\n'); + if (_offset >= 0) { + _offset += '// start\n'.length; + _length = testCode.indexOf('// end') - _offset; + } else { + _offset = 0; + _length = 0; + } + } + } +}
diff --git a/pkg/analysis_server/test/src/services/correction/assist/convert_class_to_mixin_test.dart b/pkg/analysis_server/test/src/services/correction/assist/convert_class_to_mixin_test.dart new file mode 100644 index 0000000..ce8a4d3 --- /dev/null +++ b/pkg/analysis_server/test/src/services/correction/assist/convert_class_to_mixin_test.dart
@@ -0,0 +1,409 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:analysis_server/src/services/correction/assist.dart'; +import 'package:analyzer_plugin/utilities/assist/assist.dart'; +import 'package:test_reflective_loader/test_reflective_loader.dart'; + +import 'assist_processor.dart'; + +main() { + defineReflectiveSuite(() { + defineReflectiveTests(ConvertClassToMixinTest); + }); +} + +@reflectiveTest +class ConvertClassToMixinTest extends AssistProcessorTest { + @override + AssistKind get kind => DartAssistKind.CONVERT_CLASS_TO_MIXIN; + + test_abstract() async { + await resolveTestUnit(''' +abstract class A {} +'''); + await assertHasAssistAt('A', ''' +mixin A {} +'''); + } + + test_extends_noSuper() async { + await resolveTestUnit(''' +class A {} +class B extends A {} +'''); + await assertHasAssistAt('B', ''' +class A {} +mixin B implements A {} +'''); + } + + test_extends_super() async { + await resolveTestUnit(''' +class A { + a() {} +} +class B extends A { + b() { + super.a(); + } +} +'''); + await assertHasAssistAt('B', ''' +class A { + a() {} +} +mixin B on A { + b() { + super.a(); + } +} +'''); + } + + test_extends_superSuper() async { + await resolveTestUnit(''' +class A { + a() {} +} +class B extends A {} +class C extends B { + c() { + super.a(); + } +} +'''); + await assertHasAssistAt('C', ''' +class A { + a() {} +} +class B extends A {} +mixin C on B { + c() { + super.a(); + } +} +'''); + } + + test_extendsImplements_noSuper() async { + await resolveTestUnit(''' +class A {} +class B {} +class C extends A implements B {} +'''); + await assertHasAssistAt('C', ''' +class A {} +class B {} +mixin C implements A, B {} +'''); + } + + test_extendsImplements_super_extends() async { + await resolveTestUnit(''' +class A { + a() {} +} +class B {} +class C extends A implements B { + c() { + super.a(); + } +} +'''); + await assertHasAssistAt('C', ''' +class A { + a() {} +} +class B {} +mixin C on A implements B { + c() { + super.a(); + } +} +'''); + } + + test_extendsWith_noSuper() async { + await resolveTestUnit(''' +class A {} +class B {} +class C extends A with B {} +'''); + await assertHasAssistAt('C', ''' +class A {} +class B {} +mixin C implements A, B {} +'''); + } + + test_extendsWith_super_both() async { + await resolveTestUnit(''' +class A { + a() {} +} +class B { + b() {} +} +class C extends A with B { + c() { + super.a(); + super.b(); + } +} +'''); + await assertHasAssistAt('C', ''' +class A { + a() {} +} +class B { + b() {} +} +mixin C on A, B { + c() { + super.a(); + super.b(); + } +} +'''); + } + + test_extendsWith_super_extends() async { + await resolveTestUnit(''' +class A { + a() {} +} +class B { + b() {} +} +class C extends A with B { + c() { + super.a(); + } +} +'''); + await assertHasAssistAt('C', ''' +class A { + a() {} +} +class B { + b() {} +} +mixin C on A implements B { + c() { + super.a(); + } +} +'''); + } + + test_extendsWith_super_with() async { + await resolveTestUnit(''' +class A { + a() {} +} +class B { + b() {} +} +class C extends A with B { + c() { + super.b(); + } +} +'''); + await assertHasAssistAt('C', ''' +class A { + a() {} +} +class B { + b() {} +} +mixin C on B implements A { + c() { + super.b(); + } +} +'''); + } + + test_extendsWithImplements_noSuper() async { + await resolveTestUnit(''' +class A {} +class B {} +class C {} +class D extends A with B implements C {} +'''); + await assertHasAssistAt('D', ''' +class A {} +class B {} +class C {} +mixin D implements A, B, C {} +'''); + } + + test_extendsWithImplements_super_both() async { + await resolveTestUnit(''' +class A { + a() {} +} +class B { + b() {} +} +class C {} +class D extends A with B implements C { + d() { + super.a(); + super.b(); + } +} +'''); + await assertHasAssistAt('D', ''' +class A { + a() {} +} +class B { + b() {} +} +class C {} +mixin D on A, B implements C { + d() { + super.a(); + super.b(); + } +} +'''); + } + + test_extendsWithImplements_super_extends() async { + await resolveTestUnit(''' +class A { + a() {} +} +class B { + b() {} +} +class C {} +class D extends A with B implements C { + d() { + super.a(); + } +} +'''); + await assertHasAssistAt('D', ''' +class A { + a() {} +} +class B { + b() {} +} +class C {} +mixin D on A implements B, C { + d() { + super.a(); + } +} +'''); + } + + test_extendsWithImplements_super_with() async { + await resolveTestUnit(''' +class A { + a() {} +} +class B { + b() {} +} +class C {} +class D extends A with B implements C { + d() { + super.b(); + } +} +'''); + await assertHasAssistAt('D', ''' +class A { + a() {} +} +class B { + b() {} +} +class C {} +mixin D on B implements A, C { + d() { + super.b(); + } +} +'''); + } + + test_implements() async { + await resolveTestUnit(''' +class A {} +class B implements A {} +'''); + await assertHasAssistAt('B', ''' +class A {} +mixin B implements A {} +'''); + } + + test_noClauses_invalidSelection() async { + await resolveTestUnit(''' +class A {} +'''); + await assertNoAssistAt('{}'); + } + + test_noClauses_selectKeyword() async { + await resolveTestUnit(''' +class A {} +'''); + await assertHasAssistAt('class', ''' +mixin A {} +'''); + } + + test_noClauses_selectName() async { + await resolveTestUnit(''' +class A {} +'''); + await assertHasAssistAt('A', ''' +mixin A {} +'''); + } + + test_with_noSuper() async { + await resolveTestUnit(''' +class A {} +class B with A {} +'''); + await assertHasAssistAt('B', ''' +class A {} +mixin B implements A {} +'''); + } + + test_with_super() async { + await resolveTestUnit(''' +class A { + a() {} +} +class B with A { + b() { + super.a(); + } +} +'''); + await assertHasAssistAt('B', ''' +class A { + a() {} +} +mixin B on A { + b() { + super.a(); + } +} +'''); + } +}
diff --git a/pkg/analysis_server/test/src/services/correction/assist/convert_documentation_into_block_test.dart b/pkg/analysis_server/test/src/services/correction/assist/convert_documentation_into_block_test.dart new file mode 100644 index 0000000..895f645 --- /dev/null +++ b/pkg/analysis_server/test/src/services/correction/assist/convert_documentation_into_block_test.dart
@@ -0,0 +1,96 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:analysis_server/src/services/correction/assist.dart'; +import 'package:analyzer_plugin/utilities/assist/assist.dart'; +import 'package:test_reflective_loader/test_reflective_loader.dart'; + +import 'assist_processor.dart'; + +main() { + defineReflectiveSuite(() { + defineReflectiveTests(ConvertDocumentationIntoBlockTest); + }); +} + +@reflectiveTest +class ConvertDocumentationIntoBlockTest extends AssistProcessorTest { + @override + AssistKind get kind => DartAssistKind.CONVERT_DOCUMENTATION_INTO_BLOCK; + + test_alreadyBlock() async { + await resolveTestUnit(''' +/** + * AAAAAAA + */ +class A {} +'''); + await assertNoAssistAt('AAA'); + } + + test_noSpaceBeforeText() async { + await resolveTestUnit(''' +class A { + /// AAAAA + ///BBBBB + /// + /// CCCCC + mmm() {} +} +'''); + await assertHasAssistAt('AAAAA', ''' +class A { + /** + * AAAAA + *BBBBB + * + * CCCCC + */ + mmm() {} +} +'''); + } + + test_notDocumentation() async { + await resolveTestUnit(''' +// AAAA +class A {} +'''); + await assertNoAssistAt('AAA'); + } + + test_onReference() async { + await resolveTestUnit(''' +/// AAAAAAA [int] AAAAAAA +class A {} +'''); + await assertHasAssistAt('nt]', ''' +/** + * AAAAAAA [int] AAAAAAA + */ +class A {} +'''); + } + + test_onText() async { + await resolveTestUnit(''' +class A { + /// AAAAAAA [int] AAAAAAA + /// BBBBBBBB BBBB BBBB + /// CCC [A] CCCCCCCCCCC + mmm() {} +} +'''); + await assertHasAssistAt('AAA [', ''' +class A { + /** + * AAAAAAA [int] AAAAAAA + * BBBBBBBB BBBB BBBB + * CCC [A] CCCCCCCCCCC + */ + mmm() {} +} +'''); + } +}
diff --git a/pkg/analysis_server/test/src/services/correction/assist/convert_documentation_into_line_test.dart b/pkg/analysis_server/test/src/services/correction/assist/convert_documentation_into_line_test.dart new file mode 100644 index 0000000..535bf55 --- /dev/null +++ b/pkg/analysis_server/test/src/services/correction/assist/convert_documentation_into_line_test.dart
@@ -0,0 +1,112 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:analysis_server/src/services/correction/assist.dart'; +import 'package:analyzer_plugin/utilities/assist/assist.dart'; +import 'package:test_reflective_loader/test_reflective_loader.dart'; + +import 'assist_processor.dart'; + +main() { + defineReflectiveSuite(() { + defineReflectiveTests(ConvertDocumentationIntoLineTest); + }); +} + +@reflectiveTest +class ConvertDocumentationIntoLineTest extends AssistProcessorTest { + @override + AssistKind get kind => DartAssistKind.CONVERT_DOCUMENTATION_INTO_LINE; + + test_alreadyLine() async { + await resolveTestUnit(''' +/// AAAAAAA +class A {} +'''); + await assertNoAssistAt('AAA'); + } + + test_hasEmptyLine() async { + await resolveTestUnit(''' +class A { + /** + * AAAAAAA [int] AAAAAAA + * + * BBBBBBBB BBBB BBBB + */ + mmm() {} +} +'''); + await assertHasAssistAt('AAA [', ''' +class A { + /// AAAAAAA [int] AAAAAAA + /// + /// BBBBBBBB BBBB BBBB + mmm() {} +} +'''); + } + + test_notDocumentation() async { + await resolveTestUnit(''' +/* AAAA */ +class A {} +'''); + await assertNoAssistAt('AAA'); + } + + test_onReference() async { + await resolveTestUnit(''' +/** + * AAAAAAA [int] AAAAAAA + */ +class A {} +'''); + await assertHasAssistAt('nt]', ''' +/// AAAAAAA [int] AAAAAAA +class A {} +'''); + } + + test_onText() async { + await resolveTestUnit(''' +class A { + /** + * AAAAAAA [int] AAAAAAA + * BBBBBBBB BBBB BBBB + * CCC [A] CCCCCCCCCCC + */ + mmm() {} +} +'''); + await assertHasAssistAt('AAA [', ''' +class A { + /// AAAAAAA [int] AAAAAAA + /// BBBBBBBB BBBB BBBB + /// CCC [A] CCCCCCCCCCC + mmm() {} +} +'''); + } + + test_onText_hasFirstLine() async { + await resolveTestUnit(''' +class A { + /** AAAAAAA [int] AAAAAAA + * BBBBBBBB BBBB BBBB + * CCC [A] CCCCCCCCCCC + */ + mmm() {} +} +'''); + await assertHasAssistAt('AAA [', ''' +class A { + /// AAAAAAA [int] AAAAAAA + /// BBBBBBBB BBBB BBBB + /// CCC [A] CCCCCCCCCCC + mmm() {} +} +'''); + } +}
diff --git a/pkg/analysis_server/test/src/services/correction/assist/convert_into_async_body_test.dart b/pkg/analysis_server/test/src/services/correction/assist/convert_into_async_body_test.dart new file mode 100644 index 0000000..170a3c4 --- /dev/null +++ b/pkg/analysis_server/test/src/services/correction/assist/convert_into_async_body_test.dart
@@ -0,0 +1,149 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:analysis_server/src/services/correction/assist.dart'; +import 'package:analyzer_plugin/utilities/assist/assist.dart'; +import 'package:test_reflective_loader/test_reflective_loader.dart'; + +import 'assist_processor.dart'; + +main() { + defineReflectiveSuite(() { + defineReflectiveTests(ConvertIntoAsyncBodyTest); + }); +} + +@reflectiveTest +class ConvertIntoAsyncBodyTest extends AssistProcessorTest { + @override + AssistKind get kind => DartAssistKind.CONVERT_INTO_ASYNC_BODY; + + test_async() async { + await resolveTestUnit(''' +import 'dart:async'; +Future<String> f() async => ''; +'''); + await assertNoAssistAt('=>'); + } + + test_asyncStar() async { + await resolveTestUnit(''' +import 'dart:async'; +Stream<String> f() async* {} +'''); + await assertNoAssistAt('{}'); + } + + test_closure() async { + await resolveTestUnit(''' +main() { + f(() => 123); +} +f(g) {} +'''); + await assertHasAssistAt('=>', ''' +main() { + f(() async => 123); +} +f(g) {} +'''); + } + + test_constructor() async { + await resolveTestUnit(''' +class C { + C() {} +} +'''); + await assertNoAssistAt('{}'); + } + + test_function() async { + await resolveTestUnit(''' +String f() => ''; +'''); + await assertHasAssistAt('=>', ''' +Future<String> f() async => ''; +'''); + } + + test_getter_expression_noSpace() async { + await resolveTestUnit(''' +class C { + int get g=>0; +} +'''); + await assertHasAssistAt('get g', ''' +class C { + Future<int> get g async =>0; +} +'''); + } + + test_inBody_block() async { + await resolveTestUnit(''' +class C { + void foo() { + print(42); + } +} +'''); + await assertNoAssistAt('print'); + } + + test_inBody_expression() async { + await resolveTestUnit(''' +class C { + void foo() => print(42); +} +'''); + await assertNoAssistAt('print'); + } + + test_method() async { + await resolveTestUnit(''' +class C { + int m() { return 0; } +} +'''); + await assertHasAssistAt('{ return', ''' +class C { + Future<int> m() async { return 0; } +} +'''); + } + + test_method_abstract() async { + await resolveTestUnit(''' +abstract class C { + int m(); +} +'''); + await assertHasAssistAt('m()', ''' +abstract class C { + Future<int> m(); +} +'''); + } + + test_method_noReturnType() async { + await resolveTestUnit(''' +class C { + m() { return 0; } +} +'''); + await assertHasAssistAt('{ return', ''' +class C { + m() async { return 0; } +} +'''); + } + + test_syncStar() async { + await resolveTestUnit(''' +Iterable<String> f() sync* {} +'''); + await assertNoAssistAt('{}'); + } +}
diff --git a/pkg/analysis_server/test/src/services/correction/assist/convert_into_block_body_test.dart b/pkg/analysis_server/test/src/services/correction/assist/convert_into_block_body_test.dart new file mode 100644 index 0000000..4d3fa9c --- /dev/null +++ b/pkg/analysis_server/test/src/services/correction/assist/convert_into_block_body_test.dart
@@ -0,0 +1,162 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:analysis_server/src/services/correction/assist.dart'; +import 'package:analyzer_plugin/utilities/assist/assist.dart'; +import 'package:test_reflective_loader/test_reflective_loader.dart'; + +import 'assist_processor.dart'; + +main() { + defineReflectiveSuite(() { + defineReflectiveTests(ConvertIntoBlockBodyTest); + }); +} + +@reflectiveTest +class ConvertIntoBlockBodyTest extends AssistProcessorTest { + @override + AssistKind get kind => DartAssistKind.CONVERT_INTO_BLOCK_BODY; + + test_async() async { + await resolveTestUnit(''' +class A { + mmm() async => 123; +} +'''); + await assertHasAssistAt('mmm()', ''' +class A { + mmm() async { + return 123; + } +} +'''); + } + + test_closure() async { + await resolveTestUnit(''' +setup(x) {} +main() { + setup(() => 42); +} +'''); + await assertHasAssistAt('() => 42', ''' +setup(x) {} +main() { + setup(() { + return 42; + }); +} +'''); + assertExitPosition(after: '42;'); + } + + test_closure_voidExpression() async { + await resolveTestUnit(''' +setup(x) {} +main() { + setup(() => print('done')); +} +'''); + await assertHasAssistAt('() => print', ''' +setup(x) {} +main() { + setup(() { + print('done'); + }); +} +'''); + assertExitPosition(after: "');"); + } + + test_constructor() async { + await resolveTestUnit(''' +class A { + factory A() => null; +} +'''); + await assertHasAssistAt('A()', ''' +class A { + factory A() { + return null; + } +} +'''); + } + + test_inExpression() async { + await resolveTestUnit(''' +main() => 123; +'''); + await assertNoAssistAt('123;'); + } + + test_method() async { + await resolveTestUnit(''' +class A { + mmm() => 123; +} +'''); + await assertHasAssistAt('mmm()', ''' +class A { + mmm() { + return 123; + } +} +'''); + } + + test_noEnclosingFunction() async { + await resolveTestUnit(''' +var v = 123; +'''); + await assertNoAssistAt('v ='); + } + + test_notExpressionBlock() async { + await resolveTestUnit(''' +fff() { + return 123; +} +'''); + await assertNoAssistAt('fff() {'); + } + + test_onArrow() async { + await resolveTestUnit(''' +fff() => 123; +'''); + await assertHasAssistAt('=>', ''' +fff() { + return 123; +} +'''); + } + + test_onName() async { + await resolveTestUnit(''' +fff() => 123; +'''); + await assertHasAssistAt('fff()', ''' +fff() { + return 123; +} +'''); + } + + test_throw() async { + await resolveTestUnit(''' +class A { + mmm() => throw 'error'; +} +'''); + await assertHasAssistAt('mmm()', ''' +class A { + mmm() { + throw 'error'; + } +} +'''); + } +}
diff --git a/pkg/analysis_server/test/src/services/correction/assist/convert_into_expression_body_test.dart b/pkg/analysis_server/test/src/services/correction/assist/convert_into_expression_body_test.dart new file mode 100644 index 0000000..cb7e2e2 --- /dev/null +++ b/pkg/analysis_server/test/src/services/correction/assist/convert_into_expression_body_test.dart
@@ -0,0 +1,184 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:analysis_server/src/services/correction/assist.dart'; +import 'package:analyzer_plugin/utilities/assist/assist.dart'; +import 'package:test_reflective_loader/test_reflective_loader.dart'; + +import 'assist_processor.dart'; + +main() { + defineReflectiveSuite(() { + defineReflectiveTests(ConvertIntoExpressionBodyTest); + }); +} + +@reflectiveTest +class ConvertIntoExpressionBodyTest extends AssistProcessorTest { + @override + AssistKind get kind => DartAssistKind.CONVERT_INTO_EXPRESSION_BODY; + + test_already() async { + await resolveTestUnit(''' +fff() => 42; +'''); + await assertNoAssistAt('fff()'); + } + + test_async() async { + await resolveTestUnit(''' +class A { + mmm() async { + return 42; + } +} +'''); + await assertHasAssistAt('mmm', ''' +class A { + mmm() async => 42; +} +'''); + } + + test_closure() async { + await resolveTestUnit(''' +setup(x) {} +main() { + setup(() { + return 42; + }); +} +'''); + await assertHasAssistAt('return', ''' +setup(x) {} +main() { + setup(() => 42); +} +'''); + } + + test_closure_voidExpression() async { + await resolveTestUnit(''' +setup(x) {} +main() { + setup((_) { + print('test'); + }); +} +'''); + await assertHasAssistAt('(_) {', ''' +setup(x) {} +main() { + setup((_) => print('test')); +} +'''); + } + + test_constructor() async { + await resolveTestUnit(''' +class A { + factory A() { + return null; + } +} +'''); + await assertHasAssistAt('A()', ''' +class A { + factory A() => null; +} +'''); + } + + test_function_onBlock() async { + await resolveTestUnit(''' +fff() { + return 42; +} +'''); + await assertHasAssistAt('{', ''' +fff() => 42; +'''); + } + + test_function_onName() async { + await resolveTestUnit(''' +fff() { + return 42; +} +'''); + await assertHasAssistAt('ff()', ''' +fff() => 42; +'''); + } + + test_inExpression() async { + await resolveTestUnit(''' +main() { + return 42; +} +'''); + await assertNoAssistAt('42;'); + } + + test_method_onBlock() async { + await resolveTestUnit(''' +class A { + m() { // marker + return 42; + } +} +'''); + await assertHasAssistAt('{ // marker', ''' +class A { + m() => 42; +} +'''); + } + + test_moreThanOneStatement() async { + await resolveTestUnit(''' +fff() { + var v = 42; + return v; +} +'''); + await assertNoAssistAt('fff()'); + } + + test_noEnclosingFunction() async { + await resolveTestUnit(''' +var V = 42; +'''); + await assertNoAssistAt('V = '); + } + + test_noReturn() async { + await resolveTestUnit(''' +fff() { + var v = 42; +} +'''); + await assertNoAssistAt('fff()'); + } + + test_noReturnValue() async { + await resolveTestUnit(''' +fff() { + return; +} +'''); + await assertNoAssistAt('fff()'); + } + + test_topFunction_onReturnStatement() async { + await resolveTestUnit(''' +fff() { + return 42; +} +'''); + await assertHasAssistAt('return', ''' +fff() => 42; +'''); + } +}
diff --git a/pkg/analysis_server/test/src/services/correction/assist/convert_into_final_field_test.dart b/pkg/analysis_server/test/src/services/correction/assist/convert_into_final_field_test.dart new file mode 100644 index 0000000..4fa51fa --- /dev/null +++ b/pkg/analysis_server/test/src/services/correction/assist/convert_into_final_field_test.dart
@@ -0,0 +1,194 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:analysis_server/src/services/correction/assist.dart'; +import 'package:analyzer_plugin/utilities/assist/assist.dart'; +import 'package:test_reflective_loader/test_reflective_loader.dart'; + +import 'assist_processor.dart'; + +main() { + defineReflectiveSuite(() { + defineReflectiveTests(ConvertIntoFinalFieldTest); + }); +} + +@reflectiveTest +class ConvertIntoFinalFieldTest extends AssistProcessorTest { + @override + AssistKind get kind => DartAssistKind.CONVERT_INTO_FINAL_FIELD; + + test_blockBody_onlyReturnStatement() async { + await resolveTestUnit(''' +class A { + int get foo { + return 1 + 2; + } +} +'''); + await assertHasAssistAt('get foo', ''' +class A { + final int foo = 1 + 2; +} +'''); + } + + test_hasOverride() async { + await resolveTestUnit(''' +const myAnnotation = const Object(); +class A { + @myAnnotation + int get foo => 42; +} +'''); + await assertHasAssistAt('get foo', ''' +const myAnnotation = const Object(); +class A { + @myAnnotation + final int foo = 42; +} +'''); + } + + test_hasSetter_inSuper() async { + await resolveTestUnit(''' +class A { + void set foo(_) {} +} +class B extends A { + int get foo => null; +} +'''); + await assertHasAssistAt('get foo', ''' +class A { + void set foo(_) {} +} +class B extends A { + final int foo; +} +'''); + } + + test_hasSetter_inThisClass() async { + await resolveTestUnit(''' +class A { + int get foo => null; + void set foo(_) {} +} +'''); + await assertNoAssistAt('get foo'); + } + + test_noReturnType() async { + await resolveTestUnit(''' +class A { + get foo => 42; +} +'''); + await assertHasAssistAt('get foo', ''' +class A { + final foo = 42; +} +'''); + } + + test_noReturnType_static() async { + await resolveTestUnit(''' +class A { + static get foo => 42; +} +'''); + await assertHasAssistAt('get foo', ''' +class A { + static final foo = 42; +} +'''); + } + + test_notExpressionBody() async { + await resolveTestUnit(''' +class A { + int get foo { + int v = 1 + 2; + return v + 3; + } +} +'''); + await assertNoAssistAt('get foo'); + } + + test_notGetter() async { + await resolveTestUnit(''' +class A { + int foo() => 42; +} +'''); + await assertNoAssistAt('foo'); + } + + test_notNull() async { + await resolveTestUnit(''' +class A { + int get foo => 1 + 2; +} +'''); + await assertHasAssistAt('get foo', ''' +class A { + final int foo = 1 + 2; +} +'''); + } + + test_null() async { + await resolveTestUnit(''' +class A { + int get foo => null; +} +'''); + await assertHasAssistAt('get foo', ''' +class A { + final int foo; +} +'''); + } + + test_onName() async { + await resolveTestUnit(''' +class A { + int get foo => 42; +} +'''); + await assertHasAssistAt('foo', ''' +class A { + final int foo = 42; +} +'''); + } + + test_onReturnType_parameterized() async { + await resolveTestUnit(''' +class A { + List<int> get foo => null; +} +'''); + await assertHasAssistAt('nt> get', ''' +class A { + final List<int> foo; +} +'''); + } + + test_onReturnType_simple() async { + await resolveTestUnit(''' +class A { + int get foo => 42; +} +'''); + await assertHasAssistAt('int get', ''' +class A { + final int foo = 42; +} +'''); + } +}
diff --git a/pkg/analysis_server/test/src/services/correction/assist/convert_into_for_index_test.dart b/pkg/analysis_server/test/src/services/correction/assist/convert_into_for_index_test.dart new file mode 100644 index 0000000..5816d3a --- /dev/null +++ b/pkg/analysis_server/test/src/services/correction/assist/convert_into_for_index_test.dart
@@ -0,0 +1,168 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:analysis_server/src/services/correction/assist.dart'; +import 'package:analyzer_plugin/utilities/assist/assist.dart'; +import 'package:test_reflective_loader/test_reflective_loader.dart'; + +import 'assist_processor.dart'; + +main() { + defineReflectiveSuite(() { + defineReflectiveTests(ConvertIntoForIndexTest); + }); +} + +@reflectiveTest +class ConvertIntoForIndexTest extends AssistProcessorTest { + @override + AssistKind get kind => DartAssistKind.CONVERT_INTO_FOR_INDEX; + + test_bodyNotBlock() async { + await resolveTestUnit(''' +main(List<String> items) { + for (String item in items) print(item); +} +'''); + await assertNoAssistAt('for (String'); + } + + test_doesNotDeclareVariable() async { + await resolveTestUnit(''' +main(List<String> items) { + String item; + for (item in items) { + print(item); + } +} +'''); + await assertNoAssistAt('for (item'); + } + + test_iterableIsNotVariable() async { + await resolveTestUnit(''' +main() { + for (String item in ['a', 'b', 'c']) { + print(item); + } +} +'''); + await assertNoAssistAt('for (String'); + } + + test_iterableNotList() async { + await resolveTestUnit(''' +main(Iterable<String> items) { + for (String item in items) { + print(item); + } +} +'''); + await assertNoAssistAt('for (String'); + } + + test_onDeclaredIdentifier_name() async { + await resolveTestUnit(''' +main(List<String> items) { + for (String item in items) { + print(item); + } +} +'''); + await assertHasAssistAt('item in', ''' +main(List<String> items) { + for (int i = 0; i < items.length; i++) { + String item = items[i]; + print(item); + } +} +'''); + } + + test_onDeclaredIdentifier_type() async { + await resolveTestUnit(''' +main(List<String> items) { + for (String item in items) { + print(item); + } +} +'''); + await assertHasAssistAt('tring item', ''' +main(List<String> items) { + for (int i = 0; i < items.length; i++) { + String item = items[i]; + print(item); + } +} +'''); + } + + test_onFor() async { + await resolveTestUnit(''' +main(List<String> items) { + for (String item in items) { + print(item); + } +} +'''); + await assertHasAssistAt('for (String', ''' +main(List<String> items) { + for (int i = 0; i < items.length; i++) { + String item = items[i]; + print(item); + } +} +'''); + } + + test_usesI() async { + await resolveTestUnit(''' +main(List<String> items) { + for (String item in items) { + int i = 0; + } +} +'''); + await assertHasAssistAt('for (String', ''' +main(List<String> items) { + for (int j = 0; j < items.length; j++) { + String item = items[j]; + int i = 0; + } +} +'''); + } + + test_usesIJ() async { + await resolveTestUnit(''' +main(List<String> items) { + for (String item in items) { + print(item); + int i = 0, j = 1; + } +} +'''); + await assertHasAssistAt('for (String', ''' +main(List<String> items) { + for (int k = 0; k < items.length; k++) { + String item = items[k]; + print(item); + int i = 0, j = 1; + } +} +'''); + } + + test_usesIJK() async { + await resolveTestUnit(''' +main(List<String> items) { + for (String item in items) { + print(item); + int i, j, k; + } +} +'''); + await assertNoAssistAt('for (String'); + } +}
diff --git a/pkg/analysis_server/test/src/services/correction/assist/convert_into_generic_function_syntax_test.dart b/pkg/analysis_server/test/src/services/correction/assist/convert_into_generic_function_syntax_test.dart new file mode 100644 index 0000000..e9b034e --- /dev/null +++ b/pkg/analysis_server/test/src/services/correction/assist/convert_into_generic_function_syntax_test.dart
@@ -0,0 +1,103 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:analysis_server/src/services/correction/assist.dart'; +import 'package:analyzer_plugin/utilities/assist/assist.dart'; +import 'package:test_reflective_loader/test_reflective_loader.dart'; + +import 'assist_processor.dart'; + +main() { + defineReflectiveSuite(() { + defineReflectiveTests(ConvertIntoGenericFunctionSyntaxTest); + }); +} + +@reflectiveTest +class ConvertIntoGenericFunctionSyntaxTest extends AssistProcessorTest { + @override + AssistKind get kind => DartAssistKind.CONVERT_INTO_GENERIC_FUNCTION_SYNTAX; + + test_functionTypeAlias_insideParameterList() async { + await resolveTestUnit(''' +typedef String F(int x, int y); +'''); + await assertNoAssistAt('x,'); + } + + test_functionTypeAlias_noParameterTypes() async { + await resolveTestUnit(''' +typedef String F(x); +'''); + await assertNoAssistAt('def'); + } + + test_functionTypeAlias_noReturnType_noTypeParameters() async { + await resolveTestUnit(''' +typedef String F(int x); +'''); + await assertHasAssistAt('def', ''' +typedef F = String Function(int x); +'''); + } + + test_functionTypeAlias_noReturnType_typeParameters() async { + await resolveTestUnit(''' +typedef F<P, R>(P x); +'''); + await assertHasAssistAt('def', ''' +typedef F<P, R> = Function(P x); +'''); + } + + test_functionTypeAlias_returnType_noTypeParameters() async { + await resolveTestUnit(''' +typedef String F(int x); +'''); + await assertHasAssistAt('def', ''' +typedef F = String Function(int x); +'''); + } + + test_functionTypeAlias_returnType_typeParameters() async { + await resolveTestUnit(''' +typedef R F<P, R>(P x); +'''); + await assertHasAssistAt('def', ''' +typedef F<P, R> = R Function(P x); +'''); + } + + test_functionTypedParameter_insideParameterList() async { + await resolveTestUnit(''' +g(String f(int x, int y)) {} +'''); + await assertNoAssistAt('x,'); + } + + test_functionTypedParameter_noParameterTypes() async { + await resolveTestUnit(''' +g(String f(x)) {} +'''); + await assertNoAssistAt('f('); + } + + test_functionTypedParameter_noReturnType_noTypeParameters() async { + await resolveTestUnit(''' +g(f(int x)) {} +'''); + await assertHasAssistAt('f(', ''' +g(Function(int x) f) {} +'''); + } + + test_functionTypedParameter_returnType() async { + await resolveTestUnit(''' +g(String f(int x)) {} +'''); + await assertHasAssistAt('f(', ''' +g(String Function(int x) f) {} +'''); + } +}
diff --git a/pkg/analysis_server/test/src/services/correction/assist/convert_into_getter_test.dart b/pkg/analysis_server/test/src/services/correction/assist/convert_into_getter_test.dart new file mode 100644 index 0000000..f3348c2 --- /dev/null +++ b/pkg/analysis_server/test/src/services/correction/assist/convert_into_getter_test.dart
@@ -0,0 +1,79 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:analysis_server/src/services/correction/assist.dart'; +import 'package:analyzer_plugin/utilities/assist/assist.dart'; +import 'package:test_reflective_loader/test_reflective_loader.dart'; + +import 'assist_processor.dart'; + +main() { + defineReflectiveSuite(() { + defineReflectiveTests(ConvertIntoGetterTest); + }); +} + +@reflectiveTest +class ConvertIntoGetterTest extends AssistProcessorTest { + @override + AssistKind get kind => DartAssistKind.CONVERT_INTO_GETTER; + + test_noInitializer() async { + verifyNoTestUnitErrors = false; + await resolveTestUnit(''' +class A { + final int foo; +} +'''); + await assertNoAssistAt('foo'); + } + + test_notFinal() async { + await resolveTestUnit(''' +class A { + int foo = 1; +} +'''); + await assertNoAssistAt('foo'); + } + + test_notSingleField() async { + await resolveTestUnit(''' +class A { + final int foo = 1, bar = 2; +} +'''); + await assertNoAssistAt('foo'); + } + + test_noType() async { + await resolveTestUnit(''' +class A { + final foo = 42; +} +'''); + await assertHasAssistAt('foo =', ''' +class A { + get foo => 42; +} +'''); + } + + test_type() async { + await resolveTestUnit(''' +const myAnnotation = const Object(); +class A { + @myAnnotation + final int foo = 1 + 2; +} +'''); + await assertHasAssistAt('foo =', ''' +const myAnnotation = const Object(); +class A { + @myAnnotation + int get foo => 1 + 2; +} +'''); + } +}
diff --git a/pkg/analysis_server/test/src/services/correction/assist/convert_into_is_not_empty_test.dart b/pkg/analysis_server/test/src/services/correction/assist/convert_into_is_not_empty_test.dart new file mode 100644 index 0000000..cd522a7 --- /dev/null +++ b/pkg/analysis_server/test/src/services/correction/assist/convert_into_is_not_empty_test.dart
@@ -0,0 +1,100 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:analysis_server/src/services/correction/assist.dart'; +import 'package:analyzer_plugin/utilities/assist/assist.dart'; +import 'package:test_reflective_loader/test_reflective_loader.dart'; + +import 'assist_processor.dart'; + +main() { + defineReflectiveSuite(() { + defineReflectiveTests(ConvertIntoIsNotEmptyTest); + }); +} + +@reflectiveTest +class ConvertIntoIsNotEmptyTest extends AssistProcessorTest { + @override + AssistKind get kind => DartAssistKind.CONVERT_INTO_IS_NOT_EMPTY; + + test_noBang() async { + verifyNoTestUnitErrors = false; + await resolveTestUnit(''' +main(String str) { + ~str.isEmpty; +} +'''); + await assertNoAssistAt('isEmpty;'); + } + + test_noIsNotEmpty() async { + await resolveTestUnit(''' +class A { + bool get isEmpty => false; +} +main(A a) { + !a.isEmpty; +} +'''); + await assertNoAssistAt('isEmpty;'); + } + + test_notInPrefixExpression() async { + await resolveTestUnit(''' +main(String str) { + str.isEmpty; +} +'''); + await assertNoAssistAt('isEmpty;'); + } + + test_notIsEmpty() async { + await resolveTestUnit(''' +main(int p) { + !p.isEven; +} +'''); + await assertNoAssistAt('isEven;'); + } + + test_on_isEmpty() async { + await resolveTestUnit(''' +main(String str) { + !str.isEmpty; +} +'''); + await assertHasAssistAt('isEmpty', ''' +main(String str) { + str.isNotEmpty; +} +'''); + } + + test_on_str() async { + await resolveTestUnit(''' +main(String str) { + !str.isEmpty; +} +'''); + await assertHasAssistAt('str.', ''' +main(String str) { + str.isNotEmpty; +} +'''); + } + + test_propertyAccess() async { + await resolveTestUnit(''' +main(String str) { + !'text'.isEmpty; +} +'''); + await assertHasAssistAt('isEmpty', ''' +main(String str) { + 'text'.isNotEmpty; +} +'''); + } +}
diff --git a/pkg/analysis_server/test/src/services/correction/assist/convert_into_is_not_test.dart b/pkg/analysis_server/test/src/services/correction/assist/convert_into_is_not_test.dart new file mode 100644 index 0000000..f7e1ae1 --- /dev/null +++ b/pkg/analysis_server/test/src/services/correction/assist/convert_into_is_not_test.dart
@@ -0,0 +1,195 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:analysis_server/src/services/correction/assist.dart'; +import 'package:analyzer_plugin/utilities/assist/assist.dart'; +import 'package:test_reflective_loader/test_reflective_loader.dart'; + +import 'assist_processor.dart'; + +main() { + defineReflectiveSuite(() { + defineReflectiveTests(ConvertIntoIsNotTest); + }); +} + +@reflectiveTest +class ConvertIntoIsNotTest extends AssistProcessorTest { + @override + AssistKind get kind => DartAssistKind.CONVERT_INTO_IS_NOT; + + test_childOfIs_left() async { + await resolveTestUnit(''' +main(p) { + !(p is String); +} +'''); + await assertHasAssistAt('p is', ''' +main(p) { + p is! String; +} +'''); + } + + test_childOfIs_right() async { + await resolveTestUnit(''' +main(p) { + !(p is String); +} +'''); + await assertHasAssistAt('String)', ''' +main(p) { + p is! String; +} +'''); + } + + test_is() async { + await resolveTestUnit(''' +main(p) { + !(p is String); +} +'''); + await assertHasAssistAt('is String', ''' +main(p) { + p is! String; +} +'''); + } + + test_is_alreadyIsNot() async { + await resolveTestUnit(''' +main(p) { + p is! String; +} +'''); + await assertNoAssistAt('is!'); + } + + test_is_higherPrecedencePrefix() async { + await resolveTestUnit(''' +main(p) { + !!(p is String); +} +'''); + await assertHasAssistAt('is String', ''' +main(p) { + !(p is! String); +} +'''); + } + + test_is_noEnclosingParenthesis() async { + await resolveTestUnit(''' +main(p) { + p is String; +} +'''); + await assertNoAssistAt('is String'); + } + + test_is_noPrefix() async { + await resolveTestUnit(''' +main(p) { + (p is String); +} +'''); + await assertNoAssistAt('is String'); + } + + test_is_not_higherPrecedencePrefix() async { + await resolveTestUnit(''' +main(p) { + !!(p is String); +} +'''); + await assertHasAssistAt('!(p', ''' +main(p) { + !(p is! String); +} +'''); + } + + test_is_notIsExpression() async { + await resolveTestUnit(''' +main(p) { + 123 + 456; +} +'''); + await assertNoAssistAt('123 +'); + } + + test_is_notTheNotOperator() async { + verifyNoTestUnitErrors = false; + await resolveTestUnit(''' +main(p) { + ++(p is String); +} +'''); + await assertNoAssistAt('is String'); + } + + test_not() async { + await resolveTestUnit(''' +main(p) { + !(p is String); +} +'''); + await assertHasAssistAt('!(p', ''' +main(p) { + p is! String; +} +'''); + } + + test_not_alreadyIsNot() async { + await resolveTestUnit(''' +main(p) { + !(p is! String); +} +'''); + await assertNoAssistAt('!(p'); + } + + test_not_noEnclosingParenthesis() async { + await resolveTestUnit(''' +main(p) { + !p; +} +'''); + await assertNoAssistAt('!p'); + } + + test_not_notIsExpression() async { + await resolveTestUnit(''' +main(p) { + !(p == null); +} +'''); + await assertNoAssistAt('!(p'); + } + + test_not_notTheNotOperator() async { + verifyNoTestUnitErrors = false; + await resolveTestUnit(''' +main(p) { + ++(p is String); +} +'''); + await assertNoAssistAt('++('); + } + + test_parentheses() async { + await resolveTestUnit(''' +main(p) { + !(p is String); +} +'''); + await assertHasAssistAt('(p is', ''' +main(p) { + p is! String; +} +'''); + } +}
diff --git a/pkg/analysis_server/test/src/services/correction/assist/convert_part_of_to_uri_test.dart b/pkg/analysis_server/test/src/services/correction/assist/convert_part_of_to_uri_test.dart new file mode 100644 index 0000000..381e803 --- /dev/null +++ b/pkg/analysis_server/test/src/services/correction/assist/convert_part_of_to_uri_test.dart
@@ -0,0 +1,49 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:analysis_server/src/services/correction/assist.dart'; +import 'package:analyzer_plugin/utilities/assist/assist.dart'; +import 'package:test_reflective_loader/test_reflective_loader.dart'; + +import 'assist_processor.dart'; + +main() { + defineReflectiveSuite(() { + defineReflectiveTests(ConvertPartOfToUriTest); + }); +} + +@reflectiveTest +class ConvertPartOfToUriTest extends AssistProcessorTest { + @override + AssistKind get kind => DartAssistKind.CONVERT_PART_OF_TO_URI; + + test_nonSibling() async { + addSource('/pkg/lib/foo.dart', ''' +library foo; +part 'src/bar.dart'; +'''); + testFile = convertPath('/pkg/lib/src/bar.dart'); + await resolveTestUnit(''' +part of foo; +'''); + await assertHasAssistAt('foo', ''' +part of '../foo.dart'; +'''); + } + + test_sibling() async { + addSource('/pkg/foo.dart', ''' +library foo; +part 'bar.dart'; +'''); + testFile = convertPath('/pkg/bar.dart'); + await resolveTestUnit(''' +part of foo; +'''); + await assertHasAssistAt('foo', ''' +part of 'foo.dart'; +'''); + } +}
diff --git a/pkg/analysis_server/test/src/services/correction/assist/convert_to_double_quoted_string_test.dart b/pkg/analysis_server/test/src/services/correction/assist/convert_to_double_quoted_string_test.dart new file mode 100644 index 0000000..5711b07 --- /dev/null +++ b/pkg/analysis_server/test/src/services/correction/assist/convert_to_double_quoted_string_test.dart
@@ -0,0 +1,143 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:analysis_server/src/services/correction/assist.dart'; +import 'package:analyzer_plugin/utilities/assist/assist.dart'; +import 'package:test_reflective_loader/test_reflective_loader.dart'; + +import 'assist_processor.dart'; + +main() { + defineReflectiveSuite(() { + defineReflectiveTests(ConvertToDoubleQuotedStringTest); + }); +} + +@reflectiveTest +class ConvertToDoubleQuotedStringTest extends AssistProcessorTest { + @override + AssistKind get kind => DartAssistKind.CONVERT_TO_DOUBLE_QUOTED_STRING; + + test_one_embeddedTarget() async { + await resolveTestUnit(''' +main() { + print('a"b"c'); +} +'''); + await assertNoAssistAt("'a"); + } + + test_one_enclosingTarget() async { + await resolveTestUnit(''' +main() { + print("abc"); +} +'''); + await assertNoAssistAt('"ab'); + } + + test_one_interpolation() async { + await resolveTestUnit(r''' +main() { + var b = 'b'; + var c = 'c'; + print('a $b-${c} d'); +} +'''); + await assertHasAssistAt(r"'a $b", r''' +main() { + var b = 'b'; + var c = 'c'; + print("a $b-${c} d"); +} +'''); + } + + test_one_raw() async { + await resolveTestUnit(''' +main() { + print(r'abc'); +} +'''); + await assertHasAssistAt("'ab", ''' +main() { + print(r"abc"); +} +'''); + } + + test_one_simple() async { + await resolveTestUnit(''' +main() { + print('abc'); +} +'''); + await assertHasAssistAt("'ab", ''' +main() { + print("abc"); +} +'''); + } + + test_three_embeddedTarget() async { + await resolveTestUnit(""" +main() { + print('''a""\"c'''); +} +"""); + await assertNoAssistAt("'a"); + } + + test_three_enclosingTarget() async { + await resolveTestUnit(''' +main() { + print("""abc"""); +} +'''); + await assertNoAssistAt('"ab'); + } + + test_three_interpolation() async { + await resolveTestUnit(r""" +main() { + var b = 'b'; + var c = 'c'; + print('''a $b-${c} d'''); +} +"""); + await assertHasAssistAt(r"'a $b", r''' +main() { + var b = 'b'; + var c = 'c'; + print("""a $b-${c} d"""); +} +'''); + } + + test_three_raw() async { + await resolveTestUnit(""" +main() { + print(r'''abc'''); +} +"""); + await assertHasAssistAt("'ab", ''' +main() { + print(r"""abc"""); +} +'''); + } + + test_three_simple() async { + await resolveTestUnit(""" +main() { + print('''abc'''); +} +"""); + await assertHasAssistAt("'ab", ''' +main() { + print("""abc"""); +} +'''); + } +}
diff --git a/pkg/analysis_server/test/src/services/correction/assist/convert_to_field_parameter_test.dart b/pkg/analysis_server/test/src/services/correction/assist/convert_to_field_parameter_test.dart new file mode 100644 index 0000000..2cf9958 --- /dev/null +++ b/pkg/analysis_server/test/src/services/correction/assist/convert_to_field_parameter_test.dart
@@ -0,0 +1,110 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:analysis_server/src/services/correction/assist.dart'; +import 'package:analyzer_plugin/utilities/assist/assist.dart'; +import 'package:test_reflective_loader/test_reflective_loader.dart'; + +import 'assist_processor.dart'; + +main() { + defineReflectiveSuite(() { + defineReflectiveTests(ConvertToFieldParameterTest); + }); +} + +@reflectiveTest +class ConvertToFieldParameterTest extends AssistProcessorTest { + @override + AssistKind get kind => DartAssistKind.CONVERT_TO_FIELD_PARAMETER; + + test_additionalUse() async { + await resolveTestUnit(''' +class A { + int aaa2; + int bbb2; + A(int aaa) : aaa2 = aaa, bbb2 = aaa; +} +'''); + await assertNoAssistAt('aaa)'); + } + + test_firstInitializer() async { + await resolveTestUnit(''' +class A { + int aaa2; + int bbb2; + A(int aaa, int bbb) : aaa2 = aaa, bbb2 = bbb; +} +'''); + await assertHasAssistAt('aaa, ', ''' +class A { + int aaa2; + int bbb2; + A(this.aaa2, int bbb) : bbb2 = bbb; +} +'''); + } + + test_notPureAssignment() async { + await resolveTestUnit(''' +class A { + int aaa2; + A(int aaa) : aaa2 = aaa * 2; +} +'''); + await assertNoAssistAt('aaa)'); + } + + test_onParameterName_inInitializer() async { + await resolveTestUnit(''' +class A { + int test2; + A(int test) : test2 = test { + } +} +'''); + await assertHasAssistAt('test {', ''' +class A { + int test2; + A(this.test2) { + } +} +'''); + } + + test_onParameterName_inParameters() async { + await resolveTestUnit(''' +class A { + int test; + A(int test) : test = test { + } +} +'''); + await assertHasAssistAt('test)', ''' +class A { + int test; + A(this.test) { + } +} +'''); + } + + test_secondInitializer() async { + await resolveTestUnit(''' +class A { + int aaa2; + int bbb2; + A(int aaa, int bbb) : aaa2 = aaa, bbb2 = bbb; +} +'''); + await assertHasAssistAt('bbb)', ''' +class A { + int aaa2; + int bbb2; + A(int aaa, this.bbb2) : aaa2 = aaa; +} +'''); + } +}
diff --git a/pkg/analysis_server/test/src/services/correction/assist/convert_to_int_literal_test.dart b/pkg/analysis_server/test/src/services/correction/assist/convert_to_int_literal_test.dart new file mode 100644 index 0000000..d76730c --- /dev/null +++ b/pkg/analysis_server/test/src/services/correction/assist/convert_to_int_literal_test.dart
@@ -0,0 +1,53 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:analysis_server/src/services/correction/assist.dart'; +import 'package:analyzer_plugin/utilities/assist/assist.dart'; +import 'package:test_reflective_loader/test_reflective_loader.dart'; + +import 'assist_processor.dart'; + +main() { + defineReflectiveSuite(() { + defineReflectiveTests(ConvertToIntLiteralTest); + }); +} + +@reflectiveTest +class ConvertToIntLiteralTest extends AssistProcessorTest { + @override + AssistKind get kind => DartAssistKind.CONVERT_TO_INT_LITERAL; + + test_decimal() async { + await resolveTestUnit(''' +const double myDouble = /*caret*/42.0; +'''); + await assertHasAssist(''' +const double myDouble = /*caret*/42; +'''); + } + + test_notDouble() async { + await resolveTestUnit(''' +const double myDouble = /*caret*/42; +'''); + await assertNoAssist(); + } + + test_scientific() async { + await resolveTestUnit(''' +const double myDouble = /*caret*/4.2e1; +'''); + await assertHasAssist(''' +const double myDouble = /*caret*/42; +'''); + } + + test_tooBig() async { + await resolveTestUnit(''' +const double myDouble = /*caret*/4.2e99999; +'''); + await assertNoAssist(); + } +}
diff --git a/pkg/analysis_server/test/src/services/correction/assist/convert_to_normal_parameter_test.dart b/pkg/analysis_server/test/src/services/correction/assist/convert_to_normal_parameter_test.dart new file mode 100644 index 0000000..f5ddc23 --- /dev/null +++ b/pkg/analysis_server/test/src/services/correction/assist/convert_to_normal_parameter_test.dart
@@ -0,0 +1,72 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:analysis_server/src/services/correction/assist.dart'; +import 'package:analyzer_plugin/utilities/assist/assist.dart'; +import 'package:test_reflective_loader/test_reflective_loader.dart'; + +import 'assist_processor.dart'; + +main() { + defineReflectiveSuite(() { + defineReflectiveTests(ConvertToNormalParameterTest); + }); +} + +@reflectiveTest +class ConvertToNormalParameterTest extends AssistProcessorTest { + @override + AssistKind get kind => DartAssistKind.CONVERT_TO_NORMAL_PARAMETER; + + test_dynamic() async { + await resolveTestUnit(''' +class A { + var test; + A(this.test) { + } +} +'''); + await assertHasAssistAt('test)', ''' +class A { + var test; + A(test) : test = test { + } +} +'''); + } + + test_firstInitializer() async { + await resolveTestUnit(''' +class A { + int test; + A(this.test) { + } +} +'''); + await assertHasAssistAt('test)', ''' +class A { + int test; + A(int test) : test = test { + } +} +'''); + } + + test_secondInitializer() async { + await resolveTestUnit(''' +class A { + double aaa; + int bbb; + A(this.bbb) : aaa = 1.0; +} +'''); + await assertHasAssistAt('bbb)', ''' +class A { + double aaa; + int bbb; + A(int bbb) : aaa = 1.0, bbb = bbb; +} +'''); + } +}
diff --git a/pkg/analysis_server/test/src/services/correction/assist/convert_to_single_quoted_string_test.dart b/pkg/analysis_server/test/src/services/correction/assist/convert_to_single_quoted_string_test.dart new file mode 100644 index 0000000..161f62c --- /dev/null +++ b/pkg/analysis_server/test/src/services/correction/assist/convert_to_single_quoted_string_test.dart
@@ -0,0 +1,143 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:analysis_server/src/services/correction/assist.dart'; +import 'package:analyzer_plugin/utilities/assist/assist.dart'; +import 'package:test_reflective_loader/test_reflective_loader.dart'; + +import 'assist_processor.dart'; + +main() { + defineReflectiveSuite(() { + defineReflectiveTests(ConvertToSingleQuotedStringTest); + }); +} + +@reflectiveTest +class ConvertToSingleQuotedStringTest extends AssistProcessorTest { + @override + AssistKind get kind => DartAssistKind.CONVERT_TO_SINGLE_QUOTED_STRING; + + test_one_embeddedTarget() async { + await resolveTestUnit(''' +main() { + print("a'b'c"); +} +'''); + await assertNoAssistAt('"a'); + } + + test_one_enclosingTarget() async { + await resolveTestUnit(''' +main() { + print('abc'); +} +'''); + await assertNoAssistAt("'ab"); + } + + test_one_interpolation() async { + await resolveTestUnit(r''' +main() { + var b = 'b'; + var c = 'c'; + print("a $b-${c} d"); +} +'''); + await assertHasAssistAt(r'"a $b', r''' +main() { + var b = 'b'; + var c = 'c'; + print('a $b-${c} d'); +} +'''); + } + + test_one_raw() async { + await resolveTestUnit(''' +main() { + print(r"abc"); +} +'''); + await assertHasAssistAt('"ab', ''' +main() { + print(r'abc'); +} +'''); + } + + test_one_simple() async { + await resolveTestUnit(''' +main() { + print("abc"); +} +'''); + await assertHasAssistAt('"ab', ''' +main() { + print('abc'); +} +'''); + } + + test_three_embeddedTarget() async { + await resolveTestUnit(''' +main() { + print("""a''\'bc"""); +} +'''); + await assertNoAssistAt('"a'); + } + + test_three_enclosingTarget() async { + await resolveTestUnit(""" +main() { + print('''abc'''); +} +"""); + await assertNoAssistAt("'ab"); + } + + test_three_interpolation() async { + await resolveTestUnit(r''' +main() { + var b = 'b'; + var c = 'c'; + print("""a $b-${c} d"""); +} +'''); + await assertHasAssistAt(r'"a $b', r""" +main() { + var b = 'b'; + var c = 'c'; + print('''a $b-${c} d'''); +} +"""); + } + + test_three_raw() async { + await resolveTestUnit(''' +main() { + print(r"""abc"""); +} +'''); + await assertHasAssistAt('"ab', """ +main() { + print(r'''abc'''); +} +"""); + } + + test_three_simple() async { + await resolveTestUnit(''' +main() { + print("""abc"""); +} +'''); + await assertHasAssistAt('"ab', """ +main() { + print('''abc'''); +} +"""); + } +}
diff --git a/pkg/analysis_server/test/src/services/correction/assist/encapsulate_field_test.dart b/pkg/analysis_server/test/src/services/correction/assist/encapsulate_field_test.dart new file mode 100644 index 0000000..98e3baf --- /dev/null +++ b/pkg/analysis_server/test/src/services/correction/assist/encapsulate_field_test.dart
@@ -0,0 +1,164 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:analysis_server/src/services/correction/assist.dart'; +import 'package:analyzer_plugin/utilities/assist/assist.dart'; +import 'package:test_reflective_loader/test_reflective_loader.dart'; + +import 'assist_processor.dart'; + +main() { + defineReflectiveSuite(() { + defineReflectiveTests(EncapsulateFieldTest); + }); +} + +@reflectiveTest +class EncapsulateFieldTest extends AssistProcessorTest { + @override + AssistKind get kind => DartAssistKind.ENCAPSULATE_FIELD; + + test_alreadyPrivate() async { + await resolveTestUnit(''' +class A { + int _test = 42; +} +main(A a) { + print(a._test); +} +'''); + await assertNoAssistAt('_test ='); + } + + test_documentation() async { + await resolveTestUnit(''' +class A { + /// AAA + /// BBB + int test; +} +'''); + await assertHasAssistAt('test;', ''' +class A { + /// AAA + /// BBB + int _test; + + /// AAA + /// BBB + int get test => _test; + + /// AAA + /// BBB + set test(int test) { + _test = test; + } +} +'''); + } + + test_final() async { + await resolveTestUnit(''' +class A { + final int test = 42; +} +'''); + await assertNoAssistAt('test ='); + } + + test_hasType() async { + await resolveTestUnit(''' +class A { + int test = 42; + A(this.test); +} +main(A a) { + print(a.test); +} +'''); + await assertHasAssistAt('test = 42', ''' +class A { + int _test = 42; + + int get test => _test; + + set test(int test) { + _test = test; + } + A(this._test); +} +main(A a) { + print(a.test); +} +'''); + } + + test_multipleFields() async { + await resolveTestUnit(''' +class A { + int aaa, bbb, ccc; +} +main(A a) { + print(a.bbb); +} +'''); + await assertNoAssistAt('bbb, '); + } + + test_notOnName() async { + await resolveTestUnit(''' +class A { + int test = 1 + 2 + 3; +} +'''); + await assertNoAssistAt('+ 2'); + } + + test_noType() async { + await resolveTestUnit(''' +class A { + var test = 42; +} +main(A a) { + print(a.test); +} +'''); + await assertHasAssistAt('test = 42', ''' +class A { + var _test = 42; + + get test => _test; + + set test(test) { + _test = test; + } +} +main(A a) { + print(a.test); +} +'''); + } + + test_parseError() async { + verifyNoTestUnitErrors = false; + await resolveTestUnit(''' +class A { + int; // marker +} +main(A a) { + print(a.test); +} +'''); + await assertNoAssistAt('; // marker'); + } + + test_static() async { + await resolveTestUnit(''' +class A { + static int test = 42; +} +'''); + await assertNoAssistAt('test ='); + } +}
diff --git a/pkg/analysis_server/test/src/services/correction/assist/exchange_operands_test.dart b/pkg/analysis_server/test/src/services/correction/assist/exchange_operands_test.dart new file mode 100644 index 0000000..8bbcd52 --- /dev/null +++ b/pkg/analysis_server/test/src/services/correction/assist/exchange_operands_test.dart
@@ -0,0 +1,177 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:analysis_server/src/services/correction/assist.dart'; +import 'package:analyzer_plugin/utilities/assist/assist.dart'; +import 'package:test_reflective_loader/test_reflective_loader.dart'; + +import 'assist_processor.dart'; + +main() { + defineReflectiveSuite(() { + defineReflectiveTests(ExchangeOperandsTest); + }); +} + +@reflectiveTest +class ExchangeOperandsTest extends AssistProcessorTest { + @override + AssistKind get kind => DartAssistKind.EXCHANGE_OPERANDS; + + test_compare() async { + const initialOperators = const ['<', '<=', '>', '>=']; + const resultOperators = const ['>', '>=', '<', '<=']; + for (int i = 0; i <= 0; i++) { + String initialOperator = initialOperators[i]; + String resultOperator = resultOperators[i]; + await resolveTestUnit(''' +bool main(int a, int b) { + return a $initialOperator b; +} +'''); + await assertHasAssistAt(initialOperator, ''' +bool main(int a, int b) { + return b $resultOperator a; +} +'''); + } + } + + test_extended_mixOperator_1() async { + await resolveTestUnit(''' +main() { + 1 * 2 * 3 + 4; +} +'''); + await assertHasAssistAt('* 2', ''' +main() { + 2 * 3 * 1 + 4; +} +'''); + } + + test_extended_mixOperator_2() async { + await resolveTestUnit(''' +main() { + 1 + 2 - 3 + 4; +} +'''); + await assertHasAssistAt('+ 2', ''' +main() { + 2 + 1 - 3 + 4; +} +'''); + } + + test_extended_sameOperator_afterFirst() async { + await resolveTestUnit(''' +main() { + 1 + 2 + 3; +} +'''); + await assertHasAssistAt('+ 2', ''' +main() { + 2 + 3 + 1; +} +'''); + } + + test_extended_sameOperator_afterSecond() async { + await resolveTestUnit(''' +main() { + 1 + 2 + 3; +} +'''); + await assertHasAssistAt('+ 3', ''' +main() { + 3 + 1 + 2; +} +'''); + } + + test_extraLength() async { + await resolveTestUnit(''' +main() { + 111 + 222; +} +'''); + await assertNoAssistAt('+ 222', length: 3); + } + + test_onOperand() async { + await resolveTestUnit(''' +main() { + 111 + 222; +} +'''); + await assertNoAssistAt('11 +', length: 3); + } + + test_selectionWithBinary() async { + await resolveTestUnit(''' +main() { + 1 + 2 + 3; +} +'''); + await assertNoAssistAt('1 + 2 + 3', length: '1 + 2 + 3'.length); + } + + test_simple_afterOperator() async { + await resolveTestUnit(''' +main() { + 1 + 2; +} +'''); + await assertHasAssistAt(' 2', ''' +main() { + 2 + 1; +} +'''); + } + + test_simple_beforeOperator() async { + await resolveTestUnit(''' +main() { + 1 + 2; +} +'''); + await assertHasAssistAt('+ 2', ''' +main() { + 2 + 1; +} +'''); + } + + test_simple_fullSelection() async { + await resolveTestUnit(''' +main() { + 1 + 2; +} +'''); + await assertHasAssistAt( + '1 + 2', + ''' +main() { + 2 + 1; +} +''', + length: '1 + 2'.length); + } + + test_simple_withLength() async { + await resolveTestUnit(''' +main() { + 1 + 2; +} +'''); + await assertHasAssistAt( + '+ 2', + ''' +main() { + 2 + 1; +} +''', + length: 2); + } +}
diff --git a/pkg/analysis_server/test/src/services/correction/assist/flutter_convert_to_children_test.dart b/pkg/analysis_server/test/src/services/correction/assist/flutter_convert_to_children_test.dart new file mode 100644 index 0000000..8d34099 --- /dev/null +++ b/pkg/analysis_server/test/src/services/correction/assist/flutter_convert_to_children_test.dart
@@ -0,0 +1,158 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:analysis_server/src/services/correction/assist.dart'; +import 'package:analyzer_plugin/utilities/assist/assist.dart'; +import 'package:test_reflective_loader/test_reflective_loader.dart'; + +import 'assist_processor.dart'; + +main() { + defineReflectiveSuite(() { + defineReflectiveTests(FlutterConvertToChildrenTest); + }); +} + +@reflectiveTest +class FlutterConvertToChildrenTest extends AssistProcessorTest { + @override + AssistKind get kind => DartAssistKind.FLUTTER_CONVERT_TO_CHILDREN; + + test_childUnresolved() async { + addFlutterPackage(); + verifyNoTestUnitErrors = false; + await resolveTestUnit(''' +import 'package:flutter/material.dart'; +build() { + return new Row( + /*caret*/child: new Container() + ); +} +'''); + await assertNoAssist(); + } + + test_multiLine() async { + addFlutterPackage(); + await resolveTestUnit(''' +import 'package:flutter/material.dart'; +build() { + return new Scaffold( +// start + body: new Center( + /*caret*/child: new Container( + width: 200.0, + height: 300.0, + ), + key: null, + ), +// end + ); +} +'''); + await assertHasAssist(''' +import 'package:flutter/material.dart'; +build() { + return new Scaffold( +// start + body: new Center( + /*caret*/children: <Widget>[ + new Container( + width: 200.0, + height: 300.0, + ), + ], + key: null, + ), +// end + ); +} +'''); + } + + test_newlineChild() async { + // This case could occur with deeply nested constructors, common in Flutter. + addFlutterPackage(); + await resolveTestUnit(''' +import 'package:flutter/material.dart'; +build() { + return new Scaffold( +// start + body: new Center( + /*caret*/child: + new Container( + width: 200.0, + height: 300.0, + ), + key: null, + ), +// end + ); +} +'''); + await assertHasAssist(''' +import 'package:flutter/material.dart'; +build() { + return new Scaffold( +// start + body: new Center( + /*caret*/children: <Widget>[ + new Container( + width: 200.0, + height: 300.0, + ), + ], + key: null, + ), +// end + ); +} +'''); + } + + test_notOnChild() async { + addFlutterPackage(); + await resolveTestUnit(''' +import 'package:flutter/material.dart'; +build() { + return new Scaffold( + body: /*caret*/new Center( + child: new Container(), + ), + ); +} +'''); + await assertNoAssist(); + } + + test_singleLine() async { + addFlutterPackage(); + await resolveTestUnit(''' +import 'package:flutter/material.dart'; +build() { + return new Scaffold( +// start + body: new Center( + /*caret*/child: new GestureDetector(), + key: null, + ), +// end + ); +} +'''); + await assertHasAssist(''' +import 'package:flutter/material.dart'; +build() { + return new Scaffold( +// start + body: new Center( + /*caret*/children: <Widget>[new GestureDetector()], + key: null, + ), +// end + ); +} +'''); + } +}
diff --git a/pkg/analysis_server/test/src/services/correction/assist/flutter_convert_to_stateful_widget_test.dart b/pkg/analysis_server/test/src/services/correction/assist/flutter_convert_to_stateful_widget_test.dart new file mode 100644 index 0000000..977ea72 --- /dev/null +++ b/pkg/analysis_server/test/src/services/correction/assist/flutter_convert_to_stateful_widget_test.dart
@@ -0,0 +1,403 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:analysis_server/src/services/correction/assist.dart'; +import 'package:analyzer_plugin/utilities/assist/assist.dart'; +import 'package:test_reflective_loader/test_reflective_loader.dart'; + +import 'assist_processor.dart'; + +main() { + defineReflectiveSuite(() { + defineReflectiveTests(FlutterConvertToStatefulWidgetTest); + }); +} + +@reflectiveTest +class FlutterConvertToStatefulWidgetTest extends AssistProcessorTest { + @override + AssistKind get kind => DartAssistKind.FLUTTER_CONVERT_TO_STATEFUL_WIDGET; + + test_empty() async { + addFlutterPackage(); + await resolveTestUnit(r''' +import 'package:flutter/material.dart'; + +class /*caret*/MyWidget extends StatelessWidget { + @override + Widget build(BuildContext context) { + return new Container(); + } +} +'''); + await assertHasAssist(r''' +import 'package:flutter/material.dart'; + +class /*caret*/MyWidget extends StatefulWidget { + @override + MyWidgetState createState() { + return new MyWidgetState(); + } +} + +class MyWidgetState extends State<MyWidget> { + @override + Widget build(BuildContext context) { + return new Container(); + } +} +'''); + } + + test_fields() async { + addFlutterPackage(); + await resolveTestUnit(r''' +import 'package:flutter/material.dart'; + +class /*caret*/MyWidget extends StatelessWidget { + static String staticField1; + final String instanceField1; + final String instanceField2; + String instanceField3; + static String staticField2; + String instanceField4; + String instanceField5; + static String staticField3; + + MyWidget(this.instanceField1) : instanceField2 = '' { + instanceField3 = ''; + } + + @override + Widget build(BuildContext context) { + instanceField4 = instanceField1; + return new Row( + children: [ + new Text(instanceField1), + new Text(instanceField2), + new Text(instanceField3), + new Text(instanceField4), + new Text(instanceField5), + new Text(staticField1), + new Text(staticField2), + new Text(staticField3), + ], + ); + } +} +'''); + await assertHasAssist(r''' +import 'package:flutter/material.dart'; + +class /*caret*/MyWidget extends StatefulWidget { + static String staticField1; + final String instanceField1; + final String instanceField2; + String instanceField3; + static String staticField2; + static String staticField3; + + MyWidget(this.instanceField1) : instanceField2 = '' { + instanceField3 = ''; + } + + @override + MyWidgetState createState() { + return new MyWidgetState(); + } +} + +class MyWidgetState extends State<MyWidget> { + String instanceField4; + + String instanceField5; + + @override + Widget build(BuildContext context) { + instanceField4 = widget.instanceField1; + return new Row( + children: [ + new Text(widget.instanceField1), + new Text(widget.instanceField2), + new Text(widget.instanceField3), + new Text(instanceField4), + new Text(instanceField5), + new Text(MyWidget.staticField1), + new Text(MyWidget.staticField2), + new Text(MyWidget.staticField3), + ], + ); + } +} +'''); + } + + test_getters() async { + addFlutterPackage(); + await resolveTestUnit(r''' +import 'package:flutter/material.dart'; + +class /*caret*/MyWidget extends StatelessWidget { + @override + Widget build(BuildContext context) { + return new Row( + children: [ + new Text(staticGetter1), + new Text(staticGetter2), + new Text(instanceGetter1), + new Text(instanceGetter2), + ], + ); + } + + static String get staticGetter1 => ''; + + String get instanceGetter1 => ''; + + static String get staticGetter2 => ''; + + String get instanceGetter2 => ''; +} +'''); + await assertHasAssist(r''' +import 'package:flutter/material.dart'; + +class /*caret*/MyWidget extends StatefulWidget { + @override + MyWidgetState createState() { + return new MyWidgetState(); + } + + static String get staticGetter1 => ''; + + static String get staticGetter2 => ''; +} + +class MyWidgetState extends State<MyWidget> { + @override + Widget build(BuildContext context) { + return new Row( + children: [ + new Text(MyWidget.staticGetter1), + new Text(MyWidget.staticGetter2), + new Text(instanceGetter1), + new Text(instanceGetter2), + ], + ); + } + + String get instanceGetter1 => ''; + + String get instanceGetter2 => ''; +} +'''); + } + + test_methods() async { + addFlutterPackage(); + await resolveTestUnit(r''' +import 'package:flutter/material.dart'; + +class /*caret*/MyWidget extends StatelessWidget { + static String staticField; + final String instanceField1; + String instanceField2; + + MyWidget(this.instanceField1); + + @override + Widget build(BuildContext context) { + return new Row( + children: [ + new Text(instanceField1), + new Text(instanceField2), + new Text(staticField), + ], + ); + } + + void instanceMethod1() { + instanceMethod1(); + instanceMethod2(); + staticMethod1(); + } + + static void staticMethod1() { + print('static 1'); + } + + void instanceMethod2() { + print('instance 2'); + } + + static void staticMethod2() { + print('static 2'); + } +} +'''); + await assertHasAssist(r''' +import 'package:flutter/material.dart'; + +class /*caret*/MyWidget extends StatefulWidget { + static String staticField; + final String instanceField1; + + MyWidget(this.instanceField1); + + @override + MyWidgetState createState() { + return new MyWidgetState(); + } + + static void staticMethod1() { + print('static 1'); + } + + static void staticMethod2() { + print('static 2'); + } +} + +class MyWidgetState extends State<MyWidget> { + String instanceField2; + + @override + Widget build(BuildContext context) { + return new Row( + children: [ + new Text(widget.instanceField1), + new Text(instanceField2), + new Text(MyWidget.staticField), + ], + ); + } + + void instanceMethod1() { + instanceMethod1(); + instanceMethod2(); + MyWidget.staticMethod1(); + } + + void instanceMethod2() { + print('instance 2'); + } +} +'''); + } + + test_notClass() async { + addFlutterPackage(); + await resolveTestUnit(''' +import 'package:flutter/material.dart'; +/*caret*/main() {} +'''); + assertNoAssist(); + } + + test_notStatelessWidget() async { + addFlutterPackage(); + await resolveTestUnit(''' +import 'package:flutter/material.dart'; +class /*caret*/MyWidget extends Text { + MyWidget() : super(''); +} +'''); + assertNoAssist(); + } + + test_notWidget() async { + addFlutterPackage(); + await resolveTestUnit(''' +import 'package:flutter/material.dart'; +class /*caret*/MyWidget {} +'''); + assertNoAssist(); + } + + test_simple() async { + addFlutterPackage(); + await resolveTestUnit(r''' +import 'package:flutter/material.dart'; + +class /*caret*/MyWidget extends StatelessWidget { + final String aaa; + final String bbb; + + const MyWidget(this.aaa, this.bbb); + + @override + Widget build(BuildContext context) { + return new Row( + children: [ + new Text(aaa), + new Text(bbb), + new Text('$aaa'), + new Text('${bbb}'), + ], + ); + } +} +'''); + await assertHasAssist(r''' +import 'package:flutter/material.dart'; + +class /*caret*/MyWidget extends StatefulWidget { + final String aaa; + final String bbb; + + const MyWidget(this.aaa, this.bbb); + + @override + MyWidgetState createState() { + return new MyWidgetState(); + } +} + +class MyWidgetState extends State<MyWidget> { + @override + Widget build(BuildContext context) { + return new Row( + children: [ + new Text(widget.aaa), + new Text(widget.bbb), + new Text('${widget.aaa}'), + new Text('${widget.bbb}'), + ], + ); + } +} +'''); + } + + test_tail() async { + addFlutterPackage(); + await resolveTestUnit(r''' +import 'package:flutter/material.dart'; + +class /*caret*/MyWidget extends StatelessWidget { + @override + Widget build(BuildContext context) { + return new Container(); + } +} +'''); + await assertHasAssist(r''' +import 'package:flutter/material.dart'; + +class /*caret*/MyWidget extends StatefulWidget { + @override + MyWidgetState createState() { + return new MyWidgetState(); + } +} + +class MyWidgetState extends State<MyWidget> { + @override + Widget build(BuildContext context) { + return new Container(); + } +} +'''); + } +}
diff --git a/pkg/analysis_server/test/src/services/correction/assist/flutter_move_down_test.dart b/pkg/analysis_server/test/src/services/correction/assist/flutter_move_down_test.dart new file mode 100644 index 0000000..5885e70 --- /dev/null +++ b/pkg/analysis_server/test/src/services/correction/assist/flutter_move_down_test.dart
@@ -0,0 +1,80 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:analysis_server/src/services/correction/assist.dart'; +import 'package:analyzer_plugin/utilities/assist/assist.dart'; +import 'package:test_reflective_loader/test_reflective_loader.dart'; + +import 'assist_processor.dart'; + +main() { + defineReflectiveSuite(() { + defineReflectiveTests(FlutterMoveDownTest); + }); +} + +@reflectiveTest +class FlutterMoveDownTest extends AssistProcessorTest { + @override + AssistKind get kind => DartAssistKind.FLUTTER_MOVE_DOWN; + + test_first() async { + addFlutterPackage(); + await resolveTestUnit(''' +import 'package:flutter/material.dart'; +main() { + new Column( + children: <Widget>[ + new Text('aaa'), + /*caret*/new Text('bbbbbb'), + new Text('ccccccccc'), + ], + ); +} +'''); + await assertHasAssist(''' +import 'package:flutter/material.dart'; +main() { + new Column( + children: <Widget>[ + new Text('aaa'), + /*caret*/new Text('ccccccccc'), + new Text('bbbbbb'), + ], + ); +} +'''); + assertExitPosition(before: "new Text('bbbbbb')"); + } + + test_last() async { + addFlutterPackage(); + await resolveTestUnit(''' +import 'package:flutter/material.dart'; +main() { + new Column( + children: <Widget>[ + new Text('aaa'), + new Text('bbb'), + /*caret*/new Text('ccc'), + ], + ); +} +'''); + await assertNoAssist(); + } + + test_notInList() async { + addFlutterPackage(); + await resolveTestUnit(''' +import 'package:flutter/material.dart'; +main() { + new Center( + child: /*caret*/new Text('aaa'), + ); +} +'''); + await assertNoAssist(); + } +}
diff --git a/pkg/analysis_server/test/src/services/correction/assist/flutter_move_up_test.dart b/pkg/analysis_server/test/src/services/correction/assist/flutter_move_up_test.dart new file mode 100644 index 0000000..771bb73 --- /dev/null +++ b/pkg/analysis_server/test/src/services/correction/assist/flutter_move_up_test.dart
@@ -0,0 +1,80 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:analysis_server/src/services/correction/assist.dart'; +import 'package:analyzer_plugin/utilities/assist/assist.dart'; +import 'package:test_reflective_loader/test_reflective_loader.dart'; + +import 'assist_processor.dart'; + +main() { + defineReflectiveSuite(() { + defineReflectiveTests(FlutterMoveUpTest); + }); +} + +@reflectiveTest +class FlutterMoveUpTest extends AssistProcessorTest { + @override + AssistKind get kind => DartAssistKind.FLUTTER_MOVE_UP; + + test_first() async { + addFlutterPackage(); + await resolveTestUnit(''' +import 'package:flutter/material.dart'; +main() { + new Column( + children: <Widget>[ + /*caret*/new Text('aaa'), + new Text('bbb'), + new Text('ccc'), + ], + ); +} +'''); + await assertNoAssist(); + } + + test_last() async { + addFlutterPackage(); + await resolveTestUnit(''' +import 'package:flutter/material.dart'; +main() { + new Column( + children: <Widget>[ + new Text('aaa'), + /*caret*/new Text('bbbbbb'), + new Text('ccccccccc'), + ], + ); +} +'''); + await assertHasAssist(''' +import 'package:flutter/material.dart'; +main() { + new Column( + children: <Widget>[ + new Text('bbbbbb'), + /*caret*/new Text('aaa'), + new Text('ccccccccc'), + ], + ); +} +'''); + assertExitPosition(before: "new Text('bbbbbb')"); + } + + test_notInList() async { + addFlutterPackage(); + await resolveTestUnit(''' +import 'package:flutter/material.dart'; +main() { + new Center( + child: /*caret*/new Text('aaa'), + ); +} +'''); + await assertNoAssist(); + } +}
diff --git a/pkg/analysis_server/test/src/services/correction/assist/flutter_remove_widget_test.dart b/pkg/analysis_server/test/src/services/correction/assist/flutter_remove_widget_test.dart new file mode 100644 index 0000000..842b191 --- /dev/null +++ b/pkg/analysis_server/test/src/services/correction/assist/flutter_remove_widget_test.dart
@@ -0,0 +1,236 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:analysis_server/src/services/correction/assist.dart'; +import 'package:analyzer_plugin/utilities/assist/assist.dart'; +import 'package:test_reflective_loader/test_reflective_loader.dart'; + +import 'assist_processor.dart'; + +main() { + defineReflectiveSuite(() { + defineReflectiveTests(FlutterRemoveWidgetTest); + }); +} + +@reflectiveTest +class FlutterRemoveWidgetTest extends AssistProcessorTest { + @override + AssistKind get kind => DartAssistKind.FLUTTER_REMOVE_WIDGET; + + test_childIntoChild_multiLine() async { + addFlutterPackage(); + await resolveTestUnit(''' +import 'package:flutter/material.dart'; +main() { + new Column( + children: <Widget>[ + new Center( + child: new /*caret*/Padding( + padding: const EdgeInsets.all(8.0), + child: new Center( + heightFactor: 0.5, + child: new Text('foo'), + ), + ), + ), + ], + ); +} +'''); + await assertHasAssist(''' +import 'package:flutter/material.dart'; +main() { + new Column( + children: <Widget>[ + new Center( + child: new Center( + heightFactor: 0.5, + child: new Text('foo'), + ), + ), + ], + ); +} +'''); + } + + test_childIntoChild_singleLine() async { + addFlutterPackage(); + await resolveTestUnit(''' +import 'package:flutter/material.dart'; +main() { + new Padding( + padding: const EdgeInsets.all(8.0), + child: new /*caret*/Center( + heightFactor: 0.5, + child: new Text('foo'), + ), + ); +} +'''); + await assertHasAssist(''' +import 'package:flutter/material.dart'; +main() { + new Padding( + padding: const EdgeInsets.all(8.0), + child: new Text('foo'), + ); +} +'''); + } + + test_childIntoChildren() async { + addFlutterPackage(); + await resolveTestUnit(''' +import 'package:flutter/material.dart'; +main() { + new Column( + children: <Widget>[ + new Text('foo'), + new /*caret*/Center( + heightFactor: 0.5, + child: new Padding( + padding: const EdgeInsets.all(8.0), + child: new Text('bar'), + ), + ), + new Text('baz'), + ], + ); +} +'''); + await assertHasAssist(''' +import 'package:flutter/material.dart'; +main() { + new Column( + children: <Widget>[ + new Text('foo'), + new Padding( + padding: const EdgeInsets.all(8.0), + child: new Text('bar'), + ), + new Text('baz'), + ], + ); +} +'''); + } + + test_childrenMultipleIntoChild() async { + addFlutterPackage(); + await resolveTestUnit(''' +import 'package:flutter/material.dart'; +main() { + new Center( + child: new /*caret*/Row( + children: [ + new Text('aaa'), + new Text('bbb'), + ], + ), + ); +} +'''); + await assertNoAssist(); + } + + test_childrenOneIntoChild() async { + addFlutterPackage(); + await resolveTestUnit(''' +import 'package:flutter/material.dart'; +main() { + new Center( + child: /*caret*/new Column( + children: [ + new Text('foo'), + ], + ), + ); +} +'''); + await assertHasAssist(''' +import 'package:flutter/material.dart'; +main() { + new Center( + child: /*caret*/new Text('foo'), + ); +} +'''); + } + + test_childrenOneIntoReturn() async { + addFlutterPackage(); + await resolveTestUnit(''' +import 'package:flutter/material.dart'; +main() { + return /*caret*/new Column( + children: [ + new Text('foo'), + ], + ); +} +'''); + await assertHasAssist(''' +import 'package:flutter/material.dart'; +main() { + return /*caret*/new Text('foo'); +} +'''); + } + + test_intoChildren() async { + addFlutterPackage(); + await resolveTestUnit(''' +import 'package:flutter/material.dart'; +main() { + new Column( + children: <Widget>[ + new Text('aaa'), + new /*caret*/Column( + children: [ + new Row( + children: [ + new Text('bbb'), + new Text('ccc'), + ], + ), + new Row( + children: [ + new Text('ddd'), + new Text('eee'), + ], + ), + ], + ), + new Text('fff'), + ], + ); +} +'''); + await assertHasAssist(''' +import 'package:flutter/material.dart'; +main() { + new Column( + children: <Widget>[ + new Text('aaa'), + new Row( + children: [ + new Text('bbb'), + new Text('ccc'), + ], + ), + new Row( + children: [ + new Text('ddd'), + new Text('eee'), + ], + ), + new Text('fff'), + ], + ); +} +'''); + } +}
diff --git a/pkg/analysis_server/test/src/services/correction/assist/flutter_swap_with_child_test.dart b/pkg/analysis_server/test/src/services/correction/assist/flutter_swap_with_child_test.dart new file mode 100644 index 0000000..03b6f84 --- /dev/null +++ b/pkg/analysis_server/test/src/services/correction/assist/flutter_swap_with_child_test.dart
@@ -0,0 +1,112 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:analysis_server/src/services/correction/assist.dart'; +import 'package:analyzer_plugin/utilities/assist/assist.dart'; +import 'package:test_reflective_loader/test_reflective_loader.dart'; + +import 'assist_processor.dart'; + +main() { + defineReflectiveSuite(() { + defineReflectiveTests(FlutterSwapWithChildTest); + }); +} + +@reflectiveTest +class FlutterSwapWithChildTest extends AssistProcessorTest { + @override + AssistKind get kind => DartAssistKind.FLUTTER_SWAP_WITH_CHILD; + + test_aroundCenter() async { + addFlutterPackage(); + await resolveTestUnit(''' +import 'package:flutter/material.dart'; +build() { + return new Scaffold( + body: new /*caret*/GestureDetector( + onTap: () => startResize(), + child: new Center( + child: new Container( + width: 200.0, + height: 300.0, + ), + key: null, + ), + ), + ); +} +startResize() {} +'''); + await assertHasAssist(''' +import 'package:flutter/material.dart'; +build() { + return new Scaffold( + body: new Center( + key: null, + child: new /*caret*/GestureDetector( + onTap: () => startResize(), + child: new Container( + width: 200.0, + height: 300.0, + ), + ), + ), + ); +} +startResize() {} +'''); + } + + test_notFormatted() async { + addFlutterPackage(); + await resolveTestUnit(''' +import 'package:flutter/material.dart'; + +class Foo extends StatefulWidget { + @override + _State createState() => new _State(); +} + +class _State extends State<Foo> { + @override + Widget build(BuildContext context) { + return new /*caret*/Expanded( + flex: 2, + child: new GestureDetector( + child: new Text( + 'foo', + ), onTap: () { + print(42); + }, + ), + ); + } +}'''); + await assertHasAssist(''' +import 'package:flutter/material.dart'; + +class Foo extends StatefulWidget { + @override + _State createState() => new _State(); +} + +class _State extends State<Foo> { + @override + Widget build(BuildContext context) { + return new GestureDetector( + onTap: () { + print(42); + }, + child: new /*caret*/Expanded( + flex: 2, + child: new Text( + 'foo', + ), + ), + ); + } +}'''); + } +}
diff --git a/pkg/analysis_server/test/src/services/correction/assist/flutter_swap_with_parent_test.dart b/pkg/analysis_server/test/src/services/correction/assist/flutter_swap_with_parent_test.dart new file mode 100644 index 0000000..d5ad1d3 --- /dev/null +++ b/pkg/analysis_server/test/src/services/correction/assist/flutter_swap_with_parent_test.dart
@@ -0,0 +1,160 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:analysis_server/src/services/correction/assist.dart'; +import 'package:analyzer_plugin/utilities/assist/assist.dart'; +import 'package:test_reflective_loader/test_reflective_loader.dart'; + +import 'assist_processor.dart'; + +main() { + defineReflectiveSuite(() { + defineReflectiveTests(FlutterSwapWithParentTest); + }); +} + +@reflectiveTest +class FlutterSwapWithParentTest extends AssistProcessorTest { + @override + AssistKind get kind => DartAssistKind.FLUTTER_SWAP_WITH_PARENT; + + test_inCenter() async { + addFlutterPackage(); + await resolveTestUnit(''' +import 'package:flutter/material.dart'; +build() { + return new Scaffold( + body: new Center( + child: new /*caret*/GestureDetector( + onTap: () => startResize(), + child: new Container( + width: 200.0, + height: 300.0, + ), + ), + key: null, + ), + ); +} +startResize() {} +'''); + await assertHasAssist(''' +import 'package:flutter/material.dart'; +build() { + return new Scaffold( + body: new /*caret*/GestureDetector( + onTap: () => startResize(), + child: new Center( + key: null, + child: new Container( + width: 200.0, + height: 300.0, + ), + ), + ), + ); +} +startResize() {} +'''); + } + + test_notFormatted() async { + addFlutterPackage(); + await resolveTestUnit(''' +import 'package:flutter/material.dart'; + +class Foo extends StatefulWidget { + @override + _State createState() => new _State(); +} + +class _State extends State<Foo> { + @override + Widget build(BuildContext context) { + return new GestureDetector( + child: new /*caret*/Expanded( + child: new Text( + 'foo', + ), + flex: 2, + ), onTap: () { + print(42); + }, + ); + } +}'''); + await assertHasAssist(''' +import 'package:flutter/material.dart'; + +class Foo extends StatefulWidget { + @override + _State createState() => new _State(); +} + +class _State extends State<Foo> { + @override + Widget build(BuildContext context) { + return new /*caret*/Expanded( + flex: 2, + child: new GestureDetector( + onTap: () { + print(42); + }, + child: new Text( + 'foo', + ), + ), + ); + } +}'''); + } + + test_outerIsInChildren() async { + addFlutterPackage(); + await resolveTestUnit(''' +import 'package:flutter/material.dart'; +main() { + new Column( + children: [ + new Column( + children: [ + new Padding( + padding: new EdgeInsets.all(16.0), + child: new /*caret*/Center( + child: new Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: <Widget>[], + ), + ), + ), + ], + ), + ], + ); +} +'''); + await assertHasAssist(''' +import 'package:flutter/material.dart'; +main() { + new Column( + children: [ + new Column( + children: [ + new /*caret*/Center( + child: new Padding( + padding: new EdgeInsets.all(16.0), + child: new Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: <Widget>[], + ), + ), + ), + ], + ), + ], + ); +} +'''); + } +}
diff --git a/pkg/analysis_server/test/src/services/correction/assist/flutter_wrap_center_test.dart b/pkg/analysis_server/test/src/services/correction/assist/flutter_wrap_center_test.dart new file mode 100644 index 0000000..4e300e2 --- /dev/null +++ b/pkg/analysis_server/test/src/services/correction/assist/flutter_wrap_center_test.dart
@@ -0,0 +1,84 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:analysis_server/src/services/correction/assist.dart'; +import 'package:analyzer_plugin/utilities/assist/assist.dart'; +import 'package:test_reflective_loader/test_reflective_loader.dart'; + +import 'assist_processor.dart'; + +main() { + defineReflectiveSuite(() { + defineReflectiveTests(FlutterWrapCenterTest); + }); +} + +@reflectiveTest +class FlutterWrapCenterTest extends AssistProcessorTest { + @override + AssistKind get kind => DartAssistKind.FLUTTER_WRAP_CENTER; + + test_aroundCenter() async { + addFlutterPackage(); + await resolveTestUnit(''' +import 'package:flutter/widgets.dart'; +class FakeFlutter { + main() { + return /*caret*/new Center(); + } +} +'''); + await assertNoAssist(); + } + + test_aroundContainer() async { + addFlutterPackage(); + await resolveTestUnit(''' +import 'package:flutter/widgets.dart'; +class FakeFlutter { + main() { + return /*caret*/new Container(); + } +} +'''); + await assertHasAssist(''' +import 'package:flutter/widgets.dart'; +class FakeFlutter { + main() { + return /*caret*/Center(child: new Container()); + } +} +'''); + } + + test_aroundNamedConstructor() async { + addFlutterPackage(); + await resolveTestUnit(''' +import 'package:flutter/widgets.dart'; + +class MyWidget extends StatelessWidget { + MyWidget.named(); + + Widget build(BuildContext context) => null; +} + +main() { + return MyWidget./*caret*/named(); +} +'''); + await assertHasAssist(''' +import 'package:flutter/widgets.dart'; + +class MyWidget extends StatelessWidget { + MyWidget.named(); + + Widget build(BuildContext context) => null; +} + +main() { + return Center(child: MyWidget./*caret*/named()); +} +'''); + } +}
diff --git a/pkg/analysis_server/test/src/services/correction/assist/flutter_wrap_column_test.dart b/pkg/analysis_server/test/src/services/correction/assist/flutter_wrap_column_test.dart new file mode 100644 index 0000000..cad4036 --- /dev/null +++ b/pkg/analysis_server/test/src/services/correction/assist/flutter_wrap_column_test.dart
@@ -0,0 +1,91 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:analysis_server/src/services/correction/assist.dart'; +import 'package:analyzer_plugin/utilities/assist/assist.dart'; +import 'package:test_reflective_loader/test_reflective_loader.dart'; + +import 'assist_processor.dart'; + +main() { + defineReflectiveSuite(() { + defineReflectiveTests(FlutterWrapColumnTest); + }); +} + +@reflectiveTest +class FlutterWrapColumnTest extends AssistProcessorTest { + @override + AssistKind get kind => DartAssistKind.FLUTTER_WRAP_COLUMN; + + test_coveredByWidget() async { + addFlutterPackage(); + await resolveTestUnit(''' +import 'package:flutter/widgets.dart'; + +class FakeFlutter { + main() { + return new Container( + child: new /*caret*/Text('aaa'), + ); + } +} +'''); + await assertHasAssist(''' +import 'package:flutter/widgets.dart'; + +class FakeFlutter { + main() { + return new Container( + child: Column( + children: <Widget>[ + new /*caret*/Text('aaa'), + ], + ), + ); + } +} +'''); + } + + test_coversWidgets() async { + addFlutterPackage(); + await resolveTestUnit(''' +import 'package:flutter/widgets.dart'; + +class FakeFlutter { + main() { + return new Row(children: [ + new Text('aaa'), +// start + new Text('bbb'), + new Text('ccc'), +// end + new Text('ddd'), + ]); + } +} +'''); + await assertHasAssist(''' +import 'package:flutter/widgets.dart'; + +class FakeFlutter { + main() { + return new Row(children: [ + new Text('aaa'), +// start + Column( + children: <Widget>[ + new Text('bbb'), + new Text('ccc'), + ], + ), +// end + new Text('ddd'), + ]); + } +} +'''); + } +}
diff --git a/pkg/analysis_server/test/src/services/correction/assist/flutter_wrap_container_test.dart b/pkg/analysis_server/test/src/services/correction/assist/flutter_wrap_container_test.dart new file mode 100644 index 0000000..15f8433 --- /dev/null +++ b/pkg/analysis_server/test/src/services/correction/assist/flutter_wrap_container_test.dart
@@ -0,0 +1,48 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:analysis_server/src/services/correction/assist.dart'; +import 'package:analyzer_plugin/utilities/assist/assist.dart'; +import 'package:test_reflective_loader/test_reflective_loader.dart'; + +import 'assist_processor.dart'; + +main() { + defineReflectiveSuite(() { + defineReflectiveTests(FlutterWrapContainerTest); + }); +} + +@reflectiveTest +class FlutterWrapContainerTest extends AssistProcessorTest { + @override + AssistKind get kind => DartAssistKind.FLUTTER_WRAP_CONTAINER; + + test_aroundContainer() async { + addFlutterPackage(); + await resolveTestUnit(''' +import 'package:flutter/widgets.dart'; +main() { + return /*caret*/new Container(); +} +'''); + await assertNoAssist(); + } + + test_aroundText() async { + addFlutterPackage(); + await resolveTestUnit(''' +import 'package:flutter/widgets.dart'; +main() { + /*caret*/new Text('a'); +} +'''); + await assertHasAssist(''' +import 'package:flutter/widgets.dart'; +main() { + /*caret*/Container(child: new Text('a')); +} +'''); + } +}
diff --git a/pkg/analysis_server/test/src/services/correction/assist/flutter_wrap_generic_test.dart b/pkg/analysis_server/test/src/services/correction/assist/flutter_wrap_generic_test.dart new file mode 100644 index 0000000..30b416b --- /dev/null +++ b/pkg/analysis_server/test/src/services/correction/assist/flutter_wrap_generic_test.dart
@@ -0,0 +1,313 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:analysis_server/src/services/correction/assist.dart'; +import 'package:analyzer_plugin/utilities/assist/assist.dart'; +import 'package:test_reflective_loader/test_reflective_loader.dart'; + +import 'assist_processor.dart'; + +main() { + defineReflectiveSuite(() { + defineReflectiveTests(FlutterWrapGenericTest); + }); +} + +@reflectiveTest +class FlutterWrapGenericTest extends AssistProcessorTest { + @override + AssistKind get kind => DartAssistKind.FLUTTER_WRAP_GENERIC; + + test_minimal() async { + addFlutterPackage(); + await resolveTestUnit(''' +/*caret*/x(){} +'''); + await assertNoAssist(); + } + + test_multiLine() async { + addFlutterPackage(); + await resolveTestUnit(''' +import 'package:flutter/widgets.dart'; +build() { + return new Container( + child: new Row( +// start + children: [/*caret*/ + new Text('111'), + new Text('222'), + new Container(), + ], +// end + ), + ); +} +'''); + await assertHasAssist(''' +import 'package:flutter/widgets.dart'; +build() { + return new Container( + child: new Row( +// start + children: [ + new widget( + children: [/*caret*/ + new Text('111'), + new Text('222'), + new Container(), + ], + ), + ], +// end + ), + ); +} +'''); + } + + test_multiLine_inListLiteral() async { + verifyNoTestUnitErrors = false; + addFlutterPackage(); + await resolveTestUnit(''' +import 'package:flutter/widgets.dart'; +build() { + return new Container( + child: new Row( + children: [/*caret*/ +// start + new Transform(), + new Object(), + new AspectRatio(), +// end + ], + ), + ); +} +'''); + await assertNoAssist(); + } + + test_multiLines() async { + addFlutterPackage(); + await resolveTestUnit(''' +import 'package:flutter/widgets.dart'; +class FakeFlutter { + main() { + return new Container( +// start + child: new /*caret*/DefaultTextStyle( + child: new Row( + children: <Widget>[ + new Container( + ), + ], + ), + ), +// end + ); + } +} +'''); + await assertHasAssist(''' +import 'package:flutter/widgets.dart'; +class FakeFlutter { + main() { + return new Container( +// start + child: widget( + child: new /*caret*/DefaultTextStyle( + child: new Row( + children: <Widget>[ + new Container( + ), + ], + ), + ), + ), +// end + ); + } +} +'''); + } + + test_multiLines_eol2() async { + addFlutterPackage(); + await resolveTestUnit(''' +import 'package:flutter/widgets.dart'; +class FakeFlutter {\r + main() {\r + return new Container(\r +// start\r + child: new /*caret*/DefaultTextStyle(\r + child: new Row(\r + children: <Widget>[\r + new Container(\r + ),\r + ],\r + ),\r + ),\r +// end\r + );\r + }\r +}\r +'''); + await assertHasAssist(''' +import 'package:flutter/widgets.dart'; +class FakeFlutter {\r + main() {\r + return new Container(\r +// start\r + child: widget(\r + child: new /*caret*/DefaultTextStyle(\r + child: new Row(\r + children: <Widget>[\r + new Container(\r + ),\r + ],\r + ),\r + ),\r + ),\r +// end\r + );\r + }\r +}\r +'''); + } + + test_prefixedIdentifier_identifier() async { + addFlutterPackage(); + await resolveTestUnit(''' +import 'package:flutter/widgets.dart'; + +abstract class Foo extends Widget { + Widget bar; +} + +main(Foo foo) { + return foo./*caret*/bar; +} +'''); + await assertHasAssist(''' +import 'package:flutter/widgets.dart'; + +abstract class Foo extends Widget { + Widget bar; +} + +main(Foo foo) { + return widget(child: foo./*caret*/bar); +} +'''); + } + + test_prefixedIdentifier_prefix() async { + addFlutterPackage(); + await resolveTestUnit(''' +import 'package:flutter/widgets.dart'; + +abstract class Foo extends Widget { + Widget bar; +} + +main(Foo foo) { + return /*caret*/foo.bar; +} +'''); + await assertHasAssist(''' +import 'package:flutter/widgets.dart'; + +abstract class Foo extends Widget { + Widget bar; +} + +main(Foo foo) { + return /*caret*/widget(child: foo.bar); +} +'''); + } + + test_singleLine() async { + addFlutterPackage(); + await resolveTestUnit(''' +import 'package:flutter/widgets.dart'; +class FakeFlutter { + main() { + var obj; +// start + return new Row(children: [/*caret*/ new Container()]); +// end + } +} +'''); + await assertNoAssist(); + } + + test_singleLine1() async { + addFlutterPackage(); + await resolveTestUnit(''' +import 'package:flutter/widgets.dart'; +class FakeFlutter { + main() { +// start + return /*caret*/new Container(); +// end + } +} +'''); + await assertHasAssist(''' +import 'package:flutter/widgets.dart'; +class FakeFlutter { + main() { +// start + return /*caret*/widget(child: new Container()); +// end + } +} +'''); + } + + test_singleLine2() async { + addFlutterPackage(); + await resolveTestUnit(''' +import 'package:flutter/widgets.dart'; +class FakeFlutter { + main() { + return new ClipRect./*caret*/rect(); + } +} +'''); + await assertHasAssist(''' +import 'package:flutter/widgets.dart'; +class FakeFlutter { + main() { + return widget(child: new ClipRect./*caret*/rect()); + } +} +'''); + } + + test_variable() async { + addFlutterPackage(); + await resolveTestUnit(''' +import 'package:flutter/widgets.dart'; +class FakeFlutter { + main() { + var container = new Container(); + return /*caret*/container; + } +} +'''); + await assertHasAssist(''' +import 'package:flutter/widgets.dart'; +class FakeFlutter { + main() { + var container = new Container(); + return /*caret*/widget(child: container); + } +} +'''); + } +}
diff --git a/pkg/analysis_server/test/src/services/correction/assist/flutter_wrap_padding_test.dart b/pkg/analysis_server/test/src/services/correction/assist/flutter_wrap_padding_test.dart new file mode 100644 index 0000000..50b927b --- /dev/null +++ b/pkg/analysis_server/test/src/services/correction/assist/flutter_wrap_padding_test.dart
@@ -0,0 +1,57 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:analysis_server/src/services/correction/assist.dart'; +import 'package:analyzer_plugin/utilities/assist/assist.dart'; +import 'package:test_reflective_loader/test_reflective_loader.dart'; + +import 'assist_processor.dart'; + +main() { + defineReflectiveSuite(() { + defineReflectiveTests(FlutterWrapPaddingTest); + }); +} + +@reflectiveTest +class FlutterWrapPaddingTest extends AssistProcessorTest { + @override + AssistKind get kind => DartAssistKind.FLUTTER_WRAP_PADDING; + + test_aroundContainer() async { + addFlutterPackage(); + await resolveTestUnit(''' +import 'package:flutter/widgets.dart'; +class FakeFlutter { + main() { + return /*caret*/new Container(); + } +} +'''); + await assertHasAssist(''' +import 'package:flutter/widgets.dart'; +class FakeFlutter { + main() { + return /*caret*/Padding( + padding: const EdgeInsets.all(8.0), + child: new Container(), + ); + } +} +'''); + } + + test_aroundPadding() async { + addFlutterPackage(); + await resolveTestUnit(''' +import 'package:flutter/widgets.dart'; +class FakeFlutter { + main() { + return /*caret*/new Padding(); + } +} +'''); + await assertNoAssist(); + } +}
diff --git a/pkg/analysis_server/test/src/services/correction/assist/flutter_wrap_row_test.dart b/pkg/analysis_server/test/src/services/correction/assist/flutter_wrap_row_test.dart new file mode 100644 index 0000000..c18ac34 --- /dev/null +++ b/pkg/analysis_server/test/src/services/correction/assist/flutter_wrap_row_test.dart
@@ -0,0 +1,61 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:analysis_server/src/services/correction/assist.dart'; +import 'package:analyzer_plugin/utilities/assist/assist.dart'; +import 'package:test_reflective_loader/test_reflective_loader.dart'; + +import 'assist_processor.dart'; + +main() { + defineReflectiveSuite(() { + defineReflectiveTests(FlutterWrapRowTest); + }); +} + +@reflectiveTest +class FlutterWrapRowTest extends AssistProcessorTest { + @override + AssistKind get kind => DartAssistKind.FLUTTER_WRAP_ROW; + + test_twoWidgets() async { + addFlutterPackage(); + await resolveTestUnit(''' +import 'package:flutter/widgets.dart'; + +class FakeFlutter { + main() { + return new Column(children: [ + new Text('aaa'), +// start + new Text('bbb'), + new Text('ccc'), +// end + new Text('ddd'), + ]); + } +} +'''); + await assertHasAssist(''' +import 'package:flutter/widgets.dart'; + +class FakeFlutter { + main() { + return new Column(children: [ + new Text('aaa'), +// start + Row( + children: <Widget>[ + new Text('bbb'), + new Text('ccc'), + ], + ), +// end + new Text('ddd'), + ]); + } +} +'''); + } +}
diff --git a/pkg/analysis_server/test/src/services/correction/assist/flutter_wrap_stream_builder_test.dart b/pkg/analysis_server/test/src/services/correction/assist/flutter_wrap_stream_builder_test.dart new file mode 100644 index 0000000..be7d5c2 --- /dev/null +++ b/pkg/analysis_server/test/src/services/correction/assist/flutter_wrap_stream_builder_test.dart
@@ -0,0 +1,59 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:analysis_server/src/services/correction/assist.dart'; +import 'package:analyzer_plugin/utilities/assist/assist.dart'; +import 'package:test_reflective_loader/test_reflective_loader.dart'; + +import 'assist_processor.dart'; + +main() { + defineReflectiveSuite(() { + defineReflectiveTests(FlutterWrapStreamBuilderTest); + }); +} + +@reflectiveTest +class FlutterWrapStreamBuilderTest extends AssistProcessorTest { + @override + AssistKind get kind => DartAssistKind.FLUTTER_WRAP_STREAM_BUILDER; + + test_aroundStreamBuilder() async { + addFlutterPackage(); + await resolveTestUnit(''' +import 'package:flutter/widgets.dart'; + +main() { + /*caret*/StreamBuilder( + stream: null, + builder: (context, snapshot) => null, + ); +} +'''); + await assertNoAssist(); + } + + test_aroundText() async { + addFlutterPackage(); + await resolveTestUnit(''' +import 'package:flutter/widgets.dart'; + +main() { + /*caret*/new Text('a'); +} +'''); + await assertHasAssist(''' +import 'package:flutter/widgets.dart'; + +main() { + /*caret*/StreamBuilder<Object>( + stream: null, + builder: (context, snapshot) { + return new Text('a'); + } + ); +} +'''); + } +}
diff --git a/pkg/analysis_server/test/src/services/correction/assist/import_add_show_test.dart b/pkg/analysis_server/test/src/services/correction/assist/import_add_show_test.dart new file mode 100644 index 0000000..4c62dde --- /dev/null +++ b/pkg/analysis_server/test/src/services/correction/assist/import_add_show_test.dart
@@ -0,0 +1,101 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:analysis_server/src/services/correction/assist.dart'; +import 'package:analyzer_plugin/utilities/assist/assist.dart'; +import 'package:test_reflective_loader/test_reflective_loader.dart'; + +import 'assist_processor.dart'; + +main() { + defineReflectiveSuite(() { + defineReflectiveTests(ImportAddShowTest); + }); +} + +@reflectiveTest +class ImportAddShowTest extends AssistProcessorTest { + @override + AssistKind get kind => DartAssistKind.IMPORT_ADD_SHOW; + + test_hasShow() async { + await resolveTestUnit(''' +import 'dart:math' show PI; +main() { + PI; +} +'''); + await assertNoAssistAt('import '); + } + + test_hasUnresolvedIdentifier() async { + await resolveTestUnit(''' +import 'dart:math'; +main(x) { + PI; + return x.foo(); +} +'''); + await assertHasAssistAt('import ', ''' +import 'dart:math' show PI; +main(x) { + PI; + return x.foo(); +} +'''); + } + + test_onDirective() async { + await resolveTestUnit(''' +import 'dart:math'; +main() { + PI; + E; + max(1, 2); +} +'''); + await assertHasAssistAt('import ', ''' +import 'dart:math' show E, PI, max; +main() { + PI; + E; + max(1, 2); +} +'''); + } + + test_onUri() async { + await resolveTestUnit(''' +import 'dart:math'; +main() { + PI; + E; + max(1, 2); +} +'''); + await assertHasAssistAt('art:math', ''' +import 'dart:math' show E, PI, max; +main() { + PI; + E; + max(1, 2); +} +'''); + } + + test_unresolvedUri() async { + verifyNoTestUnitErrors = false; + await resolveTestUnit(''' +import '/no/such/lib.dart'; +'''); + await assertNoAssistAt('import '); + } + + test_unused() async { + await resolveTestUnit(''' +import 'dart:math'; +'''); + await assertNoAssistAt('import '); + } +}
diff --git a/pkg/analysis_server/test/src/services/correction/assist/introduce_local_cast_type_test.dart b/pkg/analysis_server/test/src/services/correction/assist/introduce_local_cast_type_test.dart new file mode 100644 index 0000000..2201266 --- /dev/null +++ b/pkg/analysis_server/test/src/services/correction/assist/introduce_local_cast_type_test.dart
@@ -0,0 +1,127 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:analysis_server/src/services/correction/assist.dart'; +import 'package:analyzer_plugin/protocol/protocol_common.dart'; +import 'package:analyzer_plugin/utilities/assist/assist.dart'; +import 'package:test_reflective_loader/test_reflective_loader.dart'; + +import 'assist_processor.dart'; + +main() { + defineReflectiveSuite(() { + defineReflectiveTests(IntroduceLocalCastTypeTest); + }); +} + +@reflectiveTest +class IntroduceLocalCastTypeTest extends AssistProcessorTest { + @override + AssistKind get kind => DartAssistKind.INTRODUCE_LOCAL_CAST_TYPE; + + test_introduceLocalTestedType_notBlock() async { + await resolveTestUnit(''' +main(p) { + if (p is String) + print('not a block'); +} +'''); + await assertNoAssistAt('if (p'); + } + + test_introduceLocalTestedType_notIsExpression() async { + await resolveTestUnit(''' +main(p) { + if (p == null) { + } +} +'''); + await assertNoAssistAt('if (p'); + } + + test_introduceLocalTestedType_notStatement() async { + await resolveTestUnit(''' +class C { + bool b; + C(v) : b = v is int; +}'''); + await assertNoAssistAt('is int'); + } + + test_introduceLocalTestedType_if_is() async { + await resolveTestUnit(''' +class MyTypeName {} +main(p) { + if (p is MyTypeName) { + } + p = null; +} +'''); + String expected = ''' +class MyTypeName {} +main(p) { + if (p is MyTypeName) { + MyTypeName myTypeName = p; + } + p = null; +} +'''; + await assertHasAssistAt('is MyType', expected); + assertLinkedGroup( + 0, + ['myTypeName = '], + expectedSuggestions(LinkedEditSuggestionKind.VARIABLE, + ['myTypeName', 'typeName', 'name'])); + // another good location + await assertHasAssistAt('if (p', expected); + } + + test_introduceLocalTestedType_if_isNot() async { + await resolveTestUnit(''' +class MyTypeName {} +main(p) { + if (p is! MyTypeName) { + return; + } +} +'''); + String expected = ''' +class MyTypeName {} +main(p) { + if (p is! MyTypeName) { + return; + } + MyTypeName myTypeName = p; +} +'''; + await assertHasAssistAt('is! MyType', expected); + assertLinkedGroup( + 0, + ['myTypeName = '], + expectedSuggestions(LinkedEditSuggestionKind.VARIABLE, + ['myTypeName', 'typeName', 'name'])); + // another good location + await assertHasAssistAt('if (p', expected); + } + + test_introduceLocalTestedType_while() async { + await resolveTestUnit(''' +main(p) { + while (p is String) { + } + p = null; +} +'''); + String expected = ''' +main(p) { + while (p is String) { + String s = p; + } + p = null; +} +'''; + await assertHasAssistAt('is String', expected); + await assertHasAssistAt('while (p', expected); + } +}
diff --git a/pkg/analysis_server/test/src/services/correction/assist/invert_if_statement_test.dart b/pkg/analysis_server/test/src/services/correction/assist/invert_if_statement_test.dart new file mode 100644 index 0000000..54ba0aa --- /dev/null +++ b/pkg/analysis_server/test/src/services/correction/assist/invert_if_statement_test.dart
@@ -0,0 +1,61 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:analysis_server/src/services/correction/assist.dart'; +import 'package:analyzer_plugin/utilities/assist/assist.dart'; +import 'package:test_reflective_loader/test_reflective_loader.dart'; + +import 'assist_processor.dart'; + +main() { + defineReflectiveSuite(() { + defineReflectiveTests(InvertIfStatementTest); + }); +} + +@reflectiveTest +class InvertIfStatementTest extends AssistProcessorTest { + @override + AssistKind get kind => DartAssistKind.INVERT_IF_STATEMENT; + + test_blocks() async { + await resolveTestUnit(''' +main() { + if (true) { + 0; + } else { + 1; + } +} +'''); + await assertHasAssistAt('if (', ''' +main() { + if (false) { + 1; + } else { + 0; + } +} +'''); + } + + test_statements() async { + await resolveTestUnit(''' +main() { + if (true) + 0; + else + 1; +} +'''); + await assertHasAssistAt('if (', ''' +main() { + if (false) + 1; + else + 0; +} +'''); + } +}
diff --git a/pkg/analysis_server/test/src/services/correction/assist/join_if_with_inner_test.dart b/pkg/analysis_server/test/src/services/correction/assist/join_if_with_inner_test.dart new file mode 100644 index 0000000..a57c603 --- /dev/null +++ b/pkg/analysis_server/test/src/services/correction/assist/join_if_with_inner_test.dart
@@ -0,0 +1,255 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:analysis_server/src/services/correction/assist.dart'; +import 'package:analyzer_plugin/utilities/assist/assist.dart'; +import 'package:test_reflective_loader/test_reflective_loader.dart'; + +import 'assist_processor.dart'; + +main() { + defineReflectiveSuite(() { + defineReflectiveTests(JoinInWithInnerTest); + }); +} + +@reflectiveTest +class JoinInWithInnerTest extends AssistProcessorTest { + @override + AssistKind get kind => DartAssistKind.JOIN_IF_WITH_INNER; + + test_conditionAndOr() async { + await resolveTestUnit(''' +main() { + if (1 == 1) { + if (2 == 2 || 3 == 3) { + print(0); + } + } +} +'''); + await assertHasAssistAt('if (1 ==', ''' +main() { + if (1 == 1 && (2 == 2 || 3 == 3)) { + print(0); + } +} +'''); + } + + test_conditionInvocation() async { + await resolveTestUnit(''' +main() { + if (isCheck()) { + if (2 == 2) { + print(0); + } + } +} +bool isCheck() => false; +'''); + await assertHasAssistAt('if (isCheck', ''' +main() { + if (isCheck() && 2 == 2) { + print(0); + } +} +bool isCheck() => false; +'''); + } + + test_conditionOrAnd() async { + await resolveTestUnit(''' +main() { + if (1 == 1 || 2 == 2) { + if (3 == 3) { + print(0); + } + } +} +'''); + await assertHasAssistAt('if (1 ==', ''' +main() { + if ((1 == 1 || 2 == 2) && 3 == 3) { + print(0); + } +} +'''); + } + + test_innerNotIf() async { + await resolveTestUnit(''' +main() { + if (1 == 1) { + print(0); + } +} +'''); + await assertNoAssistAt('if (1 =='); + } + + test_innerWithElse() async { + await resolveTestUnit(''' +main() { + if (1 == 1) { + if (2 == 2) { + print(0); + } else { + print(1); + } + } +} +'''); + await assertNoAssistAt('if (1 =='); + } + + test_onCondition() async { + await resolveTestUnit(''' +main() { + if (1 == 1) { + if (2 == 2) { + print(0); + } + } +} +'''); + await assertHasAssistAt('1 ==', ''' +main() { + if (1 == 1 && 2 == 2) { + print(0); + } +} +'''); + } + + test_simpleConditions_block_block() async { + await resolveTestUnit(''' +main() { + if (1 == 1) { + if (2 == 2) { + print(0); + } + } +} +'''); + await assertHasAssistAt('if (1 ==', ''' +main() { + if (1 == 1 && 2 == 2) { + print(0); + } +} +'''); + } + + test_simpleConditions_block_single() async { + await resolveTestUnit(''' +main() { + if (1 == 1) { + if (2 == 2) + print(0); + } +} +'''); + await assertHasAssistAt('if (1 ==', ''' +main() { + if (1 == 1 && 2 == 2) { + print(0); + } +} +'''); + } + + test_simpleConditions_single_blockMulti() async { + await resolveTestUnit(''' +main() { + if (1 == 1) { + if (2 == 2) { + print(1); + print(2); + print(3); + } + } +} +'''); + await assertHasAssistAt('if (1 ==', ''' +main() { + if (1 == 1 && 2 == 2) { + print(1); + print(2); + print(3); + } +} +'''); + } + + test_simpleConditions_single_blockOne() async { + await resolveTestUnit(''' +main() { + if (1 == 1) + if (2 == 2) { + print(0); + } +} +'''); + await assertHasAssistAt('if (1 ==', ''' +main() { + if (1 == 1 && 2 == 2) { + print(0); + } +} +'''); + } + + test_statementAfterInner() async { + await resolveTestUnit(''' +main() { + if (1 == 1) { + if (2 == 2) { + print(2); + } + print(1); + } +} +'''); + await assertNoAssistAt('if (1 =='); + } + + test_statementBeforeInner() async { + await resolveTestUnit(''' +main() { + if (1 == 1) { + print(1); + if (2 == 2) { + print(2); + } + } +} +'''); + await assertNoAssistAt('if (1 =='); + } + + test_targetNotIf() async { + await resolveTestUnit(''' +main() { + print(0); +} +'''); + await assertNoAssistAt('print'); + } + + test_targetWithElse() async { + await resolveTestUnit(''' +main() { + if (1 == 1) { + if (2 == 2) { + print(0); + } + } else { + print(1); + } +} +'''); + await assertNoAssistAt('if (1 =='); + } +}
diff --git a/pkg/analysis_server/test/src/services/correction/assist/join_if_with_outer_test.dart b/pkg/analysis_server/test/src/services/correction/assist/join_if_with_outer_test.dart new file mode 100644 index 0000000..ffbd3ab --- /dev/null +++ b/pkg/analysis_server/test/src/services/correction/assist/join_if_with_outer_test.dart
@@ -0,0 +1,255 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:analysis_server/src/services/correction/assist.dart'; +import 'package:analyzer_plugin/utilities/assist/assist.dart'; +import 'package:test_reflective_loader/test_reflective_loader.dart'; + +import 'assist_processor.dart'; + +main() { + defineReflectiveSuite(() { + defineReflectiveTests(JoinIfWithOuterTest); + }); +} + +@reflectiveTest +class JoinIfWithOuterTest extends AssistProcessorTest { + @override + AssistKind get kind => DartAssistKind.JOIN_IF_WITH_OUTER; + + test_conditionAndOr() async { + await resolveTestUnit(''' +main() { + if (1 == 1) { + if (2 == 2 || 3 == 3) { + print(0); + } + } +} +'''); + await assertHasAssistAt('if (2 ==', ''' +main() { + if (1 == 1 && (2 == 2 || 3 == 3)) { + print(0); + } +} +'''); + } + + test_conditionInvocation() async { + await resolveTestUnit(''' +main() { + if (1 == 1) { + if (isCheck()) { + print(0); + } + } +} +bool isCheck() => false; +'''); + await assertHasAssistAt('if (isCheck', ''' +main() { + if (1 == 1 && isCheck()) { + print(0); + } +} +bool isCheck() => false; +'''); + } + + test_conditionOrAnd() async { + await resolveTestUnit(''' +main() { + if (1 == 1 || 2 == 2) { + if (3 == 3) { + print(0); + } + } +} +'''); + await assertHasAssistAt('if (3 == 3', ''' +main() { + if ((1 == 1 || 2 == 2) && 3 == 3) { + print(0); + } +} +'''); + } + + test_onCondition() async { + await resolveTestUnit(''' +main() { + if (1 == 1) { + if (2 == 2) { + print(0); + } + } +} +'''); + await assertHasAssistAt('if (2 == 2', ''' +main() { + if (1 == 1 && 2 == 2) { + print(0); + } +} +'''); + } + + test_outerNotIf() async { + await resolveTestUnit(''' +main() { + if (1 == 1) { + print(0); + } +} +'''); + await assertNoAssistAt('if (1 == 1'); + } + + test_outerWithElse() async { + await resolveTestUnit(''' +main() { + if (1 == 1) { + if (2 == 2) { + print(0); + } + } else { + print(1); + } +} +'''); + await assertNoAssistAt('if (2 == 2'); + } + + test_simpleConditions_block_block() async { + await resolveTestUnit(''' +main() { + if (1 == 1) { + if (2 == 2) { + print(0); + } + } +} +'''); + await assertHasAssistAt('if (2 == 2', ''' +main() { + if (1 == 1 && 2 == 2) { + print(0); + } +} +'''); + } + + test_simpleConditions_block_single() async { + await resolveTestUnit(''' +main() { + if (1 == 1) { + if (2 == 2) + print(0); + } +} +'''); + await assertHasAssistAt('if (2 == 2', ''' +main() { + if (1 == 1 && 2 == 2) { + print(0); + } +} +'''); + } + + test_simpleConditions_single_blockMulti() async { + await resolveTestUnit(''' +main() { + if (1 == 1) { + if (2 == 2) { + print(1); + print(2); + print(3); + } + } +} +'''); + await assertHasAssistAt('if (2 == 2', ''' +main() { + if (1 == 1 && 2 == 2) { + print(1); + print(2); + print(3); + } +} +'''); + } + + test_simpleConditions_single_blockOne() async { + await resolveTestUnit(''' +main() { + if (1 == 1) + if (2 == 2) { + print(0); + } +} +'''); + await assertHasAssistAt('if (2 == 2', ''' +main() { + if (1 == 1 && 2 == 2) { + print(0); + } +} +'''); + } + + test_statementAfterInner() async { + await resolveTestUnit(''' +main() { + if (1 == 1) { + if (2 == 2) { + print(2); + } + print(1); + } +} +'''); + await assertNoAssistAt('if (2 == 2'); + } + + test_statementBeforeInner() async { + await resolveTestUnit(''' +main() { + if (1 == 1) { + print(1); + if (2 == 2) { + print(2); + } + } +} +'''); + await assertNoAssistAt('if (2 == 2'); + } + + test_targetNotIf() async { + await resolveTestUnit(''' +main() { + print(0); +} +'''); + await assertNoAssistAt('print'); + } + + test_targetWithElse() async { + await resolveTestUnit(''' +main() { + if (1 == 1) { + if (2 == 2) { + print(0); + } else { + print(1); + } + } +} +'''); + await assertNoAssistAt('if (2 == 2'); + } +}
diff --git a/pkg/analysis_server/test/src/services/correction/assist/join_variable_declaration_test.dart b/pkg/analysis_server/test/src/services/correction/assist/join_variable_declaration_test.dart new file mode 100644 index 0000000..3216240 --- /dev/null +++ b/pkg/analysis_server/test/src/services/correction/assist/join_variable_declaration_test.dart
@@ -0,0 +1,220 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:analysis_server/src/services/correction/assist.dart'; +import 'package:analyzer_plugin/utilities/assist/assist.dart'; +import 'package:test_reflective_loader/test_reflective_loader.dart'; + +import 'assist_processor.dart'; + +main() { + defineReflectiveSuite(() { + defineReflectiveTests(JoinVariableDeclarationTest); + }); +} + +@reflectiveTest +class JoinVariableDeclarationTest extends AssistProcessorTest { + @override + AssistKind get kind => DartAssistKind.JOIN_VARIABLE_DECLARATION; + + test_onAssignment() async { + await resolveTestUnit(''' +main() { + var v; + v = 1; +} +'''); + await assertHasAssistAt('v =', ''' +main() { + var v = 1; +} +'''); + } + + test_onAssignment_hasInitializer() async { + await resolveTestUnit(''' +main() { + var v = 1; + v = 2; +} +'''); + await assertNoAssistAt('v = 2'); + } + + test_onAssignment_notAdjacent() async { + await resolveTestUnit(''' +main() { + var v; + var bar; + v = 1; +} +'''); + await assertNoAssistAt('v = 1'); + } + + test_onAssignment_notAssignment() async { + await resolveTestUnit(''' +main() { + var v; + v += 1; +} +'''); + await assertNoAssistAt('v += 1'); + } + + test_onAssignment_notDeclaration() async { + await resolveTestUnit(''' +main(var v) { + v = 1; +} +'''); + await assertNoAssistAt('v = 1'); + } + + test_onAssignment_notLeftArgument() async { + await resolveTestUnit(''' +main() { + var v; + 1 + v; // marker +} +'''); + await assertNoAssistAt('v; // marker'); + } + + test_onAssignment_notOneVariable() async { + await resolveTestUnit(''' +main() { + var v, v2; + v = 1; +} +'''); + await assertNoAssistAt('v = 1'); + } + + test_onAssignment_notResolved() async { + verifyNoTestUnitErrors = false; + await resolveTestUnit(''' +main() { + var v; + x = 1; +} +'''); + await assertNoAssistAt('x = 1'); + } + + test_onAssignment_notSameBlock() async { + await resolveTestUnit(''' +main() { + var v; + { + v = 1; + } +} +'''); + await assertNoAssistAt('v = 1'); + } + + test_onDeclaration_hasInitializer() async { + await resolveTestUnit(''' +main() { + var v = 1; + v = 2; +} +'''); + await assertNoAssistAt('v = 1'); + } + + test_onDeclaration_lastStatement() async { + await resolveTestUnit(''' +main() { + if (true) + var v; +} +'''); + await assertNoAssistAt('v;'); + } + + test_onDeclaration_nextNotAssignmentExpression() async { + await resolveTestUnit(''' +main() { + var v; + 42; +} +'''); + await assertNoAssistAt('v;'); + } + + test_onDeclaration_nextNotExpressionStatement() async { + await resolveTestUnit(''' +main() { + var v; + if (true) return; +} +'''); + await assertNoAssistAt('v;'); + } + + test_onDeclaration_nextNotPureAssignment() async { + await resolveTestUnit(''' +main() { + var v; + v += 1; +} +'''); + await assertNoAssistAt('v;'); + } + + test_onDeclaration_notOneVariable() async { + await resolveTestUnit(''' +main() { + var v, v2; + v = 1; +} +'''); + await assertNoAssistAt('v, '); + } + + test_onDeclaration_onName() async { + await resolveTestUnit(''' +main() { + var v; + v = 1; +} +'''); + await assertHasAssistAt('v;', ''' +main() { + var v = 1; +} +'''); + } + + test_onDeclaration_onType() async { + await resolveTestUnit(''' +main() { + int v; + v = 1; +} +'''); + await assertHasAssistAt('int v', ''' +main() { + int v = 1; +} +'''); + } + + test_onDeclaration_onVar() async { + await resolveTestUnit(''' +main() { + var v; + v = 1; +} +'''); + await assertHasAssistAt('var v', ''' +main() { + var v = 1; +} +'''); + } +}
diff --git a/pkg/analysis_server/test/src/services/correction/assist/remove_type_annotation_test.dart b/pkg/analysis_server/test/src/services/correction/assist/remove_type_annotation_test.dart new file mode 100644 index 0000000..f57eee3 --- /dev/null +++ b/pkg/analysis_server/test/src/services/correction/assist/remove_type_annotation_test.dart
@@ -0,0 +1,147 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:analysis_server/src/services/correction/assist.dart'; +import 'package:analyzer_plugin/utilities/assist/assist.dart'; +import 'package:test_reflective_loader/test_reflective_loader.dart'; + +import 'assist_processor.dart'; + +main() { + defineReflectiveSuite(() { + defineReflectiveTests(RemoveTypeAnnotationTest); + }); +} + +@reflectiveTest +class RemoveTypeAnnotationTest extends AssistProcessorTest { + @override + AssistKind get kind => DartAssistKind.REMOVE_TYPE_ANNOTATION; + + test_classField() async { + await resolveTestUnit(''' +class A { + int v = 1; +} +'''); + await assertHasAssistAt('v = ', ''' +class A { + var v = 1; +} +'''); + } + + test_classField_final() async { + await resolveTestUnit(''' +class A { + final int v = 1; +} +'''); + await assertHasAssistAt('v = ', ''' +class A { + final v = 1; +} +'''); + } + + test_field_noInitializer() async { + await resolveTestUnit(''' +class A { + int v; +} +'''); + await assertNoAssistAt('v;'); + } + + test_localVariable_noInitializer() async { + await resolveTestUnit(''' +main() { + int v; +} +'''); + await assertNoAssistAt('v;'); + } + + test_localVariable_onInitializer() async { + await resolveTestUnit(''' +main() { + final int v = 1; +} +'''); + await assertNoAssistAt('1;'); + } + + test_localVariable() async { + await resolveTestUnit(''' +main() { + int a = 1, b = 2; +} +'''); + await assertHasAssistAt('int ', ''' +main() { + var a = 1, b = 2; +} +'''); + } + + test_localVariable_const() async { + await resolveTestUnit(''' +main() { + const int v = 1; +} +'''); + await assertHasAssistAt('int ', ''' +main() { + const v = 1; +} +'''); + } + + test_localVariable_final() async { + await resolveTestUnit(''' +main() { + final int v = 1; +} +'''); + await assertHasAssistAt('int ', ''' +main() { + final v = 1; +} +'''); + } + + test_topLevelVariable_noInitializer() async { + verifyNoTestUnitErrors = false; + await resolveTestUnit(''' +int v; +'''); + await assertNoAssistAt('v;'); + } + + test_topLevelVariable_syntheticName() async { + verifyNoTestUnitErrors = false; + await resolveTestUnit(''' +MyType +'''); + await assertNoAssistAt('MyType'); + } + + test_topLevelVariable() async { + await resolveTestUnit(''' +int V = 1; +'''); + await assertHasAssistAt('int ', ''' +var V = 1; +'''); + } + + test_topLevelVariable_final() async { + await resolveTestUnit(''' +final int V = 1; +'''); + await assertHasAssistAt('int ', ''' +final V = 1; +'''); + } +}
diff --git a/pkg/analysis_server/test/src/services/correction/assist/replace_conditional_with_if_else_test.dart b/pkg/analysis_server/test/src/services/correction/assist/replace_conditional_with_if_else_test.dart new file mode 100644 index 0000000..4ef97dd --- /dev/null +++ b/pkg/analysis_server/test/src/services/correction/assist/replace_conditional_with_if_else_test.dart
@@ -0,0 +1,103 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:analysis_server/src/services/correction/assist.dart'; +import 'package:analyzer_plugin/utilities/assist/assist.dart'; +import 'package:test_reflective_loader/test_reflective_loader.dart'; + +import 'assist_processor.dart'; + +main() { + defineReflectiveSuite(() { + defineReflectiveTests(ReplaceConditionalWithIfElseTest); + }); +} + +@reflectiveTest +class ReplaceConditionalWithIfElseTest extends AssistProcessorTest { + @override + AssistKind get kind => DartAssistKind.REPLACE_CONDITIONAL_WITH_IF_ELSE; + + test_assignment() async { + await resolveTestUnit(''' +main() { + var v; + v = true ? 111 : 222; +} +'''); + // on conditional + await assertHasAssistAt('11 :', ''' +main() { + var v; + if (true) { + v = 111; + } else { + v = 222; + } +} +'''); + // on variable + await assertHasAssistAt('v =', ''' +main() { + var v; + if (true) { + v = 111; + } else { + v = 222; + } +} +'''); + } + + test_noEnclosingStatement() async { + await resolveTestUnit(''' +var v = true ? 111 : 222; +'''); + await assertNoAssistAt('? 111'); + } + + test_notConditional() async { + await resolveTestUnit(''' +main() { + var v = 42; +} +'''); + await assertNoAssistAt('v = 42'); + } + + test_return() async { + await resolveTestUnit(''' +main() { + return true ? 111 : 222; +} +'''); + await assertHasAssistAt('return ', ''' +main() { + if (true) { + return 111; + } else { + return 222; + } +} +'''); + } + + test_variableDeclaration() async { + await resolveTestUnit(''' +main() { + int a = 1, vvv = true ? 111 : 222, b = 2; +} +'''); + await assertHasAssistAt('11 :', ''' +main() { + int a = 1, vvv, b = 2; + if (true) { + vvv = 111; + } else { + vvv = 222; + } +} +'''); + } +}
diff --git a/pkg/analysis_server/test/src/services/correction/assist/replace_if_else_with_conditional_test.dart b/pkg/analysis_server/test/src/services/correction/assist/replace_if_else_with_conditional_test.dart new file mode 100644 index 0000000..a21af08 --- /dev/null +++ b/pkg/analysis_server/test/src/services/correction/assist/replace_if_else_with_conditional_test.dart
@@ -0,0 +1,95 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:analysis_server/src/services/correction/assist.dart'; +import 'package:analyzer_plugin/utilities/assist/assist.dart'; +import 'package:test_reflective_loader/test_reflective_loader.dart'; + +import 'assist_processor.dart'; + +main() { + defineReflectiveSuite(() { + defineReflectiveTests(ReplaceIfElseWithConditionalTest); + }); +} + +@reflectiveTest +class ReplaceIfElseWithConditionalTest extends AssistProcessorTest { + @override + AssistKind get kind => DartAssistKind.REPLACE_IF_ELSE_WITH_CONDITIONAL; + + test_assignment() async { + await resolveTestUnit(''' +main() { + int vvv; + if (true) { + vvv = 111; + } else { + vvv = 222; + } +} +'''); + await assertHasAssistAt('if (true)', ''' +main() { + int vvv; + vvv = true ? 111 : 222; +} +'''); + } + + test_expressionVsReturn() async { + await resolveTestUnit(''' +main() { + if (true) { + print(42); + } else { + return; + } +} +'''); + await assertNoAssistAt('else'); + } + + test_notIfStatement() async { + await resolveTestUnit(''' +main() { + print(0); +} +'''); + await assertNoAssistAt('print'); + } + + test_notSingleStatement() async { + await resolveTestUnit(''' +main() { + int vvv; + if (true) { + print(0); + vvv = 111; + } else { + print(0); + vvv = 222; + } +} +'''); + await assertNoAssistAt('if (true)'); + } + + test_return() async { + await resolveTestUnit(''' +main() { + if (true) { + return 111; + } else { + return 222; + } +} +'''); + await assertHasAssistAt('if (true)', ''' +main() { + return true ? 111 : 222; +} +'''); + } +}
diff --git a/pkg/analysis_server/test/src/services/correction/assist/split_and_condition_test.dart b/pkg/analysis_server/test/src/services/correction/assist/split_and_condition_test.dart new file mode 100644 index 0000000..31127f0 --- /dev/null +++ b/pkg/analysis_server/test/src/services/correction/assist/split_and_condition_test.dart
@@ -0,0 +1,158 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:analysis_server/src/services/correction/assist.dart'; +import 'package:analyzer_plugin/utilities/assist/assist.dart'; +import 'package:test_reflective_loader/test_reflective_loader.dart'; + +import 'assist_processor.dart'; + +main() { + defineReflectiveSuite(() { + defineReflectiveTests(SplitAndConditionTest); + }); +} + +@reflectiveTest +class SplitAndConditionTest extends AssistProcessorTest { + @override + AssistKind get kind => DartAssistKind.SPLIT_AND_CONDITION; + + test_hasElse() async { + await resolveTestUnit(''' +main() { + if (1 == 1 && 2 == 2) { + print(1); + } else { + print(2); + } +} +'''); + await assertNoAssistAt('&& 2'); + } + + test_innerAndExpression() async { + await resolveTestUnit(''' +main() { + if (1 == 1 && 2 == 2 && 3 == 3) { + print(0); + } +} +'''); + await assertHasAssistAt('&& 2 == 2', ''' +main() { + if (1 == 1) { + if (2 == 2 && 3 == 3) { + print(0); + } + } +} +'''); + } + + test_notAnd() async { + await resolveTestUnit(''' +main() { + if (1 == 1 || 2 == 2) { + print(0); + } +} +'''); + await assertNoAssistAt('|| 2'); + } + + test_notOnOperator() async { + await resolveTestUnit(''' +main() { + if (1 == 1 && 2 == 2) { + print(0); + } + print(3 == 3 && 4 == 4); +} +'''); + await assertNoAssistAt('main() {'); + } + + test_notPartOfIf() async { + await resolveTestUnit(''' +main() { + print(1 == 1 && 2 == 2); +} +'''); + await assertNoAssistAt('&& 2'); + } + + test_notTopLevelAnd() async { + await resolveTestUnit(''' +main() { + if (true || (1 == 1 && 2 == 2)) { + print(0); + } + if (true && (3 == 3 && 4 == 4)) { + print(0); + } +} +'''); + await assertNoAssistAt('&& 2'); + await assertNoAssistAt('&& 4'); + } + + test_selectionTooLarge() async { + await resolveTestUnit(''' +main() { + if (1 == 1 +// start +&& 2 +// end +== 2 +) { + print(0); + } + print(3 == 3 && 4 == 4); +} +'''); + await assertNoAssist(); + } + + test_thenBlock() async { + await resolveTestUnit(''' +main() { + if (true && false) { + print(0); + if (3 == 3) { + print(1); + } + } +} +'''); + await assertHasAssistAt('&& false', ''' +main() { + if (true) { + if (false) { + print(0); + if (3 == 3) { + print(1); + } + } + } +} +'''); + } + + test_thenStatement() async { + await resolveTestUnit(''' +main() { + if (true && false) + print(0); +} +'''); + await assertHasAssistAt('&& false', ''' +main() { + if (true) + if (false) + print(0); +} +'''); + } +}
diff --git a/pkg/analysis_server/test/src/services/correction/assist/split_variable_declaration_test.dart b/pkg/analysis_server/test/src/services/correction/assist/split_variable_declaration_test.dart new file mode 100644 index 0000000..2d88afc --- /dev/null +++ b/pkg/analysis_server/test/src/services/correction/assist/split_variable_declaration_test.dart
@@ -0,0 +1,87 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:analysis_server/src/services/correction/assist.dart'; +import 'package:analyzer_plugin/utilities/assist/assist.dart'; +import 'package:test_reflective_loader/test_reflective_loader.dart'; + +import 'assist_processor.dart'; + +main() { + defineReflectiveSuite(() { + defineReflectiveTests(SplitVariableDeclarationTest); + }); +} + +@reflectiveTest +class SplitVariableDeclarationTest extends AssistProcessorTest { + @override + AssistKind get kind => DartAssistKind.SPLIT_VARIABLE_DECLARATION; + + test_notOneVariable() async { + await resolveTestUnit(''' +main() { + var v = 1, v2; +} +'''); + await assertNoAssistAt('v = 1'); + } + + test_onName() async { + await resolveTestUnit(''' +main() { + var v = 1; +} +'''); + await assertHasAssistAt('v =', ''' +main() { + var v; + v = 1; +} +'''); + } + + test_onType() async { + await resolveTestUnit(''' +main() { + int v = 1; +} +'''); + await assertHasAssistAt('int ', ''' +main() { + int v; + v = 1; +} +'''); + } + + @failingTest + test_onType_prefixedByComment() async { + await resolveTestUnit(''' +main() { + /*comment*/int v = 1; +} +'''); + await assertHasAssistAt('int ', ''' +main() { + /*comment*/int v; + v = 1; +} +'''); + } + + test_onVar() async { + await resolveTestUnit(''' +main() { + var v = 1; +} +'''); + await assertHasAssistAt('var ', ''' +main() { + var v; + v = 1; +} +'''); + } +}
diff --git a/pkg/analysis_server/test/src/services/correction/assist/surround_with_block_test.dart b/pkg/analysis_server/test/src/services/correction/assist/surround_with_block_test.dart new file mode 100644 index 0000000..f4647be --- /dev/null +++ b/pkg/analysis_server/test/src/services/correction/assist/surround_with_block_test.dart
@@ -0,0 +1,42 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:analysis_server/src/services/correction/assist.dart'; +import 'package:analyzer_plugin/utilities/assist/assist.dart'; +import 'package:test_reflective_loader/test_reflective_loader.dart'; + +import 'assist_processor.dart'; + +main() { + defineReflectiveSuite(() { + defineReflectiveTests(SurroundWithBlockTest); + }); +} + +@reflectiveTest +class SurroundWithBlockTest extends AssistProcessorTest { + @override + AssistKind get kind => DartAssistKind.SURROUND_WITH_BLOCK; + + test_twoStatements() async { + await resolveTestUnit(''' +main() { +// start + print(0); + print(1); +// end +} +'''); + await assertHasAssist(''' +main() { +// start + { + print(0); + print(1); + } +// end +} +'''); + } +}
diff --git a/pkg/analysis_server/test/src/services/correction/assist/surround_with_do_while_test.dart b/pkg/analysis_server/test/src/services/correction/assist/surround_with_do_while_test.dart new file mode 100644 index 0000000..96fbd14 --- /dev/null +++ b/pkg/analysis_server/test/src/services/correction/assist/surround_with_do_while_test.dart
@@ -0,0 +1,44 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:analysis_server/src/services/correction/assist.dart'; +import 'package:analyzer_plugin/utilities/assist/assist.dart'; +import 'package:test_reflective_loader/test_reflective_loader.dart'; + +import 'assist_processor.dart'; + +main() { + defineReflectiveSuite(() { + defineReflectiveTests(SurroundWithDoWhileTest); + }); +} + +@reflectiveTest +class SurroundWithDoWhileTest extends AssistProcessorTest { + @override + AssistKind get kind => DartAssistKind.SURROUND_WITH_DO_WHILE; + + test_twoStatements() async { + await resolveTestUnit(''' +main() { +// start + print(0); + print(1); +// end +} +'''); + await assertHasAssist(''' +main() { +// start + do { + print(0); + print(1); + } while (condition); +// end +} +'''); + assertLinkedGroup(0, ['condition);']); + assertExitPosition(after: 'condition);'); + } +}
diff --git a/pkg/analysis_server/test/src/services/correction/assist/surround_with_for_in_test.dart b/pkg/analysis_server/test/src/services/correction/assist/surround_with_for_in_test.dart new file mode 100644 index 0000000..c775e1c --- /dev/null +++ b/pkg/analysis_server/test/src/services/correction/assist/surround_with_for_in_test.dart
@@ -0,0 +1,45 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:analysis_server/src/services/correction/assist.dart'; +import 'package:analyzer_plugin/utilities/assist/assist.dart'; +import 'package:test_reflective_loader/test_reflective_loader.dart'; + +import 'assist_processor.dart'; + +main() { + defineReflectiveSuite(() { + defineReflectiveTests(SurroundWithForInTest); + }); +} + +@reflectiveTest +class SurroundWithForInTest extends AssistProcessorTest { + @override + AssistKind get kind => DartAssistKind.SURROUND_WITH_FOR_IN; + + test_twoStatements() async { + await resolveTestUnit(''' +main() { +// start + print(0); + print(1); +// end +} +'''); + await assertHasAssist(''' +main() { +// start + for (var item in iterable) { + print(0); + print(1); + } +// end +} +'''); + assertLinkedGroup(0, ['item']); + assertLinkedGroup(1, ['iterable']); + assertExitPosition(after: ' }'); + } +}
diff --git a/pkg/analysis_server/test/src/services/correction/assist/surround_with_for_test.dart b/pkg/analysis_server/test/src/services/correction/assist/surround_with_for_test.dart new file mode 100644 index 0000000..770684c --- /dev/null +++ b/pkg/analysis_server/test/src/services/correction/assist/surround_with_for_test.dart
@@ -0,0 +1,47 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:analysis_server/src/services/correction/assist.dart'; +import 'package:analyzer_plugin/utilities/assist/assist.dart'; +import 'package:test_reflective_loader/test_reflective_loader.dart'; + +import 'assist_processor.dart'; + +main() { + defineReflectiveSuite(() { + defineReflectiveTests(SurroundWithForTest); + }); +} + +@reflectiveTest +class SurroundWithForTest extends AssistProcessorTest { + @override + AssistKind get kind => DartAssistKind.SURROUND_WITH_FOR; + + test_twoStatements() async { + await resolveTestUnit(''' +main() { +// start + print(0); + print(1); +// end +} +'''); + await assertHasAssist(''' +main() { +// start + for (var v = init; condition; increment) { + print(0); + print(1); + } +// end +} +'''); + assertLinkedGroup(0, ['v =']); + assertLinkedGroup(1, ['init;']); + assertLinkedGroup(2, ['condition;']); + assertLinkedGroup(3, ['increment']); + assertExitPosition(after: ' }'); + } +}
diff --git a/pkg/analysis_server/test/src/services/correction/assist/surround_with_if_test.dart b/pkg/analysis_server/test/src/services/correction/assist/surround_with_if_test.dart new file mode 100644 index 0000000..de8df15 --- /dev/null +++ b/pkg/analysis_server/test/src/services/correction/assist/surround_with_if_test.dart
@@ -0,0 +1,44 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:analysis_server/src/services/correction/assist.dart'; +import 'package:analyzer_plugin/utilities/assist/assist.dart'; +import 'package:test_reflective_loader/test_reflective_loader.dart'; + +import 'assist_processor.dart'; + +main() { + defineReflectiveSuite(() { + defineReflectiveTests(SurroundWithIfTest); + }); +} + +@reflectiveTest +class SurroundWithIfTest extends AssistProcessorTest { + @override + AssistKind get kind => DartAssistKind.SURROUND_WITH_IF; + + test_twoStatements() async { + await resolveTestUnit(''' +main() { +// start + print(0); + print(1); +// end +} +'''); + await assertHasAssist(''' +main() { +// start + if (condition) { + print(0); + print(1); + } +// end +} +'''); + assertLinkedGroup(0, ['condition']); + assertExitPosition(after: ' }'); + } +}
diff --git a/pkg/analysis_server/test/src/services/correction/assist/surround_with_try_catch_test.dart b/pkg/analysis_server/test/src/services/correction/assist/surround_with_try_catch_test.dart new file mode 100644 index 0000000..f39a5e0 --- /dev/null +++ b/pkg/analysis_server/test/src/services/correction/assist/surround_with_try_catch_test.dart
@@ -0,0 +1,48 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:analysis_server/src/services/correction/assist.dart'; +import 'package:analyzer_plugin/utilities/assist/assist.dart'; +import 'package:test_reflective_loader/test_reflective_loader.dart'; + +import 'assist_processor.dart'; + +main() { + defineReflectiveSuite(() { + defineReflectiveTests(SurroundWithTryCatchTest); + }); +} + +@reflectiveTest +class SurroundWithTryCatchTest extends AssistProcessorTest { + @override + AssistKind get kind => DartAssistKind.SURROUND_WITH_TRY_CATCH; + + test_twoStatements() async { + await resolveTestUnit(''' +main() { +// start + print(0); + print(1); +// end +} +'''); + await assertHasAssist(''' +main() { +// start + try { + print(0); + print(1); + } on Exception catch (e) { + // TODO + } +// end +} +'''); + assertLinkedGroup(0, ['Exception']); + assertLinkedGroup(1, ['e) {']); + assertLinkedGroup(2, ['// TODO']); + assertExitPosition(after: '// TODO'); + } +}
diff --git a/pkg/analysis_server/test/src/services/correction/assist/surround_with_try_finally_test.dart b/pkg/analysis_server/test/src/services/correction/assist/surround_with_try_finally_test.dart new file mode 100644 index 0000000..7e9267c --- /dev/null +++ b/pkg/analysis_server/test/src/services/correction/assist/surround_with_try_finally_test.dart
@@ -0,0 +1,46 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:analysis_server/src/services/correction/assist.dart'; +import 'package:analyzer_plugin/utilities/assist/assist.dart'; +import 'package:test_reflective_loader/test_reflective_loader.dart'; + +import 'assist_processor.dart'; + +main() { + defineReflectiveSuite(() { + defineReflectiveTests(SurroundWithTryFinallyTest); + }); +} + +@reflectiveTest +class SurroundWithTryFinallyTest extends AssistProcessorTest { + @override + AssistKind get kind => DartAssistKind.SURROUND_WITH_TRY_FINALLY; + + test_twoStatements() async { + await resolveTestUnit(''' +main() { +// start + print(0); + print(1); +// end +} +'''); + await assertHasAssist(''' +main() { +// start + try { + print(0); + print(1); + } finally { + // TODO + } +// end +} +'''); + assertLinkedGroup(0, ['// TODO']); + assertExitPosition(after: '// TODO'); + } +}
diff --git a/pkg/analysis_server/test/src/services/correction/assist/surround_with_while_test.dart b/pkg/analysis_server/test/src/services/correction/assist/surround_with_while_test.dart new file mode 100644 index 0000000..939e211 --- /dev/null +++ b/pkg/analysis_server/test/src/services/correction/assist/surround_with_while_test.dart
@@ -0,0 +1,44 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:analysis_server/src/services/correction/assist.dart'; +import 'package:analyzer_plugin/utilities/assist/assist.dart'; +import 'package:test_reflective_loader/test_reflective_loader.dart'; + +import 'assist_processor.dart'; + +main() { + defineReflectiveSuite(() { + defineReflectiveTests(SurroundWithWhileTest); + }); +} + +@reflectiveTest +class SurroundWithWhileTest extends AssistProcessorTest { + @override + AssistKind get kind => DartAssistKind.SURROUND_WITH_WHILE; + + test_twoStatements() async { + await resolveTestUnit(''' +main() { +// start + print(0); + print(1); +// end +} +'''); + await assertHasAssist(''' +main() { +// start + while (condition) { + print(0); + print(1); + } +// end +} +'''); + assertLinkedGroup(0, ['condition']); + assertExitPosition(after: ' }'); + } +}
diff --git a/pkg/analysis_server/test/src/services/correction/assist/test_all.dart b/pkg/analysis_server/test/src/services/correction/assist/test_all.dart new file mode 100644 index 0000000..be58fce --- /dev/null +++ b/pkg/analysis_server/test/src/services/correction/assist/test_all.dart
@@ -0,0 +1,129 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:test_reflective_loader/test_reflective_loader.dart'; + +import 'add_type_annotation_test.dart' as add_type_annotation; +import 'assign_to_local_variable_test.dart' as assign_to_local_variable; +import 'convert_class_to_mixin_test.dart' as convert_class_to_mixin; +import 'convert_documentation_into_block_test.dart' + as convert_documentation_into_block; +import 'convert_documentation_into_line_test.dart' + as convert_documentation_into_line; +import 'convert_into_async_body_test.dart' as convert_into_async_body; +import 'convert_into_block_body_test.dart' as convert_into_block_body; +import 'convert_into_expression_body_test.dart' as convert_into_expression_body; +import 'convert_into_final_field_test.dart' as convert_into_final_field; +import 'convert_into_for_index_test.dart' as convert_into_for_index; +import 'convert_into_generic_function_syntax_test.dart' + as convert_into_generic_function_syntax; +import 'convert_into_getter_test.dart' as convert_into_getter; +import 'convert_into_is_not_empty_test.dart' as convert_into_is_not_empty; +import 'convert_into_is_not_test.dart' as convert_into_is_not; +import 'convert_part_of_to_uri_test.dart' as convert_part_of_to_uri; +import 'convert_to_double_quoted_string_test.dart' + as convert_to_double_quoted_string; +import 'convert_to_field_parameter_test.dart' as convert_to_field_parameter; +import 'convert_to_int_literal_test.dart' as convert_to_int_literal; +import 'convert_to_normal_parameter_test.dart' as convert_to_normal_parameter; +import 'convert_to_single_quoted_string_test.dart' + as convert_to_single_quoted_string; +import 'encapsulate_field_test.dart' as encapsulate_field; +import 'exchange_operands_test.dart' as exchange_operands; +import 'flutter_convert_to_children_test.dart' as flutter_convert_to_children; +import 'flutter_convert_to_stateful_widget_test.dart' + as flutter_convert_to_stateful_widget; +import 'flutter_move_down_test.dart' as flutter_move_down; +import 'flutter_move_up_test.dart' as flutter_move_up; +import 'flutter_remove_widget_test.dart' as flutter_remove_widget; +import 'flutter_swap_with_child_test.dart' as flutter_swap_with_child; +import 'flutter_swap_with_parent_test.dart' as flutter_swap_with_parent; +import 'flutter_wrap_center_test.dart' as flutter_wrap_center; +import 'flutter_wrap_column_test.dart' as flutter_wrap_column; +import 'flutter_wrap_container_test.dart' as flutter_wrap_container; +import 'flutter_wrap_generic_test.dart' as flutter_wrap_generic; +import 'flutter_wrap_padding_test.dart' as flutter_wrap_padding; +import 'flutter_wrap_row_test.dart' as flutter_wrap_row; +import 'flutter_wrap_stream_builder_test.dart' as flutter_wrap_stream_builder; +import 'import_add_show_test.dart' as import_add_show; +import 'introduce_local_cast_type_test.dart' as introduce_local_cast_type; +import 'invert_if_statement_test.dart' as invert_if_statement; +import 'join_if_with_inner_test.dart' as join_if_with_inner; +import 'join_if_with_outer_test.dart' as join_if_with_outer; +import 'join_variable_declaration_test.dart' as join_variable_declaration; +import 'remove_type_annotation_test.dart' as remove_type_annotation; +import 'replace_conditional_with_if_else_test.dart' + as replace_conditional_with_if_else; +import 'replace_if_else_with_conditional_test.dart' + as replace_if_else_with_conditional; +import 'split_and_condition_test.dart' as split_and_condition; +import 'split_variable_declaration_test.dart' as split_variable_declaration; +import 'surround_with_block_test.dart' as surround_with_block; +import 'surround_with_do_while_test.dart' as surround_with_do_while; +import 'surround_with_for_in_test.dart' as surround_with_for_in; +import 'surround_with_for_test.dart' as surround_with_for; +import 'surround_with_if_test.dart' as surround_with_if; +import 'surround_with_try_catch_test.dart' as surround_with_try_catch; +import 'surround_with_try_finally_test.dart' as surround_with_try_finally; +import 'surround_with_while_test.dart' as surround_with_while; + +main() { + defineReflectiveSuite(() { + add_type_annotation.main(); + assign_to_local_variable.main(); + convert_class_to_mixin.main(); + convert_documentation_into_block.main(); + convert_documentation_into_line.main(); + convert_into_async_body.main(); + convert_into_block_body.main(); + convert_into_expression_body.main(); + convert_into_final_field.main(); + convert_into_for_index.main(); + convert_into_generic_function_syntax.main(); + convert_into_getter.main(); + convert_into_is_not.main(); + convert_into_is_not_empty.main(); + convert_part_of_to_uri.main(); + convert_to_double_quoted_string.main(); + convert_to_field_parameter.main(); + convert_to_int_literal.main(); + convert_to_normal_parameter.main(); + convert_to_single_quoted_string.main(); + encapsulate_field.main(); + exchange_operands.main(); + flutter_convert_to_children.main(); + flutter_convert_to_stateful_widget.main(); + flutter_move_down.main(); + flutter_move_up.main(); + flutter_remove_widget.main(); + flutter_swap_with_child.main(); + flutter_swap_with_parent.main(); + flutter_wrap_center.main(); + flutter_wrap_column.main(); + flutter_wrap_container.main(); + flutter_wrap_generic.main(); + flutter_wrap_padding.main(); + flutter_wrap_row.main(); + flutter_wrap_stream_builder.main(); + import_add_show.main(); + introduce_local_cast_type.main(); + invert_if_statement.main(); + join_if_with_inner.main(); + join_if_with_outer.main(); + join_variable_declaration.main(); + remove_type_annotation.main(); + replace_conditional_with_if_else.main(); + replace_if_else_with_conditional.main(); + split_and_condition.main(); + split_variable_declaration.main(); + surround_with_block.main(); + surround_with_do_while.main(); + surround_with_for.main(); + surround_with_for_in.main(); + surround_with_if.main(); + surround_with_try_catch.main(); + surround_with_try_finally.main(); + surround_with_while.main(); + }, name: 'assist'); +}
diff --git a/pkg/analysis_server/test/src/services/correction/fix/add_async_test.dart b/pkg/analysis_server/test/src/services/correction/fix/add_async_test.dart new file mode 100644 index 0000000..49938b4 --- /dev/null +++ b/pkg/analysis_server/test/src/services/correction/fix/add_async_test.dart
@@ -0,0 +1,199 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:analysis_server/src/services/correction/fix.dart'; +import 'package:analyzer/error/error.dart'; +import 'package:analyzer/src/error/codes.dart'; +import 'package:analyzer_plugin/utilities/fixes/fixes.dart'; +import 'package:test_reflective_loader/test_reflective_loader.dart'; + +import 'fix_processor.dart'; + +main() { + defineReflectiveSuite(() { + defineReflectiveTests(AddAsyncTest); + }); +} + +@reflectiveTest +class AddAsyncTest extends FixProcessorTest { + @override + FixKind get kind => DartFixKind.ADD_ASYNC; + + test_asyncFor() async { + await resolveTestUnit(''' +import 'dart:async'; +void main(Stream<String> names) { + await for (String name in names) { + print(name); + } +} +'''); + await assertHasFix(''' +import 'dart:async'; +Future main(Stream<String> names) async { + await for (String name in names) { + print(name); + } +} +'''); + } + + test_blockFunctionBody_function() async { + await resolveTestUnit(''' +foo() {} +main() { + await foo(); +} +'''); + await assertHasFix(''' +foo() {} +main() async { + await foo(); +} +''', errorFilter: (AnalysisError error) { + return error.errorCode == + CompileTimeErrorCode.BUILT_IN_IDENTIFIER_AS_TYPE; + }); + } + + test_blockFunctionBody_getter() async { + await resolveTestUnit(''' +int get foo => null; +int f() { + await foo; + return 1; +} +'''); + await assertHasFix(''' +int get foo => null; +Future<int> f() async { + await foo; + return 1; +} +''', errorFilter: (AnalysisError error) { + return error.errorCode == + CompileTimeErrorCode.BUILT_IN_IDENTIFIER_AS_TYPE; + }); + } + + test_closure() async { + await resolveTestUnit(''' +import 'dart:async'; + +void takeFutureCallback(Future callback()) {} + +void doStuff() => takeFutureCallback(() => await 1); +'''); + await assertHasFix(''' +import 'dart:async'; + +void takeFutureCallback(Future callback()) {} + +void doStuff() => takeFutureCallback(() async => await 1); +''', errorFilter: (AnalysisError error) { + return error.errorCode == StaticWarningCode.UNDEFINED_IDENTIFIER_AWAIT; + }); + } + + test_expressionFunctionBody() async { + await resolveTestUnit(''' +foo() {} +main() => await foo(); +'''); + await assertHasFix(''' +foo() {} +main() async => await foo(); +'''); + } + + test_nullFunctionBody() async { + await resolveTestUnit(''' +var F = await; +'''); + await assertNoFix(); + } + + test_returnFuture_alreadyFuture() async { + await resolveTestUnit(''' +import 'dart:async'; +foo() {} +Future<int> main() { + await foo(); + return 42; +} +'''); + await assertHasFix(''' +import 'dart:async'; +foo() {} +Future<int> main() async { + await foo(); + return 42; +} +''', errorFilter: (AnalysisError error) { + return error.errorCode == + CompileTimeErrorCode.BUILT_IN_IDENTIFIER_AS_TYPE; + }); + } + + test_returnFuture_dynamic() async { + await resolveTestUnit(''' +foo() {} +dynamic main() { + await foo(); + return 42; +} +'''); + await assertHasFix(''' +foo() {} +dynamic main() async { + await foo(); + return 42; +} +''', errorFilter: (AnalysisError error) { + return error.errorCode == + CompileTimeErrorCode.BUILT_IN_IDENTIFIER_AS_TYPE; + }); + } + + test_returnFuture_nonFuture() async { + await resolveTestUnit(''' +foo() {} +int main() { + await foo(); + return 42; +} +'''); + await assertHasFix(''' +foo() {} +Future<int> main() async { + await foo(); + return 42; +} +''', errorFilter: (AnalysisError error) { + return error.errorCode == + CompileTimeErrorCode.BUILT_IN_IDENTIFIER_AS_TYPE; + }); + } + + test_returnFuture_noType() async { + await resolveTestUnit(''' +foo() {} +main() { + await foo(); + return 42; +} +'''); + await assertHasFix(''' +foo() {} +main() async { + await foo(); + return 42; +} +''', errorFilter: (AnalysisError error) { + return error.errorCode == + CompileTimeErrorCode.BUILT_IN_IDENTIFIER_AS_TYPE; + }); + } +}
diff --git a/pkg/analysis_server/test/src/services/correction/fix/add_explicit_cast_test.dart b/pkg/analysis_server/test/src/services/correction/fix/add_explicit_cast_test.dart new file mode 100644 index 0000000..e0ff288 --- /dev/null +++ b/pkg/analysis_server/test/src/services/correction/fix/add_explicit_cast_test.dart
@@ -0,0 +1,463 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:analysis_server/src/services/correction/fix.dart'; +import 'package:analyzer/src/error/codes.dart'; +import 'package:analyzer_plugin/utilities/fixes/fixes.dart'; +import 'package:test_reflective_loader/test_reflective_loader.dart'; + +import 'fix_processor.dart'; + +main() { + defineReflectiveSuite(() { + defineReflectiveTests(AddExplicitCastTest); + }); +} + +@reflectiveTest +class AddExplicitCastTest extends FixProcessorTest { + @override + FixKind get kind => DartFixKind.ADD_EXPLICIT_CAST; + + test_as() async { + await resolveTestUnit(''' +f(A a) { + C c = a as B; + print(c); +} +class A {} +class B {} +class C {} +'''); + await assertNoFix(); + } + + test_assignment_general() async { + await resolveTestUnit(''' +f(A a) { + B b; + b = a; + print(b); +} +class A {} +class B {} +'''); + await assertHasFix(''' +f(A a) { + B b; + b = a as B; + print(b); +} +class A {} +class B {} +'''); + } + + test_assignment_general_all() async { + await resolveTestUnit(''' +f(A a) { + B b, b2; + b = a; + b2 = a; +} +class A {} +class B {} +'''); + await assertHasFixAllFix(StaticTypeWarningCode.INVALID_ASSIGNMENT, ''' +f(A a) { + B b, b2; + b = a as B; + b2 = a as B; +} +class A {} +class B {} +'''); + } + + test_assignment_list() async { + await resolveTestUnit(''' +f(List<A> a) { + List<B> b; + b = a.where((e) => e is B).toList(); + print(b); +} +class A {} +class B {} +'''); + await assertHasFix(''' +f(List<A> a) { + List<B> b; + b = a.where((e) => e is B).cast<B>().toList(); + print(b); +} +class A {} +class B {} +'''); + } + + test_assignment_list_all() async { + await resolveTestUnit(''' +f(List<A> a) { + List<B> b, b2; + b = a.where((e) => e is B).toList(); + b2 = a.where((e) => e is B).toList(); +} +class A {} +class B {} +'''); + await assertHasFixAllFix(StaticTypeWarningCode.INVALID_ASSIGNMENT, ''' +f(List<A> a) { + List<B> b, b2; + b = a.where((e) => e is B).cast<B>().toList(); + b2 = a.where((e) => e is B).cast<B>().toList(); +} +class A {} +class B {} +'''); + } + + test_assignment_map() async { + await resolveTestUnit(''' +f(Map<A, B> a) { + Map<B, A> b; + b = a; + print(b); +} +class A {} +class B {} +'''); + await assertHasFix(''' +f(Map<A, B> a) { + Map<B, A> b; + b = a.cast<B, A>(); + print(b); +} +class A {} +class B {} +'''); + } + + test_assignment_map_all() async { + await resolveTestUnit(''' +f(Map<A, B> a) { + Map<B, A> b, b2; + b = a; + b2 = a; +} +class A {} +class B {} +'''); + await assertHasFixAllFix(StaticTypeWarningCode.INVALID_ASSIGNMENT, ''' +f(Map<A, B> a) { + Map<B, A> b, b2; + b = a.cast<B, A>(); + b2 = a.cast<B, A>(); +} +class A {} +class B {} +'''); + } + + test_assignment_needsParens() async { + await resolveTestUnit(''' +f(A a) { + B b; + b = a..m(); + print(b); +} +class A { + int m() => 0; +} +class B {} +'''); + await assertHasFix(''' +f(A a) { + B b; + b = (a..m()) as B; + print(b); +} +class A { + int m() => 0; +} +class B {} +'''); + } + + test_assignment_needsParens_all() async { + await resolveTestUnit(''' +f(A a) { + B b, b2; + b = a..m(); + b2 = a..m(); +} +class A { + int m() => 0; +} +class B {} +'''); + await assertHasFixAllFix(StaticTypeWarningCode.INVALID_ASSIGNMENT, ''' +f(A a) { + B b, b2; + b = (a..m()) as B; + b2 = (a..m()) as B; +} +class A { + int m() => 0; +} +class B {} +'''); + } + + test_assignment_set() async { + await resolveTestUnit(''' +f(Set<A> a) { + Set<B> b; + b = a; + print(b); +} +class A {} +class B {} +'''); + await assertHasFix(''' +f(Set<A> a) { + Set<B> b; + b = a.cast<B>(); + print(b); +} +class A {} +class B {} +'''); + } + + test_assignment_set_all() async { + await resolveTestUnit(''' +f(Set<A> a) { + Set<B> b, b2; + b = a; + b2 = a; +} +class A {} +class B {} +'''); + await assertHasFixAllFix(StaticTypeWarningCode.INVALID_ASSIGNMENT, ''' +f(Set<A> a) { + Set<B> b, b2; + b = a.cast<B>(); + b2 = a.cast<B>(); +} +class A {} +class B {} +'''); + } + + test_cast() async { + await resolveTestUnit(''' +f(List<A> a) { + List<B> b = a.cast<A>(); + print(b); +} +class A {} +class B {} +'''); + await assertNoFix(); + } + + test_declaration_general() async { + await resolveTestUnit(''' +f(A a) { + B b = a; + print(b); +} +class A {} +class B {} +'''); + await assertHasFix(''' +f(A a) { + B b = a as B; + print(b); +} +class A {} +class B {} +'''); + } + + test_declaration_general_all() async { + await resolveTestUnit(''' +f(A a) { + B b = a; + B b2 = a; +} +class A {} +class B {} +'''); + await assertHasFixAllFix(StaticTypeWarningCode.INVALID_ASSIGNMENT, ''' +f(A a) { + B b = a as B; + B b2 = a as B; +} +class A {} +class B {} +'''); + } + + test_declaration_list() async { + await resolveTestUnit(''' +f(List<A> a) { + List<B> b = a.where((e) => e is B).toList(); + print(b); +} +class A {} +class B {} +'''); + await assertHasFix(''' +f(List<A> a) { + List<B> b = a.where((e) => e is B).cast<B>().toList(); + print(b); +} +class A {} +class B {} +'''); + } + + test_declaration_list_all() async { + await resolveTestUnit(''' +f(List<A> a) { + List<B> b = a.where((e) => e is B).toList(); + List<B> b2 = a.where((e) => e is B).toList(); +} +class A {} +class B {} +'''); + await assertHasFixAllFix(StaticTypeWarningCode.INVALID_ASSIGNMENT, ''' +f(List<A> a) { + List<B> b = a.where((e) => e is B).cast<B>().toList(); + List<B> b2 = a.where((e) => e is B).cast<B>().toList(); +} +class A {} +class B {} +'''); + } + + test_declaration_map() async { + await resolveTestUnit(''' +f(Map<A, B> a) { + Map<B, A> b = a; + print(b); +} +class A {} +class B {} +'''); + await assertHasFix(''' +f(Map<A, B> a) { + Map<B, A> b = a.cast<B, A>(); + print(b); +} +class A {} +class B {} +'''); + } + + test_declaration_map_all() async { + await resolveTestUnit(''' +f(Map<A, B> a) { + Map<B, A> b = a; + Map<B, A> b2 = a; +} +class A {} +class B {} +'''); + await assertHasFixAllFix(StaticTypeWarningCode.INVALID_ASSIGNMENT, ''' +f(Map<A, B> a) { + Map<B, A> b = a.cast<B, A>(); + Map<B, A> b2 = a.cast<B, A>(); +} +class A {} +class B {} +'''); + } + + test_declaration_needsParens() async { + await resolveTestUnit(''' +f(A a) { + B b = a..m(); + print(b); +} +class A { + int m() => 0; +} +class B {} +'''); + await assertHasFix(''' +f(A a) { + B b = (a..m()) as B; + print(b); +} +class A { + int m() => 0; +} +class B {} +'''); + } + + test_declaration_needsParens_all() async { + await resolveTestUnit(''' +f(A a) { + B b = a..m(); + B b2 = a..m(); +} +class A { + int m() => 0; +} +class B {} +'''); + await assertHasFixAllFix(StaticTypeWarningCode.INVALID_ASSIGNMENT, ''' +f(A a) { + B b = (a..m()) as B; + B b2 = (a..m()) as B; +} +class A { + int m() => 0; +} +class B {} +'''); + } + + test_declaration_set() async { + await resolveTestUnit(''' +f(Set<A> a) { + Set<B> b = a; + print(b); +} +class A {} +class B {} +'''); + await assertHasFix(''' +f(Set<A> a) { + Set<B> b = a.cast<B>(); + print(b); +} +class A {} +class B {} +'''); + } + + test_declaration_set_all() async { + await resolveTestUnit(''' +f(Set<A> a) { + Set<B> b = a; + Set<B> b2 = a; +} +class A {} +class B {} +'''); + await assertHasFixAllFix(StaticTypeWarningCode.INVALID_ASSIGNMENT, ''' +f(Set<A> a) { + Set<B> b = a.cast<B>(); + Set<B> b2 = a.cast<B>(); +} +class A {} +class B {} +'''); + } +}
diff --git a/pkg/analysis_server/test/src/services/correction/fix/add_field_formal_parameters_test.dart b/pkg/analysis_server/test/src/services/correction/fix/add_field_formal_parameters_test.dart new file mode 100644 index 0000000..172aee9 --- /dev/null +++ b/pkg/analysis_server/test/src/services/correction/fix/add_field_formal_parameters_test.dart
@@ -0,0 +1,123 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:analysis_server/src/services/correction/fix.dart'; +import 'package:analyzer_plugin/utilities/fixes/fixes.dart'; +import 'package:test_reflective_loader/test_reflective_loader.dart'; + +import 'fix_processor.dart'; + +main() { + defineReflectiveSuite(() { + defineReflectiveTests(AddFieldFormalParametersTest); + }); +} + +@reflectiveTest +class AddFieldFormalParametersTest extends FixProcessorTest { + @override + FixKind get kind => DartFixKind.ADD_FIELD_FORMAL_PARAMETERS; + + test_flutter() async { + addFlutterPackage(); + await resolveTestUnit(''' +import 'package:flutter/widgets.dart'; + +class MyWidget extends StatelessWidget { + final int a; + final int b; + final int c; + + MyWidget({Key key, this.a}) : super(key: key); +} +'''); + await assertHasFix(''' +import 'package:flutter/widgets.dart'; + +class MyWidget extends StatelessWidget { + final int a; + final int b; + final int c; + + MyWidget({Key key, this.a, this.b, this.c}) : super(key: key); +} +'''); + } + + test_hasRequiredParameter() async { + await resolveTestUnit(''' +class Test { + final int a; + final int b; + final int c; + Test(this.a); +} +'''); + await assertHasFix(''' +class Test { + final int a; + final int b; + final int c; + Test(this.a, this.b, this.c); +} +'''); + } + + test_noParameters() async { + await resolveTestUnit(''' +class Test { + final int a; + final int b; + final int c; + Test(); +} +'''); + await assertHasFix(''' +class Test { + final int a; + final int b; + final int c; + Test(this.a, this.b, this.c); +} +'''); + } + + test_noRequiredParameter() async { + await resolveTestUnit(''' +class Test { + final int a; + final int b; + final int c; + Test([this.c]); +} +'''); + await assertHasFix(''' +class Test { + final int a; + final int b; + final int c; + Test(this.a, this.b, [this.c]); +} +'''); + } + + test_notAllFinal() async { + await resolveTestUnit(''' +class Test { + final int a; + int b; + final int c; + Test(); +} +'''); + await assertHasFix(''' +class Test { + final int a; + int b; + final int c; + Test(this.a, this.c); +} +'''); + } +}
diff --git a/pkg/analysis_server/test/src/services/correction/fix/add_missing_parameter_named_test.dart b/pkg/analysis_server/test/src/services/correction/fix/add_missing_parameter_named_test.dart new file mode 100644 index 0000000..0378f7e --- /dev/null +++ b/pkg/analysis_server/test/src/services/correction/fix/add_missing_parameter_named_test.dart
@@ -0,0 +1,232 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:analysis_server/src/services/correction/fix.dart'; +import 'package:analyzer_plugin/utilities/fixes/fixes.dart'; +import 'package:test_reflective_loader/test_reflective_loader.dart'; + +import 'fix_processor.dart'; + +main() { + defineReflectiveSuite(() { + defineReflectiveTests(AddMissingParameterNamedTest); + }); +} + +@reflectiveTest +class AddMissingParameterNamedTest extends FixProcessorTest { + @override + FixKind get kind => DartFixKind.ADD_MISSING_PARAMETER_NAMED; + + test_constructor_hasNamed() async { + await resolveTestUnit(''' +class A { + A(int a, {int b}) {} +} + +main() { + new A(1, b: 2, named: 3.0); +} +'''); + await assertHasFix(''' +class A { + A(int a, {int b, double named}) {} +} + +main() { + new A(1, b: 2, named: 3.0); +} +'''); + } + + test_constructor_hasRequired() async { + await resolveTestUnit(''' +class A { + A(int a) {} +} + +main() { + new A(1, named: 2.0); +} +'''); + await assertHasFix(''' +class A { + A(int a, {double named}) {} +} + +main() { + new A(1, named: 2.0); +} +'''); + } + + test_constructor_noParameters() async { + await resolveTestUnit(''' +class A { + A() {} +} + +main() { + new A(named: 42); +} +'''); + await assertHasFix(''' +class A { + A({int named}) {} +} + +main() { + new A(named: 42); +} +'''); + } + + test_constructor_noParameters_named() async { + await resolveTestUnit(''' +class A { + A.aaa() {} +} + +main() { + new A.aaa(named: 42); +} +'''); + await assertHasFix(''' +class A { + A.aaa({int named}) {} +} + +main() { + new A.aaa(named: 42); +} +'''); + } + + test_function_hasNamed() async { + await resolveTestUnit(''' +test(int a, {int b: 0}) {} + +main() { + test(1, b: 2, named: 3.0); +} +'''); + await assertHasFix(''' +test(int a, {int b: 0, double named}) {} + +main() { + test(1, b: 2, named: 3.0); +} +'''); + } + + test_function_hasRequired() async { + await resolveTestUnit(''' +test(int a) {} + +main() { + test(1, named: 2.0); +} +'''); + await assertHasFix(''' +test(int a, {double named}) {} + +main() { + test(1, named: 2.0); +} +'''); + } + + test_function_noParameters() async { + await resolveTestUnit(''' +test() {} + +main() { + test(named: 42); +} +'''); + await assertHasFix(''' +test({int named}) {} + +main() { + test(named: 42); +} +'''); + } + + test_method_hasNamed() async { + await resolveTestUnit(''' +class A { + test(int a, {int b: 0}) {} + + main() { + test(1, b: 2, named: 3.0); + } +} +'''); + await assertHasFix(''' +class A { + test(int a, {int b: 0, double named}) {} + + main() { + test(1, b: 2, named: 3.0); + } +} +'''); + } + + test_method_hasOptionalPositional() async { + await resolveTestUnit(''' +class A { + test(int a, [int b]) {} + + main() { + test(1, 2, named: 3.0); + } +} +'''); + await assertNoFix(); + } + + test_method_hasRequired() async { + await resolveTestUnit(''' +class A { + test(int a) {} + + main() { + test(1, named: 2.0); + } +} +'''); + await assertHasFix(''' +class A { + test(int a, {double named}) {} + + main() { + test(1, named: 2.0); + } +} +'''); + } + + test_method_noParameters() async { + await resolveTestUnit(''' +class A { + test() {} + + main() { + test(named: 42); + } +} +'''); + await assertHasFix(''' +class A { + test({int named}) {} + + main() { + test(named: 42); + } +} +'''); + } +}
diff --git a/pkg/analysis_server/test/src/services/correction/fix/add_missing_parameter_positional_test.dart b/pkg/analysis_server/test/src/services/correction/fix/add_missing_parameter_positional_test.dart new file mode 100644 index 0000000..ba8e53d --- /dev/null +++ b/pkg/analysis_server/test/src/services/correction/fix/add_missing_parameter_positional_test.dart
@@ -0,0 +1,65 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:analysis_server/src/services/correction/fix.dart'; +import 'package:analyzer_plugin/utilities/fixes/fixes.dart'; +import 'package:test_reflective_loader/test_reflective_loader.dart'; + +import 'fix_processor.dart'; + +main() { + defineReflectiveSuite(() { + defineReflectiveTests(AddMissingParameterPositionalTest); + }); +} + +@reflectiveTest +class AddMissingParameterPositionalTest extends FixProcessorTest { + @override + FixKind get kind => DartFixKind.ADD_MISSING_PARAMETER_POSITIONAL; + + test_function_hasNamed() async { + await resolveTestUnit(''' +test({int a}) {} +main() { + test(1); +} +'''); + await assertNoFix(); + } + + test_function_hasZero() async { + await resolveTestUnit(''' +test() {} +main() { + test(1); +} +'''); + await assertHasFix(''' +test([int i]) {} +main() { + test(1); +} +'''); + } + + test_method_hasOne() async { + await resolveTestUnit(''' +class A { + test(int a) {} + main() { + test(1, 2.0); + } +} +'''); + await assertHasFix(''' +class A { + test(int a, [double d]) {} + main() { + test(1, 2.0); + } +} +'''); + } +}
diff --git a/pkg/analysis_server/test/src/services/correction/fix/add_missing_parameter_required_test.dart b/pkg/analysis_server/test/src/services/correction/fix/add_missing_parameter_required_test.dart new file mode 100644 index 0000000..7e4dbdf --- /dev/null +++ b/pkg/analysis_server/test/src/services/correction/fix/add_missing_parameter_required_test.dart
@@ -0,0 +1,142 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:analysis_server/src/services/correction/fix.dart'; +import 'package:analyzer_plugin/utilities/fixes/fixes.dart'; +import 'package:test_reflective_loader/test_reflective_loader.dart'; + +import 'fix_processor.dart'; + +main() { + defineReflectiveSuite(() { + defineReflectiveTests(AddMissingParameterRequiredTest); + }); +} + +@reflectiveTest +class AddMissingParameterRequiredTest extends FixProcessorTest { + @override + FixKind get kind => DartFixKind.ADD_MISSING_PARAMETER_REQUIRED; + + test_constructor_named_hasOne() async { + await resolveTestUnit(''' +class A { + A.named(int a) {} +} +main() { + new A.named(1, 2.0); +} +'''); + await assertHasFix(''' +class A { + A.named(int a, double d) {} +} +main() { + new A.named(1, 2.0); +} +'''); + } + + test_constructor_unnamed_hasOne() async { + await resolveTestUnit(''' +class A { + A(int a) {} +} +main() { + new A(1, 2.0); +} +'''); + await assertHasFix(''' +class A { + A(int a, double d) {} +} +main() { + new A(1, 2.0); +} +'''); + } + + test_function_hasNamed() async { + await resolveTestUnit(''' +test({int a}) {} +main() { + test(1); +} +'''); + await assertHasFix(''' +test(int i, {int a}) {} +main() { + test(1); +} +'''); + } + + test_function_hasOne() async { + await resolveTestUnit(''' +test(int a) {} +main() { + test(1, 2.0); +} +'''); + await assertHasFix(''' +test(int a, double d) {} +main() { + test(1, 2.0); +} +'''); + } + + test_function_hasZero() async { + await resolveTestUnit(''' +test() {} +main() { + test(1); +} +'''); + await assertHasFix(''' +test(int i) {} +main() { + test(1); +} +'''); + } + + test_method_hasOne() async { + await resolveTestUnit(''' +class A { + test(int a) {} + main() { + test(1, 2.0); + } +} +'''); + await assertHasFix(''' +class A { + test(int a, double d) {} + main() { + test(1, 2.0); + } +} +'''); + } + + test_method_hasZero() async { + await resolveTestUnit(''' +class A { + test() {} + main() { + test(1); + } +} +'''); + await assertHasFix(''' +class A { + test(int i) {} + main() { + test(1); + } +} +'''); + } +}
diff --git a/pkg/analysis_server/test/src/services/correction/fix/add_missing_required_argument_test.dart b/pkg/analysis_server/test/src/services/correction/fix/add_missing_required_argument_test.dart new file mode 100644 index 0000000..20df52c --- /dev/null +++ b/pkg/analysis_server/test/src/services/correction/fix/add_missing_required_argument_test.dart
@@ -0,0 +1,369 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:analysis_server/src/services/correction/fix.dart'; +import 'package:analyzer_plugin/utilities/fixes/fixes.dart'; +import 'package:test_reflective_loader/test_reflective_loader.dart'; + +import 'fix_processor.dart'; + +main() { + defineReflectiveSuite(() { + defineReflectiveTests(AddMissingRequiredArgumentTest); + }); +} + +@reflectiveTest +class AddMissingRequiredArgumentTest extends FixProcessorTest { + @override + FixKind get kind => DartFixKind.ADD_MISSING_REQUIRED_ARGUMENT; + + test_cons_flutter_children() async { + addFlutterPackage(); + addMetaPackage(); + await resolveTestUnit(''' +import 'package:flutter/widgets.dart'; +import 'package:meta/meta.dart'; + +class MyWidget extends Widget { + MyWidget({@required List<Widget> children}); +} + +build() { + return new MyWidget(); +} +'''); + await assertHasFix(''' +import 'package:flutter/widgets.dart'; +import 'package:meta/meta.dart'; + +class MyWidget extends Widget { + MyWidget({@required List<Widget> children}); +} + +build() { + return new MyWidget(children: <Widget>[],); +} +'''); + } + + test_cons_flutter_hasTrailingComma() async { + addFlutterPackage(); + addMetaPackage(); + await resolveTestUnit(''' +import 'package:flutter/widgets.dart'; +import 'package:meta/meta.dart'; + +class MyWidget extends Widget { + MyWidget({@required int a, @required int b}); +} + +build() { + return new MyWidget(a: 1,); +} +'''); + await assertHasFix(''' +import 'package:flutter/widgets.dart'; +import 'package:meta/meta.dart'; + +class MyWidget extends Widget { + MyWidget({@required int a, @required int b}); +} + +build() { + return new MyWidget(a: 1, b: null,); +} +'''); + } + + test_cons_single() async { + addMetaPackage(); + addSource('/home/test/lib/a.dart', r''' +import 'package:meta/meta.dart'; + +class A { + A({@required int a}) {} +} +'''); + await resolveTestUnit(''' +import 'package:test/a.dart'; + +main() { + A a = new A(); + print(a); +} +'''); + await assertHasFix(''' +import 'package:test/a.dart'; + +main() { + A a = new A(a: null); + print(a); +} +'''); + } + + test_cons_single_closure() async { + addMetaPackage(); + addSource('/home/test/lib/a.dart', r''' +import 'package:meta/meta.dart'; + +typedef void VoidCallback(); + +class A { + A({@required VoidCallback onPressed}) {} +} +'''); + await resolveTestUnit(''' +import 'package:test/a.dart'; + +main() { + A a = new A(); + print(a); +} +'''); + await assertHasFix(''' +import 'package:test/a.dart'; + +main() { + A a = new A(onPressed: () {}); + print(a); +} +'''); + } + + test_cons_single_closure_2() async { + addMetaPackage(); + addSource('/home/test/lib/a.dart', r''' +import 'package:meta/meta.dart'; + +typedef void Callback(e); + +class A { + A({@required Callback callback}) {} +} +'''); + await resolveTestUnit(''' +import 'package:test/a.dart'; + +main() { + A a = new A(); + print(a); +} +'''); + await assertHasFix(''' +import 'package:test/a.dart'; + +main() { + A a = new A(callback: (e) {}); + print(a); +} +'''); + } + + test_cons_single_closure_3() async { + addMetaPackage(); + addSource('/home/test/lib/a.dart', r''' +import 'package:meta/meta.dart'; + +typedef void Callback(a,b,c); + +class A { + A({@required Callback callback}) {} +} +'''); + await resolveTestUnit(''' +import 'package:test/a.dart'; + +main() { + A a = new A(); + print(a); +} +'''); + await assertHasFix(''' +import 'package:test/a.dart'; + +main() { + A a = new A(callback: (a, b, c) {}); + print(a); +} +'''); + } + + test_cons_single_closure_4() async { + addMetaPackage(); + addSource('/home/test/lib/a.dart', r''' +import 'package:meta/meta.dart'; + +typedef int Callback(int a, String b,c); + +class A { + A({@required Callback callback}) {} +} +'''); + await resolveTestUnit(''' +import 'package:test/a.dart'; + +main() { + A a = new A(); + print(a); +} +'''); + await assertHasFix(''' +import 'package:test/a.dart'; + +main() { + A a = new A(callback: (int a, String b, c) {}); + print(a); +} +'''); + } + + test_cons_single_list() async { + addMetaPackage(); + addSource('/home/test/lib/a.dart', r''' +import 'package:meta/meta.dart'; + +class A { + A({@required List<String> names}) {} +} +'''); + await resolveTestUnit(''' +import 'package:test/a.dart'; + +main() { + A a = new A(); + print(a); +} +'''); + await assertHasFix(''' +import 'package:test/a.dart'; + +main() { + A a = new A(names: <String>[]); + print(a); +} +'''); + } + + test_multiple() async { + addMetaPackage(); + await resolveTestUnit(''' +import 'package:meta/meta.dart'; + +test({@required int a, @required int bcd}) {} +main() { + test(a: 3); +} +'''); + await assertHasFix(''' +import 'package:meta/meta.dart'; + +test({@required int a, @required int bcd}) {} +main() { + test(a: 3, bcd: null); +} +'''); + } + + test_multiple_1of2() async { + addMetaPackage(); + await resolveTestUnit(''' +import 'package:meta/meta.dart'; + +test({@required int a, @required int bcd}) {} +main() { + test(); +} +'''); + await assertHasFix(''' +import 'package:meta/meta.dart'; + +test({@required int a, @required int bcd}) {} +main() { + test(a: null); +} +''', errorFilter: (error) => error.message.contains("'a'")); + } + + test_multiple_2of2() async { + addMetaPackage(); + await resolveTestUnit(''' +import 'package:meta/meta.dart'; + +test({@required int a, @required int bcd}) {} +main() { + test(); +} +'''); + await assertHasFix(''' +import 'package:meta/meta.dart'; + +test({@required int a, @required int bcd}) {} +main() { + test(bcd: null); +} +''', errorFilter: (error) => error.message.contains("'bcd'")); + } + + test_single() async { + addMetaPackage(); + await resolveTestUnit(''' +import 'package:meta/meta.dart'; + +test({@required int abc}) {} +main() { + test(); +} +'''); + await assertHasFix(''' +import 'package:meta/meta.dart'; + +test({@required int abc}) {} +main() { + test(abc: null); +} +'''); + } + + test_single_normal() async { + addMetaPackage(); + await resolveTestUnit(''' +import 'package:meta/meta.dart'; + +test(String x, {@required int abc}) {} +main() { + test("foo"); +} +'''); + await assertHasFix(''' +import 'package:meta/meta.dart'; + +test(String x, {@required int abc}) {} +main() { + test("foo", abc: null); +} +'''); + } + + test_single_with_details() async { + addMetaPackage(); + await resolveTestUnit(''' +import 'package:meta/meta.dart'; + +test({@Required("Really who doesn't need an abc?") int abc}) {} +main() { + test(); +} +'''); + await assertHasFix(''' +import 'package:meta/meta.dart'; + +test({@Required("Really who doesn't need an abc?") int abc}) {} +main() { + test(abc: null); +} +'''); + } +}
diff --git a/pkg/analysis_server/test/src/services/correction/fix/add_ne_null_test.dart b/pkg/analysis_server/test/src/services/correction/fix/add_ne_null_test.dart new file mode 100644 index 0000000..c8b6d00 --- /dev/null +++ b/pkg/analysis_server/test/src/services/correction/fix/add_ne_null_test.dart
@@ -0,0 +1,62 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:analysis_server/src/services/correction/fix.dart'; +import 'package:analyzer/src/error/codes.dart'; +import 'package:analyzer_plugin/utilities/fixes/fixes.dart'; +import 'package:test_reflective_loader/test_reflective_loader.dart'; + +import 'fix_processor.dart'; + +main() { + defineReflectiveSuite(() { + defineReflectiveTests(AddNeNullTest); + }); +} + +@reflectiveTest +class AddNeNullTest extends FixProcessorTest { + @override + FixKind get kind => DartFixKind.ADD_NE_NULL; + + test_nonBoolCondition() async { + await resolveTestUnit(''' +main(String p) { + if (p) { + print(p); + } +} +'''); + await assertHasFix(''' +main(String p) { + if (p != null) { + print(p); + } +} +'''); + } + + test_nonBoolCondition_all() async { + await resolveTestUnit(''' +main(String p, String q) { + if (p) { + print(p); + } + if (q) { + print(q); + } +} +'''); + await assertHasFixAllFix(StaticTypeWarningCode.NON_BOOL_CONDITION, ''' +main(String p, String q) { + if (p != null) { + print(p); + } + if (q != null) { + print(q); + } +} +'''); + } +}
diff --git a/pkg/analysis_server/test/src/services/correction/fix/add_override_test.dart b/pkg/analysis_server/test/src/services/correction/fix/add_override_test.dart new file mode 100644 index 0000000..8a1cf11 --- /dev/null +++ b/pkg/analysis_server/test/src/services/correction/fix/add_override_test.dart
@@ -0,0 +1,179 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:analysis_server/src/services/correction/fix.dart'; +import 'package:analysis_server/src/services/correction/fix_internal.dart'; +import 'package:analyzer_plugin/utilities/fixes/fixes.dart'; +import 'package:test_reflective_loader/test_reflective_loader.dart'; + +import 'fix_processor.dart'; + +main() { + defineReflectiveSuite(() { + defineReflectiveTests(AddOverrideTest); + }); +} + +@reflectiveTest +class AddOverrideTest extends FixProcessorLintTest { + @override + FixKind get kind => DartFixKind.ADD_OVERRIDE; + + @override + String get lintCode => LintNames.annotate_overrides; + + test_field() async { + await resolveTestUnit(''' +class abstract Test { + int get t; +} +class Sub extends Test { + int /*LINT*/t = 42; +} +'''); + await assertHasFix(''' +class abstract Test { + int get t; +} +class Sub extends Test { + @override + int /*LINT*/t = 42; +} +'''); + } + + test_getter() async { + await resolveTestUnit(''' +class Test { + int get t => null; +} +class Sub extends Test { + int get /*LINT*/t => null; +} +'''); + await assertHasFix(''' +class Test { + int get t => null; +} +class Sub extends Test { + @override + int get /*LINT*/t => null; +} +'''); + } + + test_method() async { + await resolveTestUnit(''' +class Test { + void t() { } +} +class Sub extends Test { + void /*LINT*/t() { } +} +'''); + await assertHasFix(''' +class Test { + void t() { } +} +class Sub extends Test { + @override + void /*LINT*/t() { } +} +'''); + } + + test_method_with_doc_comment() async { + await resolveTestUnit(''' +class Test { + void t() { } +} +class Sub extends Test { + /// Doc comment. + void /*LINT*/t() { } +} +'''); + await assertHasFix(''' +class Test { + void t() { } +} +class Sub extends Test { + /// Doc comment. + @override + void /*LINT*/t() { } +} +'''); + } + + test_method_with_doc_comment_2() async { + await resolveTestUnit(''' +class Test { + void t() { } +} +class Sub extends Test { + /** + * Doc comment. + */ + void /*LINT*/t() { } +} +'''); + await assertHasFix(''' +class Test { + void t() { } +} +class Sub extends Test { + /** + * Doc comment. + */ + @override + void /*LINT*/t() { } +} +'''); + } + + test_method_with_doc_comment_and_metadata() async { + await resolveTestUnit(''' +class Test { + void t() { } +} +class Sub extends Test { + /// Doc comment. + @foo + void /*LINT*/t() { } +} +'''); + await assertHasFix(''' +class Test { + void t() { } +} +class Sub extends Test { + /// Doc comment. + @override + @foo + void /*LINT*/t() { } +} +'''); + } + + test_method_with_non_doc_comment() async { + await resolveTestUnit(''' +class Test { + void t() { } +} +class Sub extends Test { + // Non-doc comment. + void /*LINT*/t() { } +} +'''); + await assertHasFix(''' +class Test { + void t() { } +} +class Sub extends Test { + // Non-doc comment. + @override + void /*LINT*/t() { } +} +'''); + } +}
diff --git a/pkg/analysis_server/test/src/services/correction/fix/add_required_test.dart b/pkg/analysis_server/test/src/services/correction/fix/add_required_test.dart new file mode 100644 index 0000000..eae5d92 --- /dev/null +++ b/pkg/analysis_server/test/src/services/correction/fix/add_required_test.dart
@@ -0,0 +1,38 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:analysis_server/src/services/correction/fix.dart'; +import 'package:analysis_server/src/services/correction/fix_internal.dart'; +import 'package:analyzer_plugin/utilities/fixes/fixes.dart'; +import 'package:test_reflective_loader/test_reflective_loader.dart'; + +import 'fix_processor.dart'; + +main() { + defineReflectiveSuite(() { + defineReflectiveTests(AddRequiredTest); + }); +} + +@reflectiveTest +class AddRequiredTest extends FixProcessorLintTest { + @override + FixKind get kind => DartFixKind.ADD_REQUIRED; + + @override + String get lintCode => LintNames.always_require_non_null_named_parameters; + + test_withAssert() async { + await resolveTestUnit(''' +void function({String /*LINT*/param}) { + assert(param != null); +} +'''); + await assertHasFix(''' +void function({@required String /*LINT*/param}) { + assert(param != null); +} +'''); + } +}
diff --git a/pkg/analysis_server/test/src/services/correction/fix/add_static_test.dart b/pkg/analysis_server/test/src/services/correction/fix/add_static_test.dart new file mode 100644 index 0000000..bf136bd --- /dev/null +++ b/pkg/analysis_server/test/src/services/correction/fix/add_static_test.dart
@@ -0,0 +1,47 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:analysis_server/src/services/correction/fix.dart'; +import 'package:analyzer_plugin/utilities/fixes/fixes.dart'; +import 'package:test_reflective_loader/test_reflective_loader.dart'; + +import 'fix_processor.dart'; + +main() { + defineReflectiveSuite(() { + defineReflectiveTests(AddStaticTest); + }); +} + +@reflectiveTest +class AddStaticTest extends FixProcessorTest { + @override + FixKind get kind => DartFixKind.ADD_STATIC; + + test_multipleFields() async { + await resolveTestUnit(''' +class C { + const int x = 0, y = 0; +} +'''); + await assertHasFix(''' +class C { + static const int x = 0, y = 0; +} +'''); + } + + test_oneField() async { + await resolveTestUnit(''' +class C { + const int x = 0; +} +'''); + await assertHasFix(''' +class C { + static const int x = 0; +} +'''); + } +}
diff --git a/pkg/analysis_server/test/src/services/correction/fix/add_super_constructor_invocation_test.dart b/pkg/analysis_server/test/src/services/correction/fix/add_super_constructor_invocation_test.dart new file mode 100644 index 0000000..f6282cc --- /dev/null +++ b/pkg/analysis_server/test/src/services/correction/fix/add_super_constructor_invocation_test.dart
@@ -0,0 +1,111 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:analysis_server/src/services/correction/fix.dart'; +import 'package:analyzer_plugin/utilities/fixes/fixes.dart'; +import 'package:test_reflective_loader/test_reflective_loader.dart'; + +import 'fix_processor.dart'; + +main() { + defineReflectiveSuite(() { + defineReflectiveTests(AddSuperConstructorInvocationTest); + }); +} + +@reflectiveTest +class AddSuperConstructorInvocationTest extends FixProcessorTest { + @override + FixKind get kind => DartFixKind.ADD_SUPER_CONSTRUCTOR_INVOCATION; + + test_hasInitializers() async { + await resolveTestUnit(''' +class A { + A(int p); +} +class B extends A { + int field; + B() : field = 42 {} +} +'''); + await assertHasFix(''' +class A { + A(int p); +} +class B extends A { + int field; + B() : field = 42, super(0) {} +} +'''); + } + + test_named() async { + await resolveTestUnit(''' +class A { + A.named(int p); +} +class B extends A { + B() {} +} +'''); + await assertHasFix(''' +class A { + A.named(int p); +} +class B extends A { + B() : super.named(0) {} +} +'''); + } + + test_named_private() async { + await resolveTestUnit(''' +class A { + A._named(int p); +} +class B extends A { + B() {} +} +'''); + await assertNoFix(); + } + + test_requiredAndNamed() async { + await resolveTestUnit(''' +class A { + A(bool p1, int p2, double p3, String p4, {p5}); +} +class B extends A { + B() {} +} +'''); + await assertHasFix(''' +class A { + A(bool p1, int p2, double p3, String p4, {p5}); +} +class B extends A { + B() : super(false, 0, 0.0, '') {} +} +'''); + } + + test_typeArgument() async { + await resolveTestUnit(''' +class A<T> { + A(T p); +} +class B extends A<int> { + B(); +} +'''); + await assertHasFix(''' +class A<T> { + A(T p); +} +class B extends A<int> { + B() : super(0); +} +'''); + } +}
diff --git a/pkg/analysis_server/test/src/services/correction/fix/change_to_nearest_precise_value_test.dart b/pkg/analysis_server/test/src/services/correction/fix/change_to_nearest_precise_value_test.dart new file mode 100644 index 0000000..01c6749 --- /dev/null +++ b/pkg/analysis_server/test/src/services/correction/fix/change_to_nearest_precise_value_test.dart
@@ -0,0 +1,66 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:analysis_server/src/services/correction/fix.dart'; +import 'package:analyzer_plugin/utilities/fixes/fixes.dart'; +import 'package:test_reflective_loader/test_reflective_loader.dart'; + +import 'fix_processor.dart'; + +main() { + defineReflectiveSuite(() { + defineReflectiveTests(ChangeToNearestPreciseValueTest); + }); +} + +@reflectiveTest +class ChangeToNearestPreciseValueTest extends FixProcessorTest { + @override + FixKind get kind => DartFixKind.CHANGE_TO_NEAREST_PRECISE_VALUE; + + test_impreciseIntAsDouble() async { + await resolveTestUnit(''' +double x = 1000000000000000000000000; +'''); + await assertHasFix(''' +double x = 999999999999999983222784; +'''); + } + + test_impreciseIntAsDouble_asCapitalHex() async { + await resolveTestUnit(''' +double x = 0X1000000000000000000000001; +'''); + await assertHasFix(''' +double x = 0x1000000000000000000000000; +'''); + } + + test_impreciseIntAsDouble_asHex() async { + await resolveTestUnit(''' +double x = 0x1000000000000000000000001; +'''); + await assertHasFix(''' +double x = 0x1000000000000000000000000; +'''); + } + + test_impreciseIntAsDouble_maxValue() async { + await resolveTestUnit(''' +double x = 10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000; +'''); + await assertHasFix(''' +double x = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368; +'''); + } + + test_impreciseIntAsDouble_maxValue_asHex() async { + await resolveTestUnit(''' +double x = 0x100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000; +'''); + await assertHasFix(''' +double x = 0xFFFFFFFFFFFFF800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000; +'''); + } +}
diff --git a/pkg/analysis_server/test/src/services/correction/fix/change_to_static_access_test.dart b/pkg/analysis_server/test/src/services/correction/fix/change_to_static_access_test.dart new file mode 100644 index 0000000..507b291 --- /dev/null +++ b/pkg/analysis_server/test/src/services/correction/fix/change_to_static_access_test.dart
@@ -0,0 +1,130 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:analysis_server/src/services/correction/fix.dart'; +import 'package:analyzer_plugin/utilities/fixes/fixes.dart'; +import 'package:test_reflective_loader/test_reflective_loader.dart'; + +import 'fix_processor.dart'; + +main() { + defineReflectiveSuite(() { + defineReflectiveTests(ChangeToStaticAccessTest); + }); +} + +@reflectiveTest +class ChangeToStaticAccessTest extends FixProcessorTest { + @override + FixKind get kind => DartFixKind.CHANGE_TO_STATIC_ACCESS; + + test_method() async { + await resolveTestUnit(''' +class A { + static foo() {} +} +main(A a) { + a.foo(); +} +'''); + await assertHasFix(''' +class A { + static foo() {} +} +main(A a) { + A.foo(); +} +'''); + } + + test_method_importType() async { + addSource('/home/test/lib/a.dart', r''' +class A { + static foo() {} +} +'''); + addSource('/home/test/lib/b.dart', r''' +import 'package:test/a.dart'; + +class B extends A {} +'''); + await resolveTestUnit(''' +import 'package:test/b.dart'; + +main(B b) { + b.foo(); +} +'''); + await assertHasFix(''' +import 'package:test/a.dart'; +import 'package:test/b.dart'; + +main(B b) { + A.foo(); +} +'''); + } + + test_method_prefixLibrary() async { + await resolveTestUnit(''' +import 'dart:async' as pref; +main(pref.Future f) { + f.wait([]); +} +'''); + await assertHasFix(''' +import 'dart:async' as pref; +main(pref.Future f) { + pref.Future.wait([]); +} +'''); + } + + test_property() async { + await resolveTestUnit(''' +class A { + static get foo => 42; +} +main(A a) { + a.foo; +} +'''); + await assertHasFix(''' +class A { + static get foo => 42; +} +main(A a) { + A.foo; +} +'''); + } + + test_property_importType() async { + addSource('/home/test/lib/a.dart', r''' +class A { + static get foo => null; +} +'''); + addSource('/home/test/lib/b.dart', r''' +import 'package:test/a.dart'; + +class B extends A {} +'''); + await resolveTestUnit(''' +import 'package:test/b.dart'; + +main(B b) { + b.foo; +} +'''); + await assertHasFix(''' +import 'package:test/a.dart'; +import 'package:test/b.dart'; + +main(B b) { + A.foo; +} +'''); + } +}
diff --git a/pkg/analysis_server/test/src/services/correction/fix/change_to_test.dart b/pkg/analysis_server/test/src/services/correction/fix/change_to_test.dart new file mode 100644 index 0000000..553d1e5 --- /dev/null +++ b/pkg/analysis_server/test/src/services/correction/fix/change_to_test.dart
@@ -0,0 +1,332 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:analysis_server/src/services/correction/fix.dart'; +import 'package:analyzer_plugin/utilities/fixes/fixes.dart'; +import 'package:test_reflective_loader/test_reflective_loader.dart'; + +import 'fix_processor.dart'; + +main() { + defineReflectiveSuite(() { + defineReflectiveTests(ChangeToTest); + }); +} + +@reflectiveTest +class ChangeToTest extends FixProcessorTest { + @override + FixKind get kind => DartFixKind.CHANGE_TO; + + test_undefinedClass_fromImport() async { + await resolveTestUnit(''' +main() { + Stirng s = 'abc'; + print(s); +} +'''); + await assertHasFix(''' +main() { + String s = 'abc'; + print(s); +} +'''); + } + + test_undefinedClass_fromThisLibrary() async { + await resolveTestUnit(''' +class MyClass {} +main() { + MyCalss v = null; + print(v); +} +'''); + await assertHasFix(''' +class MyClass {} +main() { + MyClass v = null; + print(v); +} +'''); + } + + test_undefinedClass_prefixed() async { + await resolveTestUnit(''' +import 'dart:async' as c; +main() { + c.Fture v = null; + print(v); +} +'''); + await assertHasFix(''' +import 'dart:async' as c; +main() { + c.Future v = null; + print(v); +} +'''); + } + + test_undefinedFunction_fromImport() async { + await resolveTestUnit(''' +main() { + pritn(0); +} +'''); + await assertHasFix(''' +main() { + print(0); +} +'''); + } + + test_undefinedFunction_prefixed_fromImport() async { + await resolveTestUnit(''' +import 'dart:core' as c; +main() { + c.prnt(42); +} +'''); + await assertHasFix(''' +import 'dart:core' as c; +main() { + c.print(42); +} +'''); + } + + test_undefinedFunction_prefixed_ignoreLocal() async { + await resolveTestUnit(''' +import 'dart:async' as c; +main() { + c.main(); +} +'''); + await assertNoFix(); + } + + test_undefinedFunction_thisLibrary() async { + await resolveTestUnit(''' +myFunction() {} +main() { + myFuntcion(); +} +'''); + await assertHasFix(''' +myFunction() {} +main() { + myFunction(); +} +'''); + } + + test_undefinedGetter_hint() async { + await resolveTestUnit(''' +class A { + int myField; +} +main(A a) { + var x = a; + print(x.myFild); +} +'''); + await assertHasFix(''' +class A { + int myField; +} +main(A a) { + var x = a; + print(x.myField); +} +'''); + } + + test_undefinedGetter_qualified() async { + await resolveTestUnit(''' +class A { + int myField; +} +main(A a) { + print(a.myFild); +} +'''); + await assertHasFix(''' +class A { + int myField; +} +main(A a) { + print(a.myField); +} +'''); + } + + test_undefinedGetter_qualified_static() async { + await resolveTestUnit(''' +class A { + static int MY_NAME = 1; +} +main() { + A.MY_NAM; +} +'''); + await assertHasFix(''' +class A { + static int MY_NAME = 1; +} +main() { + A.MY_NAME; +} +'''); + } + + test_undefinedGetter_unqualified() async { + await resolveTestUnit(''' +class A { + int myField; + main() { + print(myFild); + } +} +'''); + await assertHasFix(''' +class A { + int myField; + main() { + print(myField); + } +} +'''); + } + + test_undefinedMethod_ignoreOperators() async { + await resolveTestUnit(''' +main(Object object) { + object.then(); +} +'''); + await assertNoFix(); + } + + test_undefinedMethod_qualified() async { + await resolveTestUnit(''' +class A { + myMethod() {} +} +main() { + A a = new A(); + a.myMehtod(); +} +'''); + await assertHasFix(''' +class A { + myMethod() {} +} +main() { + A a = new A(); + a.myMethod(); +} +'''); + } + + test_undefinedMethod_unqualified_superClass() async { + await resolveTestUnit(''' +class A { + myMethod() {} +} +class B extends A { + main() { + myMehtod(); + } +} +'''); + await assertHasFix(''' +class A { + myMethod() {} +} +class B extends A { + main() { + myMethod(); + } +} +'''); + } + + test_undefinedMethod_unqualified_thisClass() async { + await resolveTestUnit(''' +class A { + myMethod() {} + main() { + myMehtod(); + } +} +'''); + await assertHasFix(''' +class A { + myMethod() {} + main() { + myMethod(); + } +} +'''); + } + + test_undefinedSetter_hint() async { + await resolveTestUnit(''' +class A { + int myField; +} +main(A a) { + var x = a; + x.myFild = 42; +} +'''); + await assertHasFix(''' +class A { + int myField; +} +main(A a) { + var x = a; + x.myField = 42; +} +'''); + } + + test_undefinedSetter_qualified() async { + await resolveTestUnit(''' +class A { + int myField; +} +main(A a) { + a.myFild = 42; +} +'''); + await assertHasFix(''' +class A { + int myField; +} +main(A a) { + a.myField = 42; +} +'''); + } + + test_undefinedSetter_unqualified() async { + await resolveTestUnit(''' +class A { + int myField; + main() { + myFild = 42; + } +} +'''); + await assertHasFix(''' +class A { + int myField; + main() { + myField = 42; + } +} +'''); + } +}
diff --git a/pkg/analysis_server/test/src/services/correction/fix/change_type_annotation_test.dart b/pkg/analysis_server/test/src/services/correction/fix/change_type_annotation_test.dart new file mode 100644 index 0000000..8fbb66a --- /dev/null +++ b/pkg/analysis_server/test/src/services/correction/fix/change_type_annotation_test.dart
@@ -0,0 +1,72 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:analysis_server/src/services/correction/fix.dart'; +import 'package:analyzer_plugin/utilities/fixes/fixes.dart'; +import 'package:test_reflective_loader/test_reflective_loader.dart'; + +import 'fix_processor.dart'; + +main() { + defineReflectiveSuite(() { + defineReflectiveTests(ChangeTypeAnnotationTest); + }); +} + +@reflectiveTest +class ChangeTypeAnnotationTest extends FixProcessorTest { + @override + FixKind get kind => DartFixKind.CHANGE_TYPE_ANNOTATION; + + test_generic() async { + await resolveTestUnit(''' +main() { + String v = <int>[]; + print(v); +} +'''); + await assertHasFix(''' +main() { + List<int> v = <int>[]; + print(v); +} +'''); + } + + test_multipleVariables() async { + await resolveTestUnit(''' +main() { + String a, b = 42; + print('\$a \$b'); +} +'''); + await assertNoFix(); + } + + test_notVariableDeclaration() async { + await resolveTestUnit(''' +main() { + String v; + v = 42; + print(v); +} +'''); + await assertNoFix(); + } + + test_simple() async { + await resolveTestUnit(''' +main() { + String v = 'abc'.length; + print(v); +} +'''); + await assertHasFix(''' +main() { + int v = 'abc'.length; + print(v); +} +'''); + } +}
diff --git a/pkg/analysis_server/test/src/services/correction/fix/convert_flutter_child_test.dart b/pkg/analysis_server/test/src/services/correction/fix/convert_flutter_child_test.dart new file mode 100644 index 0000000..e75321d --- /dev/null +++ b/pkg/analysis_server/test/src/services/correction/fix/convert_flutter_child_test.dart
@@ -0,0 +1,153 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:analysis_server/src/services/correction/fix.dart'; +import 'package:analyzer_plugin/utilities/fixes/fixes.dart'; +import 'package:test_reflective_loader/test_reflective_loader.dart'; + +import 'fix_processor.dart'; + +main() { + defineReflectiveSuite(() { + defineReflectiveTests(ConvertFlutterChildTest); + }); +} + +@reflectiveTest +class ConvertFlutterChildTest extends FixProcessorTest { + @override + FixKind get kind => DartFixKind.CONVERT_FLUTTER_CHILD; + + test_hasList() async { + addFlutterPackage(); + await resolveTestUnit(''' +import 'package:flutter/widgets.dart'; +build() { + return new Container( + child: new Row( + child: [ + new Text('111'), + new Text('222'), + ], + ), + ); +} +'''); + await assertHasFix(''' +import 'package:flutter/widgets.dart'; +build() { + return new Container( + child: new Row( + children: <Widget>[ + new Text('111'), + new Text('222'), + ], + ), + ); +} +'''); + } + + test_hasTypedList() async { + addFlutterPackage(); + await resolveTestUnit(''' +import 'package:flutter/widgets.dart'; +build() { + return new Container( + child: new Row( + child: <Widget>[ + new Text('111'), + new Text('222'), + ], + ), + ); +} +'''); + await assertHasFix(''' +import 'package:flutter/widgets.dart'; +build() { + return new Container( + child: new Row( + children: <Widget>[ + new Text('111'), + new Text('222'), + ], + ), + ); +} +'''); + } + + test_listNotWidget() async { + addFlutterPackage(); + await resolveTestUnit(''' +import 'package:flutter/widgets.dart'; +build() { + return new Container( + child: new Row( + child: <Widget>[ + new Container(), + null, + ], + ), + ); +} +'''); + await assertNoFix(); + } + + test_multiLine() async { + addFlutterPackage(); + await resolveTestUnit(''' +import 'package:flutter/material.dart'; +build() { + return new Scaffold( + body: new Row( + child: new Container( + width: 200.0, + height: 300.0, + ), + ), + ); +} +'''); + await assertHasFix(''' +import 'package:flutter/material.dart'; +build() { + return new Scaffold( + body: new Row( + children: <Widget>[ + new Container( + width: 200.0, + height: 300.0, + ), + ], + ), + ); +} +'''); + } + + test_widgetVariable() async { + addFlutterPackage(); + await resolveTestUnit(''' +import 'package:flutter/material.dart'; +build() { + var text = new Text('foo'); + new Row( + child: text, + ); +} +'''); + await assertHasFix(''' +import 'package:flutter/material.dart'; +build() { + var text = new Text('foo'); + new Row( + children: <Widget>[text], + ); +} +'''); + } +}
diff --git a/pkg/analysis_server/test/src/services/correction/fix/convert_flutter_children_test.dart b/pkg/analysis_server/test/src/services/correction/fix/convert_flutter_children_test.dart new file mode 100644 index 0000000..f975f0a --- /dev/null +++ b/pkg/analysis_server/test/src/services/correction/fix/convert_flutter_children_test.dart
@@ -0,0 +1,108 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:analysis_server/src/services/correction/fix.dart'; +import 'package:analyzer_plugin/utilities/fixes/fixes.dart'; +import 'package:test_reflective_loader/test_reflective_loader.dart'; + +import 'fix_processor.dart'; + +main() { + defineReflectiveSuite(() { + defineReflectiveTests(ConvertFlutterChildrenTest); + }); +} + +@reflectiveTest +class ConvertFlutterChildrenTest extends FixProcessorTest { + @override + FixKind get kind => DartFixKind.CONVERT_FLUTTER_CHILDREN; + + test_undefinedParameter_multiLine() async { + addFlutterPackage(); + await resolveTestUnit(''' +import 'package:flutter/widgets.dart'; +build() { + return new Center( + children: [ + new Container( + width: 200.0, + height: 300.0, + ), + ], + ); +} +'''); + await assertHasFix(''' +import 'package:flutter/widgets.dart'; +build() { + return new Center( + child: new Container( + width: 200.0, + height: 300.0, + ), + ); +} +'''); + } + + test_undefinedParameter_notWidget() async { + addFlutterPackage(); + await resolveTestUnit(''' +import 'package:flutter/widgets.dart'; +build() { + return new Center( + children: [ + new Object(), + ], + ); +} +'''); + await assertNoFix(); + } + + test_undefinedParameter_singleLine() async { + addFlutterPackage(); + await resolveTestUnit(''' +import 'package:flutter/widgets.dart'; +build() { + return new Center( + children: [ + new Text('foo'), + ], + ); +} +'''); + await assertHasFix(''' +import 'package:flutter/widgets.dart'; +build() { + return new Center( + child: new Text('foo'), + ); +} +'''); + } + + test_undefinedParameter_singleLine2() async { + addFlutterPackage(); + await resolveTestUnit(''' +import 'package:flutter/widgets.dart'; +build() { + var text = new Text('foo'); + new Center( + children: [text], + ); +} +'''); + await assertHasFix(''' +import 'package:flutter/widgets.dart'; +build() { + var text = new Text('foo'); + new Center( + child: text, + ); +} +'''); + } +}
diff --git a/pkg/analysis_server/test/src/services/correction/fix/convert_to_named_arguments_test.dart b/pkg/analysis_server/test/src/services/correction/fix/convert_to_named_arguments_test.dart new file mode 100644 index 0000000..de9c388 --- /dev/null +++ b/pkg/analysis_server/test/src/services/correction/fix/convert_to_named_arguments_test.dart
@@ -0,0 +1,110 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:analysis_server/src/services/correction/fix.dart'; +import 'package:analyzer_plugin/utilities/fixes/fixes.dart'; +import 'package:test_reflective_loader/test_reflective_loader.dart'; + +import 'fix_processor.dart'; + +main() { + defineReflectiveSuite(() { + defineReflectiveTests(ConvertToNamedArgumentsTest); + }); +} + +@reflectiveTest +class ConvertToNamedArgumentsTest extends FixProcessorTest { + @override + FixKind get kind => DartFixKind.CONVERT_TO_NAMED_ARGUMENTS; + + test_ambiguous() async { + await resolveTestUnit(''' +class A { + A({int a, int b}); +} + +main() { + new A(1, 2); +} +'''); + await assertNoFix(); + } + + test_instanceCreation() async { + await resolveTestUnit(''' +class A { + A({int a, double b}); +} + +main() { + new A(1.2, 3); +} +'''); + await assertHasFix(''' +class A { + A({int a, double b}); +} + +main() { + new A(b: 1.2, a: 3); +} +'''); + } + + test_instanceCreation_hasPositional() async { + await resolveTestUnit(''' +class A { + A(int a, {int b}); +} + +main() { + new A(1, 2); +} +'''); + await assertHasFix(''' +class A { + A(int a, {int b}); +} + +main() { + new A(1, b: 2); +} +'''); + } + + test_methodInvocation() async { + await resolveTestUnit(''' +class C { + void foo({int a}) {} +} + +main(C c) { + c.foo(1); +} +'''); + await assertHasFix(''' +class C { + void foo({int a}) {} +} + +main(C c) { + c.foo(a: 1); +} +'''); + } + + test_noCompatibleParameter() async { + await resolveTestUnit(''' +class A { + A({String a}); +} + +main() { + new A(1); +} +'''); + await assertNoFix(); + } +}
diff --git a/pkg/analysis_server/test/src/services/correction/fix/create_class_test.dart b/pkg/analysis_server/test/src/services/correction/fix/create_class_test.dart new file mode 100644 index 0000000..610c742 --- /dev/null +++ b/pkg/analysis_server/test/src/services/correction/fix/create_class_test.dart
@@ -0,0 +1,181 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:analysis_server/src/services/correction/fix.dart'; +import 'package:analyzer/src/error/codes.dart'; +import 'package:analyzer_plugin/utilities/fixes/fixes.dart'; +import 'package:test/test.dart'; +import 'package:test_reflective_loader/test_reflective_loader.dart'; + +import 'fix_processor.dart'; + +main() { + defineReflectiveSuite(() { + defineReflectiveTests(CreateClassTest); + }); +} + +@reflectiveTest +class CreateClassTest extends FixProcessorTest { + @override + FixKind get kind => DartFixKind.CREATE_CLASS; + + test_hasUnresolvedPrefix() async { + await resolveTestUnit(''' +main() { + prefix.Test v = null; + print(v); +} +'''); + await assertNoFix(); + } + + test_inLibraryOfPrefix() async { + addSource('/home/test/lib/lib.dart', r''' +class A {} +'''); + + await resolveTestUnit(''' +import 'lib.dart' as lib; + +main() { + lib.A a = null; + lib.Test t = null; + print('\$a \$t'); +} +'''); + + await assertHasFix(''' +class A {} + +class Test { +} +''', target: '/home/test/lib/lib.dart'); + expect(change.linkedEditGroups, hasLength(1)); + } + + test_innerLocalFunction() async { + await resolveTestUnit(''' +f() { + g() { + Test v = null; + print(v); + } + g(); +} +'''); + await assertHasFix(''' +f() { + g() { + Test v = null; + print(v); + } + g(); +} + +class Test { +} +'''); + assertLinkedGroup(change.linkedEditGroups[0], ['Test v =', 'Test {']); + } + + test_instanceCreation_withoutNew_fromFunction() async { + await resolveTestUnit(''' +main() { + Test (); +} +'''); + await assertHasFix(''' +main() { + Test (); +} + +class Test { +} +'''); + assertLinkedGroup(change.linkedEditGroups[0], ['Test ()', 'Test {']); + } + + test_instanceCreation_withoutNew_fromMethod() async { + await resolveTestUnit(''' +class A { + main() { + Test (); + } +} +'''); + await assertHasFix(''' +class A { + main() { + Test (); + } +} + +class Test { +} +'''); + assertLinkedGroup(change.linkedEditGroups[0], ['Test ()', 'Test {']); + } + + test_itemOfList() async { + await resolveTestUnit(''' +main() { + var a = [Test]; + print(a); +} +'''); + await assertHasFix(''' +main() { + var a = [Test]; + print(a); +} + +class Test { +} +'''); + assertLinkedGroup(change.linkedEditGroups[0], ['Test];', 'Test {']); + } + + test_itemOfList_inAnnotation() async { + await resolveTestUnit(''' +class MyAnnotation { + const MyAnnotation(a, b); +} +@MyAnnotation(int, const [Test]) +main() {} +'''); + await assertHasFix(''' +class MyAnnotation { + const MyAnnotation(a, b); +} +@MyAnnotation(int, const [Test]) +main() {} + +class Test { +} +''', errorFilter: (error) { + return error.errorCode == StaticWarningCode.UNDEFINED_IDENTIFIER; + }); + assertLinkedGroup(change.linkedEditGroups[0], ['Test])', 'Test {']); + } + + test_simple() async { + await resolveTestUnit(''' +main() { + Test v = null; + print(v); +} +'''); + await assertHasFix(''' +main() { + Test v = null; + print(v); +} + +class Test { +} +'''); + assertLinkedGroup(change.linkedEditGroups[0], ['Test v =', 'Test {']); + } +}
diff --git a/pkg/analysis_server/test/src/services/correction/fix/create_constructor_for_final_fields_test.dart b/pkg/analysis_server/test/src/services/correction/fix/create_constructor_for_final_fields_test.dart new file mode 100644 index 0000000..fa355b6 --- /dev/null +++ b/pkg/analysis_server/test/src/services/correction/fix/create_constructor_for_final_fields_test.dart
@@ -0,0 +1,137 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:analysis_server/src/services/correction/fix.dart'; +import 'package:analyzer_plugin/utilities/fixes/fixes.dart'; +import 'package:test_reflective_loader/test_reflective_loader.dart'; + +import 'fix_processor.dart'; + +main() { + defineReflectiveSuite(() { + defineReflectiveTests(CreateConstructorForFinalFieldsTest); + }); +} + +@reflectiveTest +class CreateConstructorForFinalFieldsTest extends FixProcessorTest { + @override + FixKind get kind => DartFixKind.CREATE_CONSTRUCTOR_FOR_FINAL_FIELDS; + + test_flutter() async { + addFlutterPackage(); + await resolveTestUnit(''' +import 'package:flutter/widgets.dart'; + +class MyWidget extends StatelessWidget { + final int a; + final int b = 2; + final int c; +} +'''); + await assertHasFix(''' +import 'package:flutter/widgets.dart'; + +class MyWidget extends StatelessWidget { + final int a; + final int b = 2; + final int c; + + const MyWidget({Key key, this.a, this.c}) : super(key: key); +} +''', errorFilter: (error) { + return error.message.contains("'a'"); + }); + } + + test_flutter_childLast() async { + addFlutterPackage(); + await resolveTestUnit(''' +import 'package:flutter/widgets.dart'; + +class MyWidget extends StatelessWidget { + final int a; + final Widget child; + final int b; +} +'''); + await assertHasFix(''' +import 'package:flutter/widgets.dart'; + +class MyWidget extends StatelessWidget { + final int a; + final Widget child; + final int b; + + const MyWidget({Key key, this.a, this.b, this.child}) : super(key: key); +} +''', errorFilter: (error) { + return error.message.contains("'a'"); + }); + } + + test_flutter_childrenLast() async { + addFlutterPackage(); + await resolveTestUnit(''' +import 'package:flutter/widgets.dart'; + +class MyWidget extends StatelessWidget { + final int a; + final List<Widget> children; + final int b; +} +'''); + await assertHasFix(''' +import 'package:flutter/widgets.dart'; + +class MyWidget extends StatelessWidget { + final int a; + final List<Widget> children; + final int b; + + const MyWidget({Key key, this.a, this.b, this.children}) : super(key: key); +} +''', errorFilter: (error) { + return error.message.contains("'a'"); + }); + } + + test_inTopLevelMethod() async { + await resolveTestUnit(''' +main() { + final int v; + print(v); +} +'''); + await assertNoFix(); + } + + test_simple() async { + await resolveTestUnit(''' +class Test { + final int a; + final int b = 2; + final int c; +} +'''); + await assertHasFix(''' +class Test { + final int a; + final int b = 2; + final int c; + + Test(this.a, this.c); +} +''', errorFilter: (error) { + return error.message.contains("'a'"); + }); + } + + test_topLevelField() async { + await resolveTestUnit(''' +final int v; +'''); + await assertNoFix(); + } +}
diff --git a/pkg/analysis_server/test/src/services/correction/fix/create_constructor_super_test.dart b/pkg/analysis_server/test/src/services/correction/fix/create_constructor_super_test.dart new file mode 100644 index 0000000..fe59b94 --- /dev/null +++ b/pkg/analysis_server/test/src/services/correction/fix/create_constructor_super_test.dart
@@ -0,0 +1,156 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:analysis_server/src/services/correction/fix.dart'; +import 'package:analyzer_plugin/utilities/fixes/fixes.dart'; +import 'package:test_reflective_loader/test_reflective_loader.dart'; + +import 'fix_processor.dart'; + +main() { + defineReflectiveSuite(() { + defineReflectiveTests(CreateConstructorSuperTest); + }); +} + +@reflectiveTest +class CreateConstructorSuperTest extends FixProcessorTest { + @override + FixKind get kind => DartFixKind.CREATE_CONSTRUCTOR_SUPER; + + test_fieldInitializer() async { + await resolveTestUnit(''' +class A { + int _field; + A(this._field); + int get field => _field; +} +class B extends A { + int existingField; + + void existingMethod() {} +} +'''); + await assertHasFix(''' +class A { + int _field; + A(this._field); + int get field => _field; +} +class B extends A { + int existingField; + + B(int field) : super(field); + + void existingMethod() {} +} +'''); + } + + test_importType() async { + addSource('/home/test/lib/a.dart', r''' +class A {} +'''); + addSource('/home/test/lib/b.dart', r''' +import 'package:test/a.dart'; + +class B { + B(A a); +} +'''); + await resolveTestUnit(''' +import 'package:test/b.dart'; + +class C extends B { +} +'''); + await assertHasFix(''' +import 'package:test/a.dart'; +import 'package:test/b.dart'; + +class C extends B { + C(A a) : super(a); +} +'''); + } + + test_named() async { + await resolveTestUnit(''' +class A { + A.named(p1, int p2); +} +class B extends A { + int existingField; + + void existingMethod() {} +} +'''); + await assertHasFix(''' +class A { + A.named(p1, int p2); +} +class B extends A { + int existingField; + + B.named(p1, int p2) : super.named(p1, p2); + + void existingMethod() {} +} +'''); + } + + test_optional() async { + await resolveTestUnit(''' +class A { + A(p1, int p2, List<String> p3, [int p4]); +} +class B extends A { + int existingField; + + void existingMethod() {} +} +'''); + await assertHasFix(''' +class A { + A(p1, int p2, List<String> p3, [int p4]); +} +class B extends A { + int existingField; + + B(p1, int p2, List<String> p3) : super(p1, p2, p3); + + void existingMethod() {} +} +'''); + } + + test_private() async { + await resolveTestUnit(''' +class A { + A._named(p); +} +class B extends A { +} +'''); + await assertNoFix(); + } + + test_typeArgument() async { + await resolveTestUnit(''' +class C<T> { + final T x; + C(this.x); +} +class D extends C<int> { +}'''); + await assertHasFix(''' +class C<T> { + final T x; + C(this.x); +} +class D extends C<int> { + D(int x) : super(x); +}'''); + } +}
diff --git a/pkg/analysis_server/test/src/services/correction/fix/create_constructor_test.dart b/pkg/analysis_server/test/src/services/correction/fix/create_constructor_test.dart new file mode 100644 index 0000000..d5e8dd5 --- /dev/null +++ b/pkg/analysis_server/test/src/services/correction/fix/create_constructor_test.dart
@@ -0,0 +1,104 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:analysis_server/src/services/correction/fix.dart'; +import 'package:analyzer_plugin/utilities/fixes/fixes.dart'; +import 'package:test_reflective_loader/test_reflective_loader.dart'; + +import 'fix_processor.dart'; + +main() { + defineReflectiveSuite(() { + defineReflectiveTests(CreateConstructorTest); + defineReflectiveTests(CreateConstructorMixinTest); + }); +} + +@reflectiveTest +class CreateConstructorMixinTest extends FixProcessorTest { + @override + FixKind get kind => DartFixKind.CREATE_CONSTRUCTOR; + + test_named() async { + await resolveTestUnit(''' +mixin M {} + +main() { + new M.named(); +} +'''); + await assertNoFix(); + } +} + +@reflectiveTest +class CreateConstructorTest extends FixProcessorTest { + @override + FixKind get kind => DartFixKind.CREATE_CONSTRUCTOR; + + test_insteadOfSyntheticDefault() async { + await resolveTestUnit(''' +class A { + int field; + + method() {} +} +main() { + new A(1, 2.0); +} +'''); + await assertHasFix(''' +class A { + int field; + + A(int i, double d); + + method() {} +} +main() { + new A(1, 2.0); +} +'''); + } + + test_named() async { + await resolveTestUnit(''' +class A { + method() {} +} +main() { + new A.named(1, 2.0); +} +'''); + await assertHasFix(''' +class A { + A.named(int i, double d); + + method() {} +} +main() { + new A.named(1, 2.0); +} +'''); + assertLinkedGroup(change.linkedEditGroups[0], ['named(int ', 'named(1']); + } + + test_named_emptyClassBody() async { + await resolveTestUnit(''' +class A {} +main() { + new A.named(1); +} +'''); + await assertHasFix(''' +class A { + A.named(int i); +} +main() { + new A.named(1); +} +'''); + assertLinkedGroup(change.linkedEditGroups[0], ['named(int ', 'named(1']); + } +}
diff --git a/pkg/analysis_server/test/src/services/correction/fix/create_field_test.dart b/pkg/analysis_server/test/src/services/correction/fix/create_field_test.dart new file mode 100644 index 0000000..ed3eee0 --- /dev/null +++ b/pkg/analysis_server/test/src/services/correction/fix/create_field_test.dart
@@ -0,0 +1,555 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:analysis_server/src/services/correction/fix.dart'; +import 'package:analyzer_plugin/utilities/fixes/fixes.dart'; +import 'package:test_reflective_loader/test_reflective_loader.dart'; + +import 'fix_processor.dart'; + +main() { + defineReflectiveSuite(() { + defineReflectiveTests(CreateFieldTest); + defineReflectiveTests(CreateFieldMixinTest); + }); +} + +@reflectiveTest +class CreateFieldMixinTest extends FixProcessorTest { + @override + FixKind get kind => DartFixKind.CREATE_FIELD; + + test_getter_qualified_instance() async { + await resolveTestUnit(''' +mixin M { +} + +main(M m) { + int v = m.test; + print(v); +} +'''); + await assertHasFix(''' +mixin M { + int test; +} + +main(M m) { + int v = m.test; + print(v); +} +'''); + } + + test_setter_qualified_instance_hasField() async { + await resolveTestUnit(''' +mixin M { + int aaa; + int zzz; + + existingMethod() {} +} + +main(M m) { + m.test = 5; +} +'''); + await assertHasFix(''' +mixin M { + int aaa; + int zzz; + + int test; + + existingMethod() {} +} + +main(M m) { + m.test = 5; +} +'''); + } +} + +@reflectiveTest +class CreateFieldTest extends FixProcessorTest { + @override + FixKind get kind => DartFixKind.CREATE_FIELD; + + test_getter_multiLevel() async { + await resolveTestUnit(''' +class A { +} +class B { + A a; +} +class C { + B b; +} +main(C c) { + int v = c.b.a.test; + print(v); +} +'''); + await assertHasFix(''' +class A { + int test; +} +class B { + A a; +} +class C { + B b; +} +main(C c) { + int v = c.b.a.test; + print(v); +} +'''); + } + + test_getter_qualified_instance() async { + await resolveTestUnit(''' +class A { +} +main(A a) { + int v = a.test; + print(v); +} +'''); + await assertHasFix(''' +class A { + int test; +} +main(A a) { + int v = a.test; + print(v); +} +'''); + } + + test_getter_qualified_instance_differentLibrary() async { + addSource('/home/test/lib/other.dart', ''' +/** + * A comment to push the offset of the braces for the following class + * declaration past the end of the content of the test file. Used to catch an + * index out of bounds exception that occurs when using the test source instead + * of the target source to compute the location at which to insert the field. + */ +class A { +} +'''); + + await resolveTestUnit(''' +import 'package:test/other.dart'; + +main(A a) { + int v = a.test; + print(v); +} +'''); + + await assertHasFix(''' +/** + * A comment to push the offset of the braces for the following class + * declaration past the end of the content of the test file. Used to catch an + * index out of bounds exception that occurs when using the test source instead + * of the target source to compute the location at which to insert the field. + */ +class A { + int test; +} +''', target: '/home/test/lib/other.dart'); + } + + test_getter_qualified_instance_dynamicType() async { + await resolveTestUnit(''' +class A { + B b; + void f(Object p) { + p == b.test; + } +} +class B { +} +'''); + await assertHasFix(''' +class A { + B b; + void f(Object p) { + p == b.test; + } +} +class B { + var test; +} +'''); + } + + test_getter_qualified_propagatedType() async { + await resolveTestUnit(''' +class A { + A get self => this; +} +main() { + var a = new A(); + int v = a.self.test; + print(v); +} +'''); + await assertHasFix(''' +class A { + int test; + + A get self => this; +} +main() { + var a = new A(); + int v = a.self.test; + print(v); +} +'''); + } + + test_getter_unqualified_instance_asInvocationArgument() async { + await resolveTestUnit(''' +class A { + main() { + f(test); + } +} +f(String s) {} +'''); + await assertHasFix(''' +class A { + String test; + + main() { + f(test); + } +} +f(String s) {} +'''); + } + + test_getter_unqualified_instance_assignmentRhs() async { + await resolveTestUnit(''' +class A { + main() { + int v = test; + print(v); + } +} +'''); + await assertHasFix(''' +class A { + int test; + + main() { + int v = test; + print(v); + } +} +'''); + } + + test_getter_unqualified_instance_asStatement() async { + await resolveTestUnit(''' +class A { + main() { + test; + } +} +'''); + await assertHasFix(''' +class A { + var test; + + main() { + test; + } +} +'''); + } + + test_hint() async { + await resolveTestUnit(''' +class A { +} +main(A a) { + var x = a; + int v = x.test; + print(v); +} +'''); + await assertHasFix(''' +class A { + int test; +} +main(A a) { + var x = a; + int v = x.test; + print(v); +} +'''); + } + + test_hint_setter() async { + await resolveTestUnit(''' +class A { +} +main(A a) { + var x = a; + x.test = 0; +} +'''); + await assertHasFix(''' +class A { + int test; +} +main(A a) { + var x = a; + x.test = 0; +} +'''); + } + + test_importType() async { + addSource('/home/test/lib/a.dart', r''' +class A {} +'''); + + addSource('/home/test/lib/b.dart', r''' +import 'package:test/a.dart'; + +A getA() => null; +'''); + + await resolveTestUnit(''' +import 'package:test/b.dart'; + +class C { +} + +main(C c) { + c.test = getA(); +} +'''); + + await assertHasFix(''' +import 'package:test/a.dart'; +import 'package:test/b.dart'; + +class C { + A test; +} + +main(C c) { + c.test = getA(); +} +'''); + } + + test_inEnum() async { + await resolveTestUnit(''' +enum MyEnum { + AAA, BBB +} +main() { + MyEnum.foo; +} +'''); + await assertNoFix(); + } + + test_inSDK() async { + await resolveTestUnit(''' +main(List p) { + p.foo = 1; +} +'''); + await assertNoFix(); + } + + test_invalidInitializer_withoutType() async { + await resolveTestUnit(''' +class C { + C(this.text); +} +'''); + await assertHasFix(''' +class C { + var text; + + C(this.text); +} +'''); + } + + test_invalidInitializer_withType() async { + await resolveTestUnit(''' +class C { + C(String this.text); +} +'''); + await assertHasFix(''' +class C { + String text; + + C(String this.text); +} +'''); + } + + test_setter_generic_BAD() async { + await resolveTestUnit(''' +class A { +} +class B<T> { + List<T> items; + main(A a) { + a.test = items; + } +} +'''); + await assertHasFix(''' +class A { + List test; +} +class B<T> { + List<T> items; + main(A a) { + a.test = items; + } +} +'''); + } + + test_setter_generic_OK_local() async { + await resolveTestUnit(''' +class A<T> { + List<T> items; + + main(A a) { + test = items; + } +} +'''); + await assertHasFix(''' +class A<T> { + List<T> items; + + List<T> test; + + main(A a) { + test = items; + } +} +'''); + } + + test_setter_qualified_instance_hasField() async { + await resolveTestUnit(''' +class A { + int aaa; + int zzz; + + existingMethod() {} +} +main(A a) { + a.test = 5; +} +'''); + await assertHasFix(''' +class A { + int aaa; + int zzz; + + int test; + + existingMethod() {} +} +main(A a) { + a.test = 5; +} +'''); + } + + test_setter_qualified_instance_hasMethod() async { + await resolveTestUnit(''' +class A { + existingMethod() {} +} +main(A a) { + a.test = 5; +} +'''); + await assertHasFix(''' +class A { + int test; + + existingMethod() {} +} +main(A a) { + a.test = 5; +} +'''); + } + + test_setter_qualified_static() async { + await resolveTestUnit(''' +class A { +} +main() { + A.test = 5; +} +'''); + await assertHasFix(''' +class A { + static int test; +} +main() { + A.test = 5; +} +'''); + } + + test_setter_unqualified_instance() async { + await resolveTestUnit(''' +class A { + main() { + test = 5; + } +} +'''); + await assertHasFix(''' +class A { + int test; + + main() { + test = 5; + } +} +'''); + } + + test_setter_unqualified_static() async { + await resolveTestUnit(''' +class A { + static main() { + test = 5; + } +} +'''); + await assertHasFix(''' +class A { + static int test; + + static main() { + test = 5; + } +} +'''); + } +}
diff --git a/pkg/analysis_server/test/src/services/correction/fix/create_file_test.dart b/pkg/analysis_server/test/src/services/correction/fix/create_file_test.dart new file mode 100644 index 0000000..3bb2fd8 --- /dev/null +++ b/pkg/analysis_server/test/src/services/correction/fix/create_file_test.dart
@@ -0,0 +1,101 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:analysis_server/src/protocol_server.dart'; +import 'package:analysis_server/src/services/correction/fix.dart'; +import 'package:analyzer_plugin/utilities/fixes/fixes.dart'; +import 'package:test/test.dart'; +import 'package:test_reflective_loader/test_reflective_loader.dart'; + +import 'fix_processor.dart'; + +main() { + defineReflectiveSuite(() { + defineReflectiveTests(CreateFileTest); + }); +} + +@reflectiveTest +class CreateFileTest extends FixProcessorTest { + @override + FixKind get kind => DartFixKind.CREATE_FILE; + + test_forImport() async { + await resolveTestUnit(''' +import 'my_file.dart'; +'''); + await assertHasFixWithoutApplying(); + // validate change + List<SourceFileEdit> fileEdits = change.edits; + expect(fileEdits, hasLength(1)); + SourceFileEdit fileEdit = change.edits[0]; + expect(fileEdit.file, convertPath('/home/test/lib/my_file.dart')); + expect(fileEdit.fileStamp, -1); + expect(fileEdit.edits, hasLength(1)); + expect( + fileEdit.edits[0].replacement, + contains('// TODO Implement this library.'), + ); + } + + test_forImport_BAD_notDart() async { + await resolveTestUnit(''' +import 'my_file.txt'; +'''); + await assertNoFix(); + } + + test_forImport_inPackage_lib() async { + await resolveTestUnit(''' +import 'a/bb/my_lib.dart'; +'''); + await assertHasFixWithoutApplying(); + // validate change + List<SourceFileEdit> fileEdits = change.edits; + expect(fileEdits, hasLength(1)); + SourceFileEdit fileEdit = change.edits[0]; + expect(fileEdit.file, convertPath('/home/test/lib/a/bb/my_lib.dart')); + expect(fileEdit.fileStamp, -1); + expect(fileEdit.edits, hasLength(1)); + expect( + fileEdit.edits[0].replacement, + contains('// TODO Implement this library.'), + ); + } + + test_forImport_inPackage_test() async { + testFile = convertPath('/home/test/test/test.dart'); + await resolveTestUnit(''' +import 'a/bb/my_lib.dart'; +'''); + await assertHasFixWithoutApplying(); + // validate change + List<SourceFileEdit> fileEdits = change.edits; + expect(fileEdits, hasLength(1)); + SourceFileEdit fileEdit = change.edits[0]; + expect(fileEdit.file, convertPath('/home/test/test/a/bb/my_lib.dart')); + expect(fileEdit.fileStamp, -1); + expect(fileEdit.edits, hasLength(1)); + expect( + fileEdit.edits[0].replacement, + contains('// TODO Implement this library.'), + ); + } + + test_forPart() async { + await resolveTestUnit(''' +library my.lib; +part 'my_part.dart'; +'''); + await assertHasFixWithoutApplying(); + // validate change + List<SourceFileEdit> fileEdits = change.edits; + expect(fileEdits, hasLength(1)); + SourceFileEdit fileEdit = change.edits[0]; + expect(fileEdit.file, convertPath('/home/test/lib/my_part.dart')); + expect(fileEdit.fileStamp, -1); + expect(fileEdit.edits, hasLength(1)); + expect(fileEdit.edits[0].replacement, contains('part of my.lib;')); + } +}
diff --git a/pkg/analysis_server/test/src/services/correction/fix/create_function_test.dart b/pkg/analysis_server/test/src/services/correction/fix/create_function_test.dart new file mode 100644 index 0000000..6fc4504 --- /dev/null +++ b/pkg/analysis_server/test/src/services/correction/fix/create_function_test.dart
@@ -0,0 +1,550 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:analysis_server/src/protocol_server.dart'; +import 'package:analysis_server/src/services/correction/fix.dart'; +import 'package:analyzer_plugin/utilities/fixes/fixes.dart'; +import 'package:test_reflective_loader/test_reflective_loader.dart'; + +import 'fix_processor.dart'; + +main() { + defineReflectiveSuite(() { + defineReflectiveTests(CreateFunctionTest); + }); +} + +@reflectiveTest +class CreateFunctionTest extends FixProcessorTest { + @override + FixKind get kind => DartFixKind.CREATE_FUNCTION; + + assert_returnType_bool(String lineWithTest) async { + await resolveTestUnit(''' +main() { + bool b = true; + $lineWithTest + print(b); +} +'''); + await assertHasFix(''' +main() { + bool b = true; + $lineWithTest + print(b); +} + +bool test() { +} +'''); + } + + test_bottomArgument() async { + await resolveTestUnit(''' +main() { + test(throw 42); +} +'''); + await assertHasFix(''' +main() { + test(throw 42); +} + +void test(param0) { +} +'''); + } + + test_duplicateArgumentNames() async { + await resolveTestUnit(''' +class C { + int x; +} + +foo(C c1, C c2) { + bar(c1.x, c2.x); +} +'''); + await assertHasFix(''' +class C { + int x; +} + +foo(C c1, C c2) { + bar(c1.x, c2.x); +} + +void bar(int x, int x2) { +} +'''); + } + + test_dynamicArgument() async { + await resolveTestUnit(''' +main() { + dynamic v; + test(v); +} +'''); + await assertHasFix(''' +main() { + dynamic v; + test(v); +} + +void test(v) { +} +'''); + } + + test_dynamicReturnType() async { + await resolveTestUnit(''' +main() { + dynamic v = test(); + print(v); +} +'''); + await assertHasFix(''' +main() { + dynamic v = test(); + print(v); +} + +test() { +} +'''); + } + + test_fromFunction() async { + await resolveTestUnit(''' +main() { + int v = myUndefinedFunction(1, 2.0, '3'); + print(v); +} +'''); + await assertHasFix(''' +main() { + int v = myUndefinedFunction(1, 2.0, '3'); + print(v); +} + +int myUndefinedFunction(int i, double d, String s) { +} +'''); + } + + test_fromMethod() async { + await resolveTestUnit(''' +class A { + main() { + int v = myUndefinedFunction(1, 2.0, '3'); + print(v); + } +} +'''); + await assertHasFix(''' +class A { + main() { + int v = myUndefinedFunction(1, 2.0, '3'); + print(v); + } +} + +int myUndefinedFunction(int i, double d, String s) { +} +'''); + } + + test_functionType_cascadeSecond() async { + await resolveTestUnit(''' +class A { + B ma() => null; +} +class B { + useFunction(int g(double a, String b)) {} +} + +main() { + A a = new A(); + a..ma().useFunction(test); +} +'''); + await assertHasFix(''' +class A { + B ma() => null; +} +class B { + useFunction(int g(double a, String b)) {} +} + +main() { + A a = new A(); + a..ma().useFunction(test); +} + +int test(double a, String b) { +} +'''); + } + + test_functionType_coreFunction() async { + await resolveTestUnit(''' +main() { + useFunction(g: test); +} +useFunction({Function g}) {} +'''); + await assertHasFix(''' +main() { + useFunction(g: test); +} +useFunction({Function g}) {} + +test() { +} +'''); + } + + test_functionType_dynamicArgument() async { + await resolveTestUnit(''' +main() { + useFunction(test); +} +useFunction(int g(a, b)) {} +'''); + await assertHasFix(''' +main() { + useFunction(test); +} +useFunction(int g(a, b)) {} + +int test(a, b) { +} +'''); + } + + test_functionType_function() async { + await resolveTestUnit(''' +main() { + useFunction(test); +} +useFunction(int g(double a, String b)) {} +'''); + await assertHasFix(''' +main() { + useFunction(test); +} +useFunction(int g(double a, String b)) {} + +int test(double a, String b) { +} +'''); + } + + test_functionType_function_namedArgument() async { + await resolveTestUnit(''' +main() { + useFunction(g: test); +} +useFunction({int g(double a, String b)}) {} +'''); + await assertHasFix(''' +main() { + useFunction(g: test); +} +useFunction({int g(double a, String b)}) {} + +int test(double a, String b) { +} +'''); + } + + test_functionType_importType() async { + addSource('/home/test/lib/a.dart', r''' +class A {} +'''); + addSource('/home/test/lib/b.dart', r''' +import 'package:test/a.dart'; + +useFunction(int g(A a)) {} +'''); + await resolveTestUnit(''' +import 'package:test/b.dart'; + +main() { + useFunction(test); +} +'''); + await assertHasFix(''' +import 'package:test/a.dart'; +import 'package:test/b.dart'; + +main() { + useFunction(test); +} + +int test(A a) { +} +'''); + } + + test_functionType_notFunctionType() async { + await resolveTestUnit(''' +main(A a) { + useFunction(a.test); +} +typedef A(); +useFunction(g) {} +'''); + await assertNoFix(); + } + + test_generic_type() async { + await resolveTestUnit(''' +class A { + List<int> items; + main() { + process(items); + } +} +'''); + await assertHasFix(''' +class A { + List<int> items; + main() { + process(items); + } +} + +void process(List<int> items) { +} +'''); + assertLinkedGroup( + change.linkedEditGroups[2], + ['List<int> items) {'], + expectedSuggestions(LinkedEditSuggestionKind.TYPE, + ['List<int>', 'Iterable<int>', 'Object'])); + } + + test_generic_typeParameter() async { + await resolveTestUnit(''' +class A<T> { + Map<int, T> items; + main() { + process(items); + } +} +'''); + await assertHasFix(''' +class A<T> { + Map<int, T> items; + main() { + process(items); + } +} + +void process(Map items) { +} +'''); + } + + test_importType() async { + addSource('/home/test/lib/lib.dart', r''' +library lib; +import 'dart:async'; +Future getFuture() => null; +'''); + await resolveTestUnit(''' +import 'lib.dart'; +main() { + test(getFuture()); +} +'''); + await assertHasFix(''' +import 'lib.dart'; +main() { + test(getFuture()); +} + +void test(Future future) { +} +'''); + } + + test_nullArgument() async { + await resolveTestUnit(''' +main() { + test(null); +} +'''); + await assertHasFix(''' +main() { + test(null); +} + +void test(param0) { +} +'''); + } + + test_returnType_bool_and_left() async { + await assert_returnType_bool("test() && b;"); + } + + test_returnType_bool_and_right() async { + await assert_returnType_bool("b && test();"); + } + + test_returnType_bool_assert() async { + await assert_returnType_bool("assert ( test() );"); + } + + test_returnType_bool_do() async { + await assert_returnType_bool("do {} while ( test() );"); + } + + test_returnType_bool_if() async { + await assert_returnType_bool("if ( test() ) {}"); + } + + test_returnType_bool_or_left() async { + await assert_returnType_bool("test() || b;"); + } + + test_returnType_bool_or_right() async { + await assert_returnType_bool("b || test();"); + } + + test_returnType_bool_unaryNegation() async { + await assert_returnType_bool("!test();"); + } + + test_returnType_bool_while() async { + await assert_returnType_bool("while ( test() ) {}"); + } + + test_returnType_fromAssignment_eq() async { + await resolveTestUnit(''' +main() { + int v; + v = myUndefinedFunction(); + print(v); +} +'''); + await assertHasFix(''' +main() { + int v; + v = myUndefinedFunction(); + print(v); +} + +int myUndefinedFunction() { +} +'''); + } + + test_returnType_fromAssignment_plusEq() async { + await resolveTestUnit(''' +main() { + int v; + v += myUndefinedFunction(); + print(v); +} +'''); + await assertHasFix(''' +main() { + int v; + v += myUndefinedFunction(); + print(v); +} + +num myUndefinedFunction() { +} +'''); + } + + test_returnType_fromBinary_right() async { + await resolveTestUnit(''' +main() { + 0 + myUndefinedFunction(); +} +'''); + await assertHasFix(''' +main() { + 0 + myUndefinedFunction(); +} + +num myUndefinedFunction() { +} +'''); + } + + test_returnType_fromInitializer() async { + await resolveTestUnit(''' +main() { + int v = myUndefinedFunction(); + print(v); +} +'''); + await assertHasFix(''' +main() { + int v = myUndefinedFunction(); + print(v); +} + +int myUndefinedFunction() { +} +'''); + } + + test_returnType_fromInvocationArgument() async { + await resolveTestUnit(''' +foo(int p) {} +main() { + foo( myUndefinedFunction() ); +} +'''); + await assertHasFix(''' +foo(int p) {} +main() { + foo( myUndefinedFunction() ); +} + +int myUndefinedFunction() { +} +'''); + } + + test_returnType_fromReturn() async { + await resolveTestUnit(''' +int main() { + return myUndefinedFunction(); +} +'''); + await assertHasFix(''' +int main() { + return myUndefinedFunction(); +} + +int myUndefinedFunction() { +} +'''); + } + + test_returnType_void() async { + await resolveTestUnit(''' +main() { + myUndefinedFunction(); +} +'''); + await assertHasFix(''' +main() { + myUndefinedFunction(); +} + +void myUndefinedFunction() { +} +'''); + } +}
diff --git a/pkg/analysis_server/test/src/services/correction/fix/create_getter_test.dart b/pkg/analysis_server/test/src/services/correction/fix/create_getter_test.dart new file mode 100644 index 0000000..85941b0 --- /dev/null +++ b/pkg/analysis_server/test/src/services/correction/fix/create_getter_test.dart
@@ -0,0 +1,363 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:analysis_server/src/services/correction/fix.dart'; +import 'package:analyzer_plugin/utilities/fixes/fixes.dart'; +import 'package:test_reflective_loader/test_reflective_loader.dart'; + +import 'fix_processor.dart'; + +main() { + defineReflectiveSuite(() { + defineReflectiveTests(CreateGetterTest); + defineReflectiveTests(CreateGetterMixinTest); + }); +} + +@reflectiveTest +class CreateGetterMixinTest extends FixProcessorTest { + @override + FixKind get kind => DartFixKind.CREATE_GETTER; + + test_qualified_instance() async { + await resolveTestUnit(''' +mixin M { +} + +main(M m) { + int v = m.test; + print(v); +} +'''); + await assertHasFix(''' +mixin M { + int get test => null; +} + +main(M m) { + int v = m.test; + print(v); +} +'''); + } + + test_unqualified_instance_assignmentLhs() async { + await resolveTestUnit(''' +mixin M { + main() { + test = 42; + } +} +'''); + await assertNoFix(); + } + + test_unqualified_instance_assignmentRhs() async { + await resolveTestUnit(''' +mixin M { + main() { + int v = test; + print(v); + } +} +'''); + await assertHasFix(''' +mixin M { + int get test => null; + + main() { + int v = test; + print(v); + } +} +'''); + } +} + +@reflectiveTest +class CreateGetterTest extends FixProcessorTest { + @override + FixKind get kind => DartFixKind.CREATE_GETTER; + + test_hint_getter() async { + await resolveTestUnit(''' +class A { +} +main(A a) { + var x = a; + int v = x.test; + print(v); +} +'''); + await assertHasFix(''' +class A { + int get test => null; +} +main(A a) { + var x = a; + int v = x.test; + print(v); +} +'''); + } + + test_inSDK() async { + await resolveTestUnit(''' +main(List p) { + int v = p.foo; + print(v); +} +'''); + await assertNoFix(); + } + + test_location_afterLastGetter() async { + await resolveTestUnit(''' +class A { + int existingField; + + int get existingGetter => null; + + existingMethod() {} +} +main(A a) { + int v = a.test; + print(v); +} +'''); + await assertHasFix(''' +class A { + int existingField; + + int get existingGetter => null; + + int get test => null; + + existingMethod() {} +} +main(A a) { + int v = a.test; + print(v); +} +'''); + } + + test_multiLevel() async { + await resolveTestUnit(''' +class A { +} +class B { + A a; +} +class C { + B b; +} +main(C c) { + int v = c.b.a.test; + print(v); +} +'''); + await assertHasFix(''' +class A { + int get test => null; +} +class B { + A a; +} +class C { + B b; +} +main(C c) { + int v = c.b.a.test; + print(v); +} +'''); + } + + test_qualified_instance() async { + await resolveTestUnit(''' +class A { +} +main(A a) { + int v = a.test; + print(v); +} +'''); + await assertHasFix(''' +class A { + int get test => null; +} +main(A a) { + int v = a.test; + print(v); +} +'''); + } + + test_qualified_instance_differentLibrary() async { + addSource('/home/test/lib/other.dart', ''' +/** + * A comment to push the offset of the braces for the following class + * declaration past the end of the content of the test file. Used to catch an + * index out of bounds exception that occurs when using the test source instead + * of the target source to compute the location at which to insert the field. + */ +class A { +} +'''); + + await resolveTestUnit(''' +import 'package:test/other.dart'; + +main(A a) { + int v = a.test; + print(v); +} +'''); + + await assertHasFix(''' +/** + * A comment to push the offset of the braces for the following class + * declaration past the end of the content of the test file. Used to catch an + * index out of bounds exception that occurs when using the test source instead + * of the target source to compute the location at which to insert the field. + */ +class A { + int get test => null; +} +''', target: '/home/test/lib/other.dart'); + } + + test_qualified_instance_dynamicType() async { + await resolveTestUnit(''' +class A { + B b; + void f(Object p) { + p == b.test; + } +} +class B { +} +'''); + await assertHasFix(''' +class A { + B b; + void f(Object p) { + p == b.test; + } +} +class B { + get test => null; +} +'''); + } + + test_qualified_propagatedType() async { + await resolveTestUnit(''' +class A { + A get self => this; +} +main() { + var a = new A(); + int v = a.self.test; + print(v); +} +'''); + await assertHasFix(''' +class A { + A get self => this; + + int get test => null; +} +main() { + var a = new A(); + int v = a.self.test; + print(v); +} +'''); + } + + test_setterContext() async { + await resolveTestUnit(''' +class A { +} +main(A a) { + a.test = 42; +} +'''); + await assertNoFix(); + } + + test_unqualified_instance_asInvocationArgument() async { + await resolveTestUnit(''' +class A { + main() { + f(test); + } +} +f(String s) {} +'''); + await assertHasFix(''' +class A { + String get test => null; + + main() { + f(test); + } +} +f(String s) {} +'''); + } + + test_unqualified_instance_assignmentLhs() async { + await resolveTestUnit(''' +class A { + main() { + test = 42; + } +} +'''); + await assertNoFix(); + } + + test_unqualified_instance_assignmentRhs() async { + await resolveTestUnit(''' +class A { + main() { + int v = test; + print(v); + } +} +'''); + await assertHasFix(''' +class A { + int get test => null; + + main() { + int v = test; + print(v); + } +} +'''); + } + + test_unqualified_instance_asStatement() async { + await resolveTestUnit(''' +class A { + main() { + test; + } +} +'''); + await assertHasFix(''' +class A { + get test => null; + + main() { + test; + } +} +'''); + } +}
diff --git a/pkg/analysis_server/test/src/services/correction/fix/create_local_variable_test.dart b/pkg/analysis_server/test/src/services/correction/fix/create_local_variable_test.dart new file mode 100644 index 0000000..933eec9 --- /dev/null +++ b/pkg/analysis_server/test/src/services/correction/fix/create_local_variable_test.dart
@@ -0,0 +1,218 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:analysis_server/src/protocol_server.dart'; +import 'package:analysis_server/src/services/correction/fix.dart'; +import 'package:analyzer_plugin/utilities/fixes/fixes.dart'; +import 'package:test/test.dart'; +import 'package:test_reflective_loader/test_reflective_loader.dart'; + +import 'fix_processor.dart'; + +main() { + defineReflectiveSuite(() { + defineReflectiveTests(CreateLocalVariableTest); + }); +} + +@reflectiveTest +class CreateLocalVariableTest extends FixProcessorTest { + @override + FixKind get kind => DartFixKind.CREATE_LOCAL_VARIABLE; + + test_functionType_named() async { + await resolveTestUnit(''' +typedef MY_FUNCTION(int p); +foo(MY_FUNCTION f) {} +main() { + foo(bar); +} +'''); + await assertHasFix(''' +typedef MY_FUNCTION(int p); +foo(MY_FUNCTION f) {} +main() { + MY_FUNCTION bar; + foo(bar); +} +'''); + } + + test_functionType_named_generic() async { + await resolveTestUnit(''' +typedef MY_FUNCTION<T>(T p); +foo(MY_FUNCTION<int> f) {} +main() { + foo(bar); +} +'''); + await assertHasFix(''' +typedef MY_FUNCTION<T>(T p); +foo(MY_FUNCTION<int> f) {} +main() { + MY_FUNCTION<int> bar; + foo(bar); +} +'''); + } + + test_functionType_synthetic() async { + await resolveTestUnit(''' +foo(f(int p)) {} +main() { + foo(bar); +} +'''); + await assertHasFix(''' +foo(f(int p)) {} +main() { + Function(int p) bar; + foo(bar); +} +'''); + } + + test_read_typeAssignment() async { + await resolveTestUnit(''' +main() { + int a = test; + print(a); +} +'''); + await assertHasFix(''' +main() { + int test; + int a = test; + print(a); +} +'''); + } + + test_read_typeCondition() async { + await resolveTestUnit(''' +main() { + if (!test) { + print(42); + } +} +'''); + await assertHasFix(''' +main() { + bool test; + if (!test) { + print(42); + } +} +'''); + } + + test_read_typeInvocationArgument() async { + await resolveTestUnit(''' +main() { + f(test); +} +f(String p) {} +'''); + await assertHasFix(''' +main() { + String test; + f(test); +} +f(String p) {} +'''); + assertLinkedGroup(change.linkedEditGroups[0], ['String test;']); + assertLinkedGroup(change.linkedEditGroups[1], ['test;', 'test);']); + } + + test_read_typeInvocationTarget() async { + await resolveTestUnit(''' +main() { + test.add('hello'); +} +'''); + await assertHasFix(''' +main() { + var test; + test.add('hello'); +} +'''); + assertLinkedGroup(change.linkedEditGroups[0], ['test;', 'test.add(']); + } + + test_withImport() async { + addPackageFile('pkg', 'a/a.dart', ''' +class A {} +'''); + addPackageFile('pkg', 'b/b.dart', ''' +class B {} +'''); + addPackageFile('pkg', 'c/c.dart', ''' +import 'package:pkg/a/a.dart'; +import 'package:pkg/b/b.dart'; + +class C { + C(A a, B b); +} +'''); + + await resolveTestUnit(''' +import 'package:pkg/a/a.dart'; +import 'package:pkg/c/c.dart'; + +main() { + A a; + new C(a, b); +} +'''); + await assertHasFix(''' +import 'package:pkg/a/a.dart'; +import 'package:pkg/b/b.dart'; +import 'package:pkg/c/c.dart'; + +main() { + A a; + B b; + new C(a, b); +} +'''); + List<LinkedEditGroup> groups = change.linkedEditGroups; + expect(groups, hasLength(2)); + LinkedEditGroup typeGroup = groups[0]; + List<Position> typePositions = typeGroup.positions; + expect(typePositions, hasLength(1)); + expect(typePositions[0].offset, 112); + LinkedEditGroup nameGroup = groups[1]; + List<Position> groupPositions = nameGroup.positions; + expect(groupPositions, hasLength(2)); + expect(groupPositions[0].offset, 114); + expect(groupPositions[1].offset, 128); + } + + test_write_assignment() async { + await resolveTestUnit(''' +main() { + test = 42; +} +'''); + await assertHasFix(''' +main() { + var test = 42; +} +'''); + } + + test_write_assignment_compound() async { + await resolveTestUnit(''' +main() { + test += 42; +} +'''); + await assertHasFix(''' +main() { + int test; + test += 42; +} +'''); + } +}
diff --git a/pkg/analysis_server/test/src/services/correction/fix/create_method_test.dart b/pkg/analysis_server/test/src/services/correction/fix/create_method_test.dart new file mode 100644 index 0000000..bf502f1 --- /dev/null +++ b/pkg/analysis_server/test/src/services/correction/fix/create_method_test.dart
@@ -0,0 +1,705 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:analysis_server/src/protocol_server.dart'; +import 'package:analysis_server/src/services/correction/fix.dart'; +import 'package:analyzer_plugin/utilities/fixes/fixes.dart'; +import 'package:test_reflective_loader/test_reflective_loader.dart'; + +import 'fix_processor.dart'; + +main() { + defineReflectiveSuite(() { + defineReflectiveTests(CreateMethodTest); + defineReflectiveTests(CreateMethodMixinTest); + }); +} + +@reflectiveTest +class CreateMethodMixinTest extends FixProcessorTest { + @override + FixKind get kind => DartFixKind.CREATE_METHOD; + + test_createQualified_instance() async { + await resolveTestUnit(''' +mixin M {} + +main(M m) { + m.myUndefinedMethod(); +} +'''); + await assertHasFix(''' +mixin M { + void myUndefinedMethod() {} +} + +main(M m) { + m.myUndefinedMethod(); +} +'''); + } + + test_createQualified_static() async { + await resolveTestUnit(''' +mixin M {} + +main() { + M.myUndefinedMethod(); +} +'''); + await assertHasFix(''' +mixin M { + static void myUndefinedMethod() {} +} + +main() { + M.myUndefinedMethod(); +} +'''); + } + + test_createUnqualified() async { + await resolveTestUnit(''' +mixin M { + main() { + myUndefinedMethod(); + } +} +'''); + await assertHasFix(''' +mixin M { + main() { + myUndefinedMethod(); + } + + void myUndefinedMethod() {} +} +'''); + } + + test_functionType_method_enclosingMixin_static() async { + await resolveTestUnit(''' +mixin M { + static foo() { + useFunction(test); + } +} + +useFunction(int g(double a, String b)) {} +'''); + await assertHasFix(''' +mixin M { + static foo() { + useFunction(test); + } + + static int test(double a, String b) { + } +} + +useFunction(int g(double a, String b)) {} +'''); + } + + test_functionType_method_targetMixin() async { + await resolveTestUnit(''' +main(M m) { + useFunction(m.test); +} + +mixin M { +} + +useFunction(int g(double a, String b)) {} +'''); + await assertHasFix(''' +main(M m) { + useFunction(m.test); +} + +mixin M { + int test(double a, String b) { + } +} + +useFunction(int g(double a, String b)) {} +'''); + } +} + +@reflectiveTest +class CreateMethodTest extends FixProcessorTest { + @override + FixKind get kind => DartFixKind.CREATE_METHOD; + + test_createQualified_emptyClassBody() async { + await resolveTestUnit(''' +class A {} +main() { + A.myUndefinedMethod(); +} +'''); + await assertHasFix(''' +class A { + static void myUndefinedMethod() {} +} +main() { + A.myUndefinedMethod(); +} +'''); + } + + test_createQualified_fromClass() async { + await resolveTestUnit(''' +class A { +} +main() { + A.myUndefinedMethod(); +} +'''); + await assertHasFix(''' +class A { + static void myUndefinedMethod() {} +} +main() { + A.myUndefinedMethod(); +} +'''); + } + + test_createQualified_fromClass_hasOtherMember() async { + await resolveTestUnit(''' +class A { + foo() {} +} +main() { + A.myUndefinedMethod(); +} +'''); + await assertHasFix(''' +class A { + foo() {} + + static void myUndefinedMethod() {} +} +main() { + A.myUndefinedMethod(); +} +'''); + } + + test_createQualified_fromInstance() async { + await resolveTestUnit(''' +class A { +} +main(A a) { + a.myUndefinedMethod(); +} +'''); + await assertHasFix(''' +class A { + void myUndefinedMethod() {} +} +main(A a) { + a.myUndefinedMethod(); +} +'''); + } + + test_createQualified_targetIsFunctionType() async { + await resolveTestUnit(''' +typedef A(); +main() { + A.myUndefinedMethod(); +} +'''); + await assertNoFix(); + } + + test_createQualified_targetIsUnresolved() async { + await resolveTestUnit(''' +main() { + NoSuchClass.myUndefinedMethod(); +} +'''); + await assertNoFix(); + } + + test_createUnqualified_duplicateArgumentNames() async { + await resolveTestUnit(''' +class C { + int x; +} + +class D { + foo(C c1, C c2) { + bar(c1.x, c2.x); + } +}'''); + await assertHasFix(''' +class C { + int x; +} + +class D { + foo(C c1, C c2) { + bar(c1.x, c2.x); + } + + void bar(int x, int x2) {} +}'''); + } + + test_createUnqualified_parameters() async { + await resolveTestUnit(''' +class A { + main() { + myUndefinedMethod(0, 1.0, '3'); + } +} +'''); + await assertHasFix(''' +class A { + main() { + myUndefinedMethod(0, 1.0, '3'); + } + + void myUndefinedMethod(int i, double d, String s) {} +} +'''); + // linked positions + int index = 0; + assertLinkedGroup( + change.linkedEditGroups[index++], ['void myUndefinedMethod(']); + assertLinkedGroup(change.linkedEditGroups[index++], + ['myUndefinedMethod(0', 'myUndefinedMethod(int']); + assertLinkedGroup( + change.linkedEditGroups[index++], + ['int i'], + expectedSuggestions(LinkedEditSuggestionKind.TYPE, + ['int', 'num', 'Object', 'Comparable<num>'])); + assertLinkedGroup(change.linkedEditGroups[index++], ['i,']); + assertLinkedGroup( + change.linkedEditGroups[index++], + ['double d'], + expectedSuggestions(LinkedEditSuggestionKind.TYPE, + ['double', 'num', 'Object', 'Comparable<num>'])); + assertLinkedGroup(change.linkedEditGroups[index++], ['d,']); + assertLinkedGroup( + change.linkedEditGroups[index++], + ['String s'], + expectedSuggestions(LinkedEditSuggestionKind.TYPE, + ['String', 'Object', 'Comparable<String>', 'Pattern'])); + assertLinkedGroup(change.linkedEditGroups[index++], ['s)']); + } + + test_createUnqualified_parameters_named() async { + await resolveTestUnit(''' +class A { + main() { + myUndefinedMethod(0, bbb: 1.0, ccc: '2'); + } +} +'''); + await assertHasFix(''' +class A { + main() { + myUndefinedMethod(0, bbb: 1.0, ccc: '2'); + } + + void myUndefinedMethod(int i, {double bbb, String ccc}) {} +} +'''); + // linked positions + int index = 0; + assertLinkedGroup( + change.linkedEditGroups[index++], ['void myUndefinedMethod(']); + assertLinkedGroup(change.linkedEditGroups[index++], + ['myUndefinedMethod(0', 'myUndefinedMethod(int']); + assertLinkedGroup( + change.linkedEditGroups[index++], + ['int i'], + expectedSuggestions(LinkedEditSuggestionKind.TYPE, + ['int', 'num', 'Object', 'Comparable<num>'])); + assertLinkedGroup(change.linkedEditGroups[index++], ['i,']); + assertLinkedGroup( + change.linkedEditGroups[index++], + ['double bbb'], + expectedSuggestions(LinkedEditSuggestionKind.TYPE, + ['double', 'num', 'Object', 'Comparable<num>'])); + assertLinkedGroup( + change.linkedEditGroups[index++], + ['String ccc'], + expectedSuggestions(LinkedEditSuggestionKind.TYPE, + ['String', 'Object', 'Comparable<String>', 'Pattern'])); + } + + test_createUnqualified_returnType() async { + await resolveTestUnit(''' +class A { + main() { + int v = myUndefinedMethod(); + print(v); + } +} +'''); + await assertHasFix(''' +class A { + main() { + int v = myUndefinedMethod(); + print(v); + } + + int myUndefinedMethod() {} +} +'''); + // linked positions + assertLinkedGroup(change.linkedEditGroups[0], ['int myUndefinedMethod(']); + assertLinkedGroup(change.linkedEditGroups[1], + ['myUndefinedMethod();', 'myUndefinedMethod() {']); + } + + test_createUnqualified_staticFromField() async { + await resolveTestUnit(''' +class A { + static var f = myUndefinedMethod(); +} +'''); + await assertHasFix(''' +class A { + static var f = myUndefinedMethod(); + + static myUndefinedMethod() {} +} +'''); + } + + test_createUnqualified_staticFromMethod() async { + await resolveTestUnit(''' +class A { + static main() { + myUndefinedMethod(); + } +} +'''); + await assertHasFix(''' +class A { + static main() { + myUndefinedMethod(); + } + + static void myUndefinedMethod() {} +} +'''); + } + + test_functionType_method_enclosingClass_static() async { + await resolveTestUnit(''' +class A { + static foo() { + useFunction(test); + } +} +useFunction(int g(double a, String b)) {} +'''); + await assertHasFix(''' +class A { + static foo() { + useFunction(test); + } + + static int test(double a, String b) { + } +} +useFunction(int g(double a, String b)) {} +'''); + } + + test_functionType_method_enclosingClass_static2() async { + await resolveTestUnit(''' +class A { + var f; + A() : f = useFunction(test); +} +useFunction(int g(double a, String b)) {} +'''); + await assertHasFix(''' +class A { + var f; + A() : f = useFunction(test); + + static int test(double a, String b) { + } +} +useFunction(int g(double a, String b)) {} +'''); + } + + test_functionType_method_targetClass() async { + await resolveTestUnit(''' +main(A a) { + useFunction(a.test); +} +class A { +} +useFunction(int g(double a, String b)) {} +'''); + await assertHasFix(''' +main(A a) { + useFunction(a.test); +} +class A { + int test(double a, String b) { + } +} +useFunction(int g(double a, String b)) {} +'''); + } + + test_functionType_method_targetClass_hasOtherMember() async { + await resolveTestUnit(''' +main(A a) { + useFunction(a.test); +} +class A { + m() {} +} +useFunction(int g(double a, String b)) {} +'''); + await assertHasFix(''' +main(A a) { + useFunction(a.test); +} +class A { + m() {} + + int test(double a, String b) { + } +} +useFunction(int g(double a, String b)) {} +'''); + } + + test_functionType_notFunctionType() async { + await resolveTestUnit(''' +main(A a) { + useFunction(a.test); +} +typedef A(); +useFunction(g) {} +'''); + await assertNoFix(); + } + + test_functionType_unknownTarget() async { + await resolveTestUnit(''' +main(A a) { + useFunction(a.test); +} +class A { +} +useFunction(g) {} +'''); + await assertNoFix(); + } + + test_generic_argumentType() async { + await resolveTestUnit(''' +class A<T> { + B b; + Map<int, T> items; + main() { + b.process(items); + } +} + +class B { +} +'''); + await assertHasFix(''' +class A<T> { + B b; + Map<int, T> items; + main() { + b.process(items); + } +} + +class B { + void process(Map items) {} +} +'''); + } + + test_generic_literal() async { + await resolveTestUnit(''' +class A { + B b; + List<int> items; + main() { + b.process(items); + } +} + +class B {} +'''); + await assertHasFix(''' +class A { + B b; + List<int> items; + main() { + b.process(items); + } +} + +class B { + void process(List<int> items) {} +} +'''); + } + + test_generic_local() async { + await resolveTestUnit(''' +class A<T> { + List<T> items; + main() { + process(items); + } +} +'''); + await assertHasFix(''' +class A<T> { + List<T> items; + main() { + process(items); + } + + void process(List<T> items) {} +} +'''); + } + + test_generic_returnType() async { + await resolveTestUnit(''' +class A<T> { + main() { + T t = new B().compute(); + print(t); + } +} + +class B { +} +'''); + await assertHasFix(''' +class A<T> { + main() { + T t = new B().compute(); + print(t); + } +} + +class B { + compute() {} +} +'''); + } + + test_hint_createQualified_fromInstance() async { + await resolveTestUnit(''' +class A { +} +main() { + var a = new A(); + a.myUndefinedMethod(); +} +'''); + await assertHasFix(''' +class A { + void myUndefinedMethod() {} +} +main() { + var a = new A(); + a.myUndefinedMethod(); +} +'''); + } + + test_inSDK() async { + await resolveTestUnit(''' +main() { + List.foo(); +} +'''); + await assertNoFix(); + } + + test_parameterType_differentPrefixInTargetUnit() async { + String code2 = r''' +import 'test3.dart' as bbb; +export 'test3.dart'; + +class D { +} +'''; + + addSource('/home/test/lib/test2.dart', code2); + addSource('/home/test/lib/test3.dart', r''' +library test3; +class E {} +'''); + + await resolveTestUnit(''' +import 'test2.dart' as aaa; + +main(aaa.D d, aaa.E e) { + d.foo(e); +} +'''); + + await assertHasFix(''' +import 'test3.dart' as bbb; +export 'test3.dart'; + +class D { + void foo(bbb.E e) {} +} +''', target: '/home/test/lib/test2.dart'); + } + + test_parameterType_inTargetUnit() async { + addSource('/home/test/lib/test2.dart', r''' +class D { +} + +class E {} +'''); + + await resolveTestUnit(''' +import 'test2.dart' as test2; + +main(test2.D d, test2.E e) { + d.foo(e); +} +'''); + + await assertHasFix(''' +class D { + void foo(E e) {} +} + +class E {} +''', target: '/home/test/lib/test2.dart'); + } + + test_targetIsEnum() async { + await resolveTestUnit(''' +enum MyEnum {A, B} +main() { + MyEnum.foo(); +} +'''); + await assertNoFix(); + } +}
diff --git a/pkg/analysis_server/test/src/services/correction/fix/create_missing_overrides_test.dart b/pkg/analysis_server/test/src/services/correction/fix/create_missing_overrides_test.dart new file mode 100644 index 0000000..7656709 --- /dev/null +++ b/pkg/analysis_server/test/src/services/correction/fix/create_missing_overrides_test.dart
@@ -0,0 +1,520 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:analysis_server/src/protocol_server.dart'; +import 'package:analysis_server/src/services/correction/fix.dart'; +import 'package:analyzer_plugin/utilities/fixes/fixes.dart'; +import 'package:test/test.dart'; +import 'package:test_reflective_loader/test_reflective_loader.dart'; + +import 'fix_processor.dart'; + +main() { + defineReflectiveSuite(() { + defineReflectiveTests(CreateMissingOverridesTest); + }); +} + +@reflectiveTest +class CreateMissingOverridesTest extends FixProcessorTest { + @override + FixKind get kind => DartFixKind.CREATE_MISSING_OVERRIDES; + + test_field_untyped() async { + await resolveTestUnit(''' +class A { + var f; +} + +class B implements A { +} +'''); + await assertHasFix(''' +class A { + var f; +} + +class B implements A { + @override + var f; +} +'''); + } + + test_functionTypeAlias() async { + await resolveTestUnit(''' +typedef int Binary(int left, int right); + +abstract class Emulator { + void performBinary(Binary binary); +} + +class MyEmulator extends Emulator { +} +'''); + await assertHasFix(''' +typedef int Binary(int left, int right); + +abstract class Emulator { + void performBinary(Binary binary); +} + +class MyEmulator extends Emulator { + @override + void performBinary(Binary binary) { + // TODO: implement performBinary + } +} +'''); + } + + test_functionTypedParameter() async { + await resolveTestUnit(''' +abstract class A { + void forEach(int f(double p1, String p2)); +} + +class B extends A { +} +'''); + await assertHasFix(''' +abstract class A { + void forEach(int f(double p1, String p2)); +} + +class B extends A { + @override + void forEach(int Function(double p1, String p2) f) { + // TODO: implement forEach + } +} +'''); + } + + test_generics_typeArguments() async { + await resolveTestUnit(''' +class Iterator<T> { +} + +abstract class IterableMixin<T> { + Iterator<T> get iterator; +} + +class Test extends IterableMixin<int> { +} +'''); + await assertHasFix(''' +class Iterator<T> { +} + +abstract class IterableMixin<T> { + Iterator<T> get iterator; +} + +class Test extends IterableMixin<int> { + @override + // TODO: implement iterator + Iterator<int> get iterator => null; +} +'''); + } + + test_generics_typeParameters() async { + await resolveTestUnit(''' +abstract class ItemProvider<T> { + List<T> getItems(); +} + +class Test<V> extends ItemProvider<V> { +} +'''); + await assertHasFix(''' +abstract class ItemProvider<T> { + List<T> getItems(); +} + +class Test<V> extends ItemProvider<V> { + @override + List<V> getItems() { + // TODO: implement getItems + return null; + } +} +'''); + } + + test_getter() async { + await resolveTestUnit(''' +abstract class A { + get g1; + int get g2; +} + +class B extends A { +} +'''); + await assertHasFix(''' +abstract class A { + get g1; + int get g2; +} + +class B extends A { + @override + // TODO: implement g1 + get g1 => null; + + @override + // TODO: implement g2 + int get g2 => null; +} +'''); + } + + test_importPrefix() async { + await resolveTestUnit(''' +import 'dart:async' as aaa; +abstract class A { + Map<aaa.Future, List<aaa.Future>> g(aaa.Future p); +} + +class B extends A { +} +'''); + await assertHasFix(''' +import 'dart:async' as aaa; +abstract class A { + Map<aaa.Future, List<aaa.Future>> g(aaa.Future p); +} + +class B extends A { + @override + Map<aaa.Future, List<aaa.Future>> g(aaa.Future p) { + // TODO: implement g + return null; + } +} +'''); + } + + test_mergeToField_getterSetter() async { + await resolveTestUnit(''' +class A { + int ma; + void mb() {} + double mc; +} + +class B implements A { +} +'''); + await assertHasFix(''' +class A { + int ma; + void mb() {} + double mc; +} + +class B implements A { + @override + int ma; + + @override + double mc; + + @override + void mb() { + // TODO: implement mb + } +} +'''); + } + + test_method() async { + await resolveTestUnit(''' +abstract class A { + void m1(); + int m2(); + String m3(int p1, double p2, Map<int, List<String>> p3); + String m4(p1, p2); + String m5(p1, [int p2 = 2, int p3, p4 = 4]); + String m6(p1, {int p2 = 2, int p3, p4: 4}); +} + +class B extends A { +} +'''); + String expectedCode = ''' +abstract class A { + void m1(); + int m2(); + String m3(int p1, double p2, Map<int, List<String>> p3); + String m4(p1, p2); + String m5(p1, [int p2 = 2, int p3, p4 = 4]); + String m6(p1, {int p2 = 2, int p3, p4: 4}); +} + +class B extends A { + @override + void m1() { + // TODO: implement m1 + } + + @override + int m2() { + // TODO: implement m2 + return null; + } + + @override + String m3(int p1, double p2, Map<int, List<String>> p3) { + // TODO: implement m3 + return null; + } + + @override + String m4(p1, p2) { + // TODO: implement m4 + return null; + } + + @override + String m5(p1, [int p2 = 2, int p3, p4 = 4]) { + // TODO: implement m5 + return null; + } + + @override + String m6(p1, {int p2 = 2, int p3, p4 = 4}) { + // TODO: implement m6 + return null; + } +} +'''; + await assertHasFix(expectedCode); + { + // end position should be on "m1", not on "m2", "m3", etc. + Position endPosition = change.selection; + expect(endPosition, isNotNull); + expect(endPosition.file, testFile); + int endOffset = endPosition.offset; + String endString = expectedCode.substring(endOffset, endOffset + 25); + expect(endString, contains('m1')); + expect(endString, isNot(contains('m2'))); + expect(endString, isNot(contains('m3'))); + expect(endString, isNot(contains('m4'))); + expect(endString, isNot(contains('m5'))); + expect(endString, isNot(contains('m6'))); + } + } + + test_method_emptyClassBody() async { + await resolveTestUnit(''' +abstract class A { + void foo(); +} + +class B extends A {} +'''); + await assertHasFix(''' +abstract class A { + void foo(); +} + +class B extends A { + @override + void foo() { + // TODO: implement foo + } +} +'''); + } + + test_method_generic() async { + await resolveTestUnit(''' +class C<T> {} +class V<E> {} + +abstract class A { + E1 foo<E1, E2 extends C<int>>(V<E2> v); +} + +class B implements A { +} +'''); + await assertHasFix(''' +class C<T> {} +class V<E> {} + +abstract class A { + E1 foo<E1, E2 extends C<int>>(V<E2> v); +} + +class B implements A { + @override + E1 foo<E1, E2 extends C<int>>(V<E2> v) { + // TODO: implement foo + return null; + } +} +'''); + } + + test_method_generic_withBounds() async { + // https://github.com/dart-lang/sdk/issues/31199 + await resolveTestUnit(''' +abstract class A<K, V> { + List<T> foo<T extends V>(K key); +} + +class B<K, V> implements A<K, V> { +} +'''); + await assertHasFix(''' +abstract class A<K, V> { + List<T> foo<T extends V>(K key); +} + +class B<K, V> implements A<K, V> { + @override + List<T> foo<T extends V>(K key) { + // TODO: implement foo + return null; + } +} +'''); + } + + test_method_genericClass2() async { + await resolveTestUnit(''' +class A<R> { + R foo(int a) => null; +} + +class B<R> extends A<R> { + R bar(double b) => null; +} + +class X implements B<bool> { +} +'''); + await assertHasFix(''' +class A<R> { + R foo(int a) => null; +} + +class B<R> extends A<R> { + R bar(double b) => null; +} + +class X implements B<bool> { + @override + bool bar(double b) { + // TODO: implement bar + return null; + } + + @override + bool foo(int a) { + // TODO: implement foo + return null; + } +} +'''); + } + + test_method_notEmptyClassBody() async { + await resolveTestUnit(''' +abstract class A { + void foo(); +} + +class B extends A { + void bar() {} +} +'''); + await assertHasFix(''' +abstract class A { + void foo(); +} + +class B extends A { + void bar() {} + + @override + void foo() { + // TODO: implement foo + } +} +'''); + } + + test_operator() async { + await resolveTestUnit(''' +abstract class A { + int operator [](int index); + void operator []=(int index, String value); +} + +class B extends A { +} +'''); + await assertHasFix(''' +abstract class A { + int operator [](int index); + void operator []=(int index, String value); +} + +class B extends A { + @override + int operator [](int index) { + // TODO: implement [] + return null; + } + + @override + void operator []=(int index, String value) { + // TODO: implement []= + } +} +'''); + } + + test_setter() async { + await resolveTestUnit(''' +abstract class A { + set s1(x); + set s2(int x); + void set s3(String x); +} + +class B extends A { +} +'''); + await assertHasFix(''' +abstract class A { + set s1(x); + set s2(int x); + void set s3(String x); +} + +class B extends A { + @override + void set s1(x) { + // TODO: implement s1 + } + + @override + void set s2(int x) { + // TODO: implement s2 + } + + @override + void set s3(String x) { + // TODO: implement s3 + } +} +'''); + } +}
diff --git a/pkg/analysis_server/test/src/services/correction/fix/create_mixin_test.dart b/pkg/analysis_server/test/src/services/correction/fix/create_mixin_test.dart new file mode 100644 index 0000000..463f417 --- /dev/null +++ b/pkg/analysis_server/test/src/services/correction/fix/create_mixin_test.dart
@@ -0,0 +1,160 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:analysis_server/src/services/correction/fix.dart'; +import 'package:analyzer/src/error/codes.dart'; +import 'package:analyzer_plugin/utilities/fixes/fixes.dart'; +import 'package:test/test.dart'; +import 'package:test_reflective_loader/test_reflective_loader.dart'; + +import 'fix_processor.dart'; + +main() { + defineReflectiveSuite(() { + defineReflectiveTests(CreateMixinTest); + }); +} + +@reflectiveTest +class CreateMixinTest extends FixProcessorTest { + @override + FixKind get kind => DartFixKind.CREATE_MIXIN; + + test_hasUnresolvedPrefix() async { + await resolveTestUnit(''' +main() { + prefix.Test v = null; + print(v); +} +'''); + await assertNoFix(); + } + + test_inLibraryOfPrefix() async { + String libCode = r''' +class A {} +'''; + addSource('/home/test/lib/lib.dart', libCode); + await resolveTestUnit(''' +import 'lib.dart' as lib; + +main() { + lib.A a = null; + lib.Test t = null; + print('\$a \$t'); +} +'''); + await assertHasFix(''' +class A {} + +mixin Test { +} +''', target: '/home/test/lib/lib.dart'); + expect(change.linkedEditGroups, hasLength(1)); + } + + test_innerLocalFunction() async { + await resolveTestUnit(''' +f() { + g() { + Test v = null; + print(v); + } + g(); +} +'''); + await assertHasFix(''' +f() { + g() { + Test v = null; + print(v); + } + g(); +} + +mixin Test { +} +'''); + assertLinkedGroup(change.linkedEditGroups[0], ['Test v =', 'Test {']); + } + + test_instanceCreation_withNew() async { + await resolveTestUnit(''' +main() { + new Test(); +} +'''); + await assertNoFix(); + } + + test_instanceCreation_withoutNew() async { + await resolveTestUnit(''' +main() { + Test(); +} +'''); + await assertNoFix(); + } + + test_itemOfList() async { + await resolveTestUnit(''' +main() { + var a = [Test]; + print(a); +} +'''); + await assertHasFix(''' +main() { + var a = [Test]; + print(a); +} + +mixin Test { +} +'''); + assertLinkedGroup(change.linkedEditGroups[0], ['Test];', 'Test {']); + } + + test_itemOfList_inAnnotation() async { + await resolveTestUnit(''' +class MyAnnotation { + const MyAnnotation(a, b); +} +@MyAnnotation(int, const [Test]) +main() {} +'''); + await assertHasFix(''' +class MyAnnotation { + const MyAnnotation(a, b); +} +@MyAnnotation(int, const [Test]) +main() {} + +mixin Test { +} +''', errorFilter: (error) { + return error.errorCode == StaticWarningCode.UNDEFINED_IDENTIFIER; + }); + assertLinkedGroup(change.linkedEditGroups[0], ['Test])', 'Test {']); + } + + test_simple() async { + await resolveTestUnit(''' +main() { + Test v = null; + print(v); +} +'''); + await assertHasFix(''' +main() { + Test v = null; + print(v); +} + +mixin Test { +} +'''); + assertLinkedGroup(change.linkedEditGroups[0], ['Test v =', 'Test {']); + } +}
diff --git a/pkg/analysis_server/test/src/services/correction/fix/create_no_such_method_test.dart b/pkg/analysis_server/test/src/services/correction/fix/create_no_such_method_test.dart new file mode 100644 index 0000000..5799c31 --- /dev/null +++ b/pkg/analysis_server/test/src/services/correction/fix/create_no_such_method_test.dart
@@ -0,0 +1,57 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:analysis_server/src/services/correction/fix.dart'; +import 'package:analyzer_plugin/utilities/fixes/fixes.dart'; +import 'package:test_reflective_loader/test_reflective_loader.dart'; + +import 'fix_processor.dart'; + +main() { + defineReflectiveSuite(() { + defineReflectiveTests(CreateNoSuchMethodTest); + }); +} + +@reflectiveTest +class CreateNoSuchMethodTest extends FixProcessorTest { + @override + FixKind get kind => DartFixKind.CREATE_NO_SUCH_METHOD; + + test_class() async { + await resolveTestUnit(''' +abstract class A { + m1(); + int m2(); +} + +class B extends A { + existing() {} +} +'''); + await assertHasFix(''' +abstract class A { + m1(); + int m2(); +} + +class B extends A { + existing() {} + + noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation); +} +'''); + } + + test_classTypeAlias() async { + await resolveTestUnit(''' +abstract class A { + m(); +} + +class B = Object with A; +'''); + await assertNoFix(); + } +}
diff --git a/pkg/analysis_server/test/src/services/correction/fix/extend_class_for_mixin_test.dart b/pkg/analysis_server/test/src/services/correction/fix/extend_class_for_mixin_test.dart new file mode 100644 index 0000000..d65e90a --- /dev/null +++ b/pkg/analysis_server/test/src/services/correction/fix/extend_class_for_mixin_test.dart
@@ -0,0 +1,79 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:analysis_server/src/services/correction/fix.dart'; +import 'package:analyzer_plugin/utilities/fixes/fixes.dart'; +import 'package:test_reflective_loader/test_reflective_loader.dart'; + +import 'fix_processor.dart'; + +main() { + defineReflectiveSuite(() { + defineReflectiveTests(ExtendClassForMixinTest); + }); +} + +@reflectiveTest +class ExtendClassForMixinTest extends FixProcessorTest { + @override + FixKind get kind => DartFixKind.EXTEND_CLASS_FOR_MIXIN; + + test_missingClass_withExtends() async { + await resolveTestUnit(''' +class A {} +class B {} +mixin M on B {} +class C extends A with M {} +'''); + await assertNoFix(); + } + + test_missingClass_withoutExtends_withImplements() async { + await resolveTestUnit(''' +class A {} +class B {} +mixin M on B {} +class C with M implements A {} +'''); + await assertHasFix(''' +class A {} +class B {} +mixin M on B {} +class C extends B with M implements A {} +'''); + } + + test_missingClass_withoutExtends_withoutImplements() async { + await resolveTestUnit(''' +class A {} +mixin M on A {} +class C with M {} +'''); + await assertHasFix(''' +class A {} +mixin M on A {} +class C extends A with M {} +'''); + } + + test_missingMixin_withExtends() async { + await resolveTestUnit(''' +class A {} +mixin M {} +mixin N on M {} +class C extends A with N {} +'''); + await assertNoFix(); + } + + @failingTest + test_missingMixin_withoutExtends() async { + await resolveTestUnit(''' +mixin M {} +mixin N on M {} +class C with N {} +'''); + await assertNoFix(); + } +}
diff --git a/pkg/analysis_server/test/src/services/correction/fix/fix_processor.dart b/pkg/analysis_server/test/src/services/correction/fix/fix_processor.dart new file mode 100644 index 0000000..76cc4ce --- /dev/null +++ b/pkg/analysis_server/test/src/services/correction/fix/fix_processor.dart
@@ -0,0 +1,265 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'dart:async'; + +import 'package:analysis_server/plugin/edit/fix/fix_core.dart'; +import 'package:analysis_server/src/services/correction/fix.dart'; +import 'package:analysis_server/src/services/correction/fix_internal.dart'; +import 'package:analyzer/error/error.dart'; +import 'package:analyzer/src/dart/error/lint_codes.dart'; +import 'package:analyzer_plugin/protocol/protocol_common.dart' + hide AnalysisError; +import 'package:analyzer_plugin/utilities/fixes/fixes.dart'; +import 'package:test/test.dart'; + +import '../../../../abstract_single_unit.dart'; + +/// A base class defining support for writing fix processor tests that are +/// specific to fixes associated with lints that use the FixKind. +abstract class FixProcessorLintTest extends FixProcessorTest { + /// Return the lint code being tested. + String get lintCode; + + /// Find the error that is to be fixed by computing the errors in the file, + /// using the [errorFilter] to filter out errors that should be ignored, and + /// expecting that there is a single remaining error. The error filter should + /// return `true` if the error should not be ignored. + Future<AnalysisError> _findErrorToFix( + bool Function(AnalysisError) errorFilter, + {int length}) async { + int index = testCode.indexOf('/*LINT*/'); + if (index < 0) { + fail('Missing "/*LINT*/" marker'); + } + return new AnalysisError(testSource, index + '/*LINT*/'.length, length ?? 0, + new LintCode(lintCode, '<ignored>')); + } +} + +/// A base class defining support for writing fix processor tests. +abstract class FixProcessorTest extends AbstractSingleUnitTest { + /// The errors in the file for which fixes are being computed. + List<AnalysisError> _errors; + + /// The source change associated with the fix that was found, or `null` if + /// neither [assertHasFix] nor [assertHasFixAllFix] has been invoked. + SourceChange change; + + /// The result of applying the [change] to the file content, or `null` if + /// neither [assertHasFix] nor [assertHasFixAllFix] has been invoked. + String resultCode; + + /// Return the kind of fixes being tested by this test class. + FixKind get kind; + + Future<void> assertHasFix(String expected, + {bool Function(AnalysisError) errorFilter, + int length, + String target}) async { + AnalysisError error = await _findErrorToFix(errorFilter, length: length); + Fix fix = await _assertHasFix(error); + change = fix.change; + + // apply to "file" + List<SourceFileEdit> fileEdits = change.edits; + expect(fileEdits, hasLength(1)); + + String fileContent = testCode; + if (target != null) { + expect(fileEdits.first.file, convertPath(target)); + fileContent = getFile(target).readAsStringSync(); + } + + resultCode = SourceEdit.applySequence(fileContent, change.edits[0].edits); + expect(resultCode, expected); + } + + assertHasFixAllFix(ErrorCode errorCode, String expected, + {String target}) async { + AnalysisError error = await _findErrorToFixOfType(errorCode); + Fix fix = await _assertHasFixAllFix(error); + change = fix.change; + + // apply to "file" + List<SourceFileEdit> fileEdits = change.edits; + expect(fileEdits, hasLength(1)); + + String fileContent = testCode; + if (target != null) { + expect(fileEdits.first.file, convertPath(target)); + fileContent = getFile(target).readAsStringSync(); + } + + resultCode = SourceEdit.applySequence(fileContent, change.edits[0].edits); + expect(resultCode, expected); + } + + Future<void> assertHasFixWithoutApplying( + {bool Function(AnalysisError) errorFilter}) async { + AnalysisError error = await _findErrorToFix(errorFilter); + Fix fix = await _assertHasFix(error); + change = fix.change; + } + + void assertLinkedGroup(LinkedEditGroup group, List<String> expectedStrings, + [List<LinkedEditSuggestion> expectedSuggestions]) { + List<Position> expectedPositions = _findResultPositions(expectedStrings); + expect(group.positions, unorderedEquals(expectedPositions)); + if (expectedSuggestions != null) { + expect(group.suggestions, unorderedEquals(expectedSuggestions)); + } + } + + /// Compute fixes for all of the errors in the test file to effectively assert + /// that no exceptions will be thrown by doing so. + Future<void> assertNoExceptions() async { + List<AnalysisError> errors = await _computeErrors(); + for (var error in errors) { + await _computeFixes(error); + } + } + + /// Compute fixes and ensure that there is no fix of the [kind] being tested by + /// this class. + Future<void> assertNoFix({bool Function(AnalysisError) errorFilter}) async { + AnalysisError error = await _findErrorToFix(errorFilter); + await _assertNoFix(error); + } + + List<LinkedEditSuggestion> expectedSuggestions( + LinkedEditSuggestionKind kind, List<String> values) { + return values.map((value) { + return new LinkedEditSuggestion(value, kind); + }).toList(); + } + + @override + void setUp() { + super.setUp(); + verifyNoTestUnitErrors = false; + } + + /// Computes fixes and verifies that there is a fix for the given [error] of + /// the appropriate kind. + Future<Fix> _assertHasFix(AnalysisError error) async { + // Compute the fixes for this AnalysisError + final List<Fix> fixes = await _computeFixes(error); + + // Assert that none of the fixes are a fix-all fix. + Fix foundFix = null; + for (Fix fix in fixes) { + if (fix.isFixAllFix()) { + fail('A fix-all fix was found for the error: $error ' + 'in the computed set of fixes:\n${fixes.join('\n')}'); + } else if (fix.kind == kind) { + foundFix ??= fix; + } + } + if (foundFix == null) { + fail('Expected to find fix $kind in\n${fixes.join('\n')}'); + } + return foundFix; + } + + /// Computes fixes and verifies that there is a fix for the given [error] of + /// the appropriate kind. + Future<Fix> _assertHasFixAllFix(AnalysisError error) async { + if (!kind.canBeAppliedTogether()) { + fail('Expected to find and return fix-all FixKind for $kind, ' + 'but kind.canBeAppliedTogether is ${kind.canBeAppliedTogether}'); + } + + // Compute the fixes for the error. + List<Fix> fixes = await _computeFixes(error); + + // Assert that there exists such a fix in the list. + Fix foundFix = null; + for (Fix fix in fixes) { + if (fix.kind == kind && fix.isFixAllFix()) { + foundFix = fix; + break; + } + } + if (foundFix == null) { + fail('No fix-all fix was found for the error: $error ' + 'in the computed set of fixes:\n${fixes.join('\n')}'); + } + return foundFix; + } + + Future<void> _assertNoFix(AnalysisError error) async { + List<Fix> fixes = await _computeFixes(error); + for (Fix fix in fixes) { + if (fix.kind == kind) { + fail('Unexpected fix $kind in\n${fixes.join('\n')}'); + } + } + } + + Future<List<AnalysisError>> _computeErrors() async { + if (_errors == null) { + if (testAnalysisResult != null) { + _errors = testAnalysisResult.errors; + } + if (_errors == null) { + var result = await session.getResolvedUnit(testFile); + _errors = result.errors; + } + } + return _errors; + } + + /// Computes fixes for the given [error] in [testUnit]. + Future<List<Fix>> _computeFixes(AnalysisError error) async { + var context = new DartFixContextImpl(testAnalysisResult, error); + return await new DartFixContributor().computeFixes(context); + } + + /// Find the error that is to be fixed by computing the errors in the file, + /// using the [errorFilter] to filter out errors that should be ignored, and + /// expecting that there is a single remaining error. The error filter should + /// return `true` if the error should not be ignored. + Future<AnalysisError> _findErrorToFix( + bool Function(AnalysisError) errorFilter, + {int length}) async { + List<AnalysisError> errors = await _computeErrors(); + if (errorFilter != null) { + if (errors.length == 1) { + fail('Unnecessary error filter'); + } + errors = errors.where(errorFilter).toList(); + } + if (errors.length == 0) { + fail('Expected one error, found: none'); + } else if (errors.length > 1) { + StringBuffer buffer = new StringBuffer(); + buffer.writeln('Expected one error, found:'); + for (AnalysisError error in errors) { + buffer.writeln(' $error [${error.errorCode}]'); + } + fail(buffer.toString()); + } + return errors[0]; + } + + Future<AnalysisError> _findErrorToFixOfType(ErrorCode errorCode) async { + List<AnalysisError> errors = await _computeErrors(); + for (AnalysisError error in errors) { + if (error.errorCode == errorCode) { + return error; + } + } + return null; + } + + List<Position> _findResultPositions(List<String> searchStrings) { + List<Position> positions = <Position>[]; + for (String search in searchStrings) { + int offset = resultCode.indexOf(search); + positions.add(new Position(testFile, offset)); + } + return positions; + } +}
diff --git a/pkg/analysis_server/test/src/services/correction/fix/fix_test.dart b/pkg/analysis_server/test/src/services/correction/fix/fix_test.dart new file mode 100644 index 0000000..655614c --- /dev/null +++ b/pkg/analysis_server/test/src/services/correction/fix/fix_test.dart
@@ -0,0 +1,29 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:analyzer_plugin/utilities/fixes/fixes.dart'; +import 'package:test/test.dart'; +import 'package:test_reflective_loader/test_reflective_loader.dart'; + +import 'fix_processor.dart'; + +main() { + defineReflectiveSuite(() { + defineReflectiveTests(FixTest); + }); +} + +@reflectiveTest +class FixTest extends FixProcessorTest { + @override + FixKind get kind => fail('kind should not be requested'); + + test_malformedTypeTest() async { + await resolveTestUnit(''' +main(p) { + p i s Null; +}'''); + await assertNoExceptions(); + } +}
diff --git a/pkg/analysis_server/test/src/services/correction/fix/import_async_test.dart b/pkg/analysis_server/test/src/services/correction/fix/import_async_test.dart new file mode 100644 index 0000000..7bd9141 --- /dev/null +++ b/pkg/analysis_server/test/src/services/correction/fix/import_async_test.dart
@@ -0,0 +1,51 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:analysis_server/src/services/correction/fix.dart'; +import 'package:analyzer_plugin/utilities/fixes/fixes.dart'; +import 'package:test_reflective_loader/test_reflective_loader.dart'; + +import 'fix_processor.dart'; + +main() { + defineReflectiveSuite(() { + defineReflectiveTests(ImportAsyncTest); + }); +} + +@reflectiveTest +class ImportAsyncTest extends FixProcessorTest { + @override + FixKind get kind => DartFixKind.IMPORT_ASYNC; + + test_future() async { + updateTestPubspecFile(''' +environment: + sdk: ^2.0.0 +'''); + await resolveTestUnit(''' +Future<int> zero() async => 0; +'''); + await assertHasFix(''' +import 'dart:async'; + +Future<int> zero() async => 0; +'''); + } + + test_stream() async { + updateTestPubspecFile(''' +environment: + sdk: ^2.0.0 +'''); + await resolveTestUnit(''' +Stream<int> zero() => null; +'''); + await assertHasFix(''' +import 'dart:async'; + +Stream<int> zero() => null; +'''); + } +}
diff --git a/pkg/analysis_server/test/src/services/correction/fix/import_library_prefix_test.dart b/pkg/analysis_server/test/src/services/correction/fix/import_library_prefix_test.dart new file mode 100644 index 0000000..af0bbbe --- /dev/null +++ b/pkg/analysis_server/test/src/services/correction/fix/import_library_prefix_test.dart
@@ -0,0 +1,57 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:analysis_server/src/services/correction/fix.dart'; +import 'package:analyzer_plugin/utilities/fixes/fixes.dart'; +import 'package:test_reflective_loader/test_reflective_loader.dart'; + +import 'fix_processor.dart'; + +main() { + defineReflectiveSuite(() { + defineReflectiveTests(ImportLibraryPrefixTest); + }); +} + +@reflectiveTest +class ImportLibraryPrefixTest extends FixProcessorTest { + @override + FixKind get kind => DartFixKind.IMPORT_LIBRARY_PREFIX; + + test_withClass() async { + await resolveTestUnit(''' +import 'dart:collection' as pref; +main() { + pref.HashMap s = null; + LinkedHashMap f = null; + print('\$s \$f'); +} +'''); + await assertHasFix(''' +import 'dart:collection' as pref; +main() { + pref.HashMap s = null; + pref.LinkedHashMap f = null; + print('\$s \$f'); +} +'''); + } + + test_withTopLevelVariable() async { + await resolveTestUnit(''' +import 'dart:math' as pref; +main() { + print(pref.E); + print(PI); +} +'''); + await assertHasFix(''' +import 'dart:math' as pref; +main() { + print(pref.E); + print(pref.PI); +} +'''); + } +}
diff --git a/pkg/analysis_server/test/src/services/correction/fix/import_library_project_test.dart b/pkg/analysis_server/test/src/services/correction/fix/import_library_project_test.dart new file mode 100644 index 0000000..68d5820 --- /dev/null +++ b/pkg/analysis_server/test/src/services/correction/fix/import_library_project_test.dart
@@ -0,0 +1,485 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:analysis_server/src/services/correction/fix.dart'; +import 'package:analyzer_plugin/utilities/fixes/fixes.dart'; +import 'package:test_reflective_loader/test_reflective_loader.dart'; + +import 'fix_processor.dart'; + +main() { + defineReflectiveSuite(() { + defineReflectiveTests(ImportLibraryProject1Test); + defineReflectiveTests(ImportLibraryProject2Test); + defineReflectiveTests(ImportLibraryProject3Test); + }); +} + +@reflectiveTest +class ImportLibraryProject1Test extends FixProcessorTest + with ImportLibraryTestMixin { + @override + FixKind get kind => DartFixKind.IMPORT_LIBRARY_PROJECT1; + + test_alreadyImported_package() async { + addSource('/home/test/lib/lib.dart', ''' +class A {} +class B {} +'''); + await resolveTestUnit(''' +import 'lib.dart' show A; +main() { + A a; + B b; + print('\$a \$b'); +} +'''); + await assertNoFix(); + } + + test_notInLib() async { + addSource('/home/other/test/lib.dart', 'class Test {}'); + await resolveTestUnit(''' +main() { + Test t; + print(t); +} +'''); + await assertNoFix(); + } + + test_preferDirectOverExport() async { + _configureMyPkg({'b.dart': 'class Test {}', 'a.dart': "export 'b.dart';"}); + await resolveTestUnit(''' +main() { + Test test = null; + print(test); +} +'''); + await assertHasFix(''' +import 'package:my_pkg/b.dart'; + +main() { + Test test = null; + print(test); +} +'''); + } + + test_preferDirectOverExport_src() async { + _configureMyPkg({'b.dart': 'class Test {}', 'a.dart': "export 'b.dart';"}); + await resolveTestUnit(''' +main() { + Test test = null; + print(test); +} +'''); + await assertHasFix(''' +import 'package:my_pkg/b.dart'; + +main() { + Test test = null; + print(test); +} +'''); + } + + test_withClass_annotation() async { + addSource('/home/test/lib/lib.dart', ''' +library lib; +class Test { + const Test(int p); +} +'''); + await resolveTestUnit(''' +@Test(0) +main() { +} +'''); + await assertHasFix(''' +import 'package:test/lib.dart'; + +@Test(0) +main() { +} +'''); + } + + test_withClass_hasOtherLibraryWithPrefix() async { + addSource('/home/test/lib/a.dart', ''' +library a; +class One {} +'''); + addSource('/home/test/lib/b.dart', ''' +library b; +class One {} +class Two {} +'''); + await resolveTestUnit(''' +import 'package:test/b.dart' show Two; +main () { + new Two(); + new One(); +} +'''); + await assertHasFix(''' +import 'package:test/a.dart'; +import 'package:test/b.dart' show Two; +main () { + new Two(); + new One(); +} +'''); + } + + test_withClass_inParentFolder() async { + testFile = convertPath('/home/test/bin/aaa/test.dart'); + addSource('/home/test/bin/lib.dart', ''' +library lib; +class Test {} +'''); + await resolveTestUnit(''' +main() { + Test t = null; + print(t); +} +'''); + await assertHasFix(''' +import '../lib.dart'; + +main() { + Test t = null; + print(t); +} +'''); + } + + test_withClass_inRelativeFolder() async { + testFile = convertPath('/home/test/bin/test.dart'); + addSource('/home/test/tool/sub/folder/lib.dart', ''' +library lib; +class Test {} +'''); + await resolveTestUnit(''' +main() { + Test t = null; + print(t); +} +'''); + await assertHasFix(''' +import '../tool/sub/folder/lib.dart'; + +main() { + Test t = null; + print(t); +} +'''); + } + + test_withClass_inSameFolder() async { + testFile = convertPath('/home/test/bin/test.dart'); + addSource('/home/test/bin/lib.dart', ''' +library lib; +class Test {} +'''); + await resolveTestUnit(''' +main() { + Test t = null; + print(t); +} +'''); + await assertHasFix(''' +import 'lib.dart'; + +main() { + Test t = null; + print(t); +} +'''); + } + + test_withClass_instanceCreation_const() async { + addSource('/home/test/lib/lib.dart', ''' +class Test { + const Test(); +} +'''); + await resolveTestUnit(''' +main() { + return const Test(); +} +'''); + await assertHasFix(''' +import 'package:test/lib.dart'; + +main() { + return const Test(); +} +'''); + } + + test_withClass_instanceCreation_const_namedConstructor() async { + addSource('/home/test/lib/lib.dart', ''' +class Test { + const Test.named(); +} +'''); + await resolveTestUnit(''' +main() { + const Test.named(); +} +'''); + await assertHasFix(''' +import 'package:test/lib.dart'; + +main() { + const Test.named(); +} +'''); + } + + test_withClass_instanceCreation_implicit() async { + addSource('/home/test/lib/lib.dart', ''' +class Test { + const Test(); +} +'''); + await resolveTestUnit(''' +main() { + return Test(); +} +'''); + await assertHasFix(''' +import 'package:test/lib.dart'; + +main() { + return Test(); +} +'''); + } + + test_withClass_instanceCreation_new() async { + addSource('/home/test/lib/lib.dart', ''' +class Test { + const Test(); +} +'''); + await resolveTestUnit(''' +main() { + return new Test(); +} +'''); + await assertHasFix(''' +import 'package:test/lib.dart'; + +main() { + return new Test(); +} +'''); + } + + test_withClass_instanceCreation_new_namedConstructor() async { + addSource('/home/test/lib/lib.dart', ''' +class Test { + Test.named(); +} +'''); + await resolveTestUnit(''' +main() { + new Test.named(); +} +'''); + await assertHasFix(''' +import 'package:test/lib.dart'; + +main() { + new Test.named(); +} +'''); + } + + test_withFunction() async { + addSource('/home/test/lib/lib.dart', ''' +library lib; +myFunction() {} +'''); + await resolveTestUnit(''' +main() { + myFunction(); +} +'''); + await assertHasFix(''' +import 'package:test/lib.dart'; + +main() { + myFunction(); +} +'''); + } + + test_withFunction_unresolvedMethod() async { + addSource('/home/test/lib/lib.dart', ''' +library lib; +myFunction() {} +'''); + await resolveTestUnit(''' +class A { + main() { + myFunction(); + } +} +'''); + await assertHasFix(''' +import 'package:test/lib.dart'; + +class A { + main() { + myFunction(); + } +} +'''); + } + + test_withFunctionTypeAlias() async { + addSource('/home/test/lib/lib.dart', ''' +library lib; +typedef MyFunction(); +'''); + await resolveTestUnit(''' +main() { + MyFunction t = null; + print(t); +} +'''); + await assertHasFix(''' +import 'package:test/lib.dart'; + +main() { + MyFunction t = null; + print(t); +} +'''); + } + + test_withTopLevelVariable() async { + addSource('/home/test/lib/lib.dart', ''' +library lib; +int MY_VAR = 42; +'''); + await resolveTestUnit(''' +main() { + print(MY_VAR); +} +'''); + await assertHasFix(''' +import 'package:test/lib.dart'; + +main() { + print(MY_VAR); +} +'''); + } +} + +@reflectiveTest +class ImportLibraryProject2Test extends FixProcessorTest + with ImportLibraryTestMixin { + @override + FixKind get kind => DartFixKind.IMPORT_LIBRARY_PROJECT2; + + test_preferDirectOverExport() async { + _configureMyPkg({ + 'b.dart': 'class Test {}', + 'a.dart': "export 'b.dart';", + }); + await resolveTestUnit(''' +main() { + Test test = null; + print(test); +} +'''); + await assertHasFix(''' +import 'package:my_pkg/a.dart'; + +main() { + Test test = null; + print(test); +} +'''); + } + + test_preferDirectOverExport_src() async { + _configureMyPkg({ + 'b.dart': 'class Test {}', + 'a.dart': "export 'b.dart';", + }); + await resolveTestUnit(''' +main() { + Test test = null; + print(test); +} +'''); + await assertHasFix(''' +import 'package:my_pkg/a.dart'; + +main() { + Test test = null; + print(test); +} +'''); + } +} + +@reflectiveTest +class ImportLibraryProject3Test extends FixProcessorTest { + @override + FixKind get kind => DartFixKind.IMPORT_LIBRARY_PROJECT3; + + test_inLibSrc_differentContextRoot() async { + addPackageFile('bbb', 'b1.dart', r''' +import 'src/b2.dart'; +class A {} +'''); + addPackageFile('bbb', 'src/b2.dart', 'class Test {}'); + await resolveTestUnit(''' +import 'package:bbb/b1.dart'; +main() { + Test t; + A a; + print('\$t \$a'); +} +'''); + await assertNoFix(); + } + + test_inLibSrc_thisContextRoot() async { + addSource('/home/test/lib/src/lib.dart', 'class Test {}'); + await resolveTestUnit(''' +main() { + Test t; + print(t); +} +'''); + await assertHasFix(''' +import 'package:test/src/lib.dart'; + +main() { + Test t; + print(t); +} +'''); + } +} + +mixin ImportLibraryTestMixin on FixProcessorTest { + /// Configures the source factory to have a package named 'my_pkg' and for + /// the package to contain all of the files described by the [pathToCode] map. + /// The keys in the map are paths relative to the root of the package, and the + /// values are the contents of the files at those paths. + void _configureMyPkg(Map<String, String> pathToCode) { + pathToCode.forEach((path, code) { + addPackageFile('my_pkg', path, code); + }); + } +}
diff --git a/pkg/analysis_server/test/src/services/correction/fix/import_library_sdk_test.dart b/pkg/analysis_server/test/src/services/correction/fix/import_library_sdk_test.dart new file mode 100644 index 0000000..ce3dcc4 --- /dev/null +++ b/pkg/analysis_server/test/src/services/correction/fix/import_library_sdk_test.dart
@@ -0,0 +1,272 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:analysis_server/src/services/correction/fix.dart'; +import 'package:analyzer/src/error/codes.dart'; +import 'package:analyzer_plugin/utilities/fixes/fixes.dart'; +import 'package:test_reflective_loader/test_reflective_loader.dart'; + +import 'fix_processor.dart'; + +main() { + defineReflectiveSuite(() { + defineReflectiveTests(ImportLibrarySdkTest); + }); +} + +@reflectiveTest +class ImportLibrarySdkTest extends FixProcessorTest { + @override + FixKind get kind => DartFixKind.IMPORT_LIBRARY_SDK; + + test_alreadyImported_sdk() async { + await resolveTestUnit(''' +import 'dart:collection' show HashMap; +main() { + HashMap s = null; + LinkedHashMap f = null; + print('\$s \$f'); +} +'''); + await assertNoFix(); + } + + test_withClass_asExpression() async { + await resolveTestUnit(''' +main(p) { + p as HashMap; +} +'''); + await assertHasFix(''' +import 'dart:collection'; + +main(p) { + p as HashMap; +} +'''); + } + + test_withClass_instanceCreation_explicitNew() async { + await resolveTestUnit(''' +class C { + foo() { + new HashMap(); + } +} +'''); + await assertHasFix(''' +import 'dart:collection'; + +class C { + foo() { + new HashMap(); + } +} +'''); + } + + test_withClass_instanceCreation_explicitNew_namedConstructor() async { + await resolveTestUnit(''' +class C { + foo() { + new Completer.sync(0); + } +} +'''); + await assertHasFix(''' +import 'dart:async'; + +class C { + foo() { + new Completer.sync(0); + } +} +'''); + } + + test_withClass_instanceCreation_implicitNew() async { + await resolveTestUnit(''' +class C { + foo() { + HashMap(); + } +} +'''); + await assertHasFix(''' +import 'dart:collection'; + +class C { + foo() { + HashMap(); + } +} +'''); + } + + test_withClass_instanceCreation_implicitNew_namedConstructor() async { + await resolveTestUnit(''' +class C { + foo() { + Completer.sync(0); + } +} +'''); + await assertHasFix(''' +import 'dart:async'; + +class C { + foo() { + Completer.sync(0); + } +} +'''); + } + + test_withClass_invocationTarget() async { + await resolveTestUnit(''' +main() { + Timer.run(null); +} +'''); + await assertHasFix(''' +import 'dart:async'; + +main() { + Timer.run(null); +} +'''); + } + + test_withClass_IsExpression() async { + await resolveTestUnit(''' +main(p) { + p is Completer; +} +'''); + await assertHasFix(''' +import 'dart:async'; + +main(p) { + p is Completer; +} +'''); + } + + test_withClass_itemOfList() async { + await resolveTestUnit(''' +main() { + var a = [Completer]; + print(a); +} +'''); + await assertHasFix(''' +import 'dart:async'; + +main() { + var a = [Completer]; + print(a); +} +'''); + } + + test_withClass_itemOfList_inAnnotation() async { + await resolveTestUnit(''' +class MyAnnotation { + const MyAnnotation(a, b); +} +@MyAnnotation(int, const [Completer]) +main() {} +'''); + await assertHasFix(''' +import 'dart:async'; + +class MyAnnotation { + const MyAnnotation(a, b); +} +@MyAnnotation(int, const [Completer]) +main() {} +''', errorFilter: (error) { + return error.errorCode == StaticWarningCode.UNDEFINED_IDENTIFIER; + }); + } + + test_withClass_typeAnnotation() async { + await resolveTestUnit(''' +main() { + Completer f = null; + print(f); +} +'''); + await assertHasFix(''' +import 'dart:async'; + +main() { + Completer f = null; + print(f); +} +'''); + } + + test_withClass_typeAnnotation_PrefixedIdentifier() async { + await resolveTestUnit(''' +main() { + Timer.run; +} +'''); + await assertHasFix(''' +import 'dart:async'; + +main() { + Timer.run; +} +'''); + } + + test_withClass_typeArgument() async { + await resolveTestUnit(''' +main() { + List<Completer> completers = []; + print(completers); +} +'''); + await assertHasFix(''' +import 'dart:async'; + +main() { + List<Completer> completers = []; + print(completers); +} +'''); + } + + test_withTopLevelVariable() async { + await resolveTestUnit(''' +main() { + print(PI); +} +'''); + await assertHasFix(''' +import 'dart:math'; + +main() { + print(PI); +} +'''); + } + + test_withTopLevelVariable_annotation() async { + await resolveTestUnit(''' +@PI +main() { +} +'''); + await assertHasFix(''' +import 'dart:math'; + +@PI +main() { +} +'''); + } +}
diff --git a/pkg/analysis_server/test/src/services/correction/fix/import_library_show_test.dart b/pkg/analysis_server/test/src/services/correction/fix/import_library_show_test.dart new file mode 100644 index 0000000..4f3885f --- /dev/null +++ b/pkg/analysis_server/test/src/services/correction/fix/import_library_show_test.dart
@@ -0,0 +1,63 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:analysis_server/src/services/correction/fix.dart'; +import 'package:analyzer_plugin/utilities/fixes/fixes.dart'; +import 'package:test_reflective_loader/test_reflective_loader.dart'; + +import 'fix_processor.dart'; + +main() { + defineReflectiveSuite(() { + defineReflectiveTests(ImportLibraryShowTest); + }); +} + +@reflectiveTest +class ImportLibraryShowTest extends FixProcessorTest { + @override + FixKind get kind => DartFixKind.IMPORT_LIBRARY_SHOW; + + test_package() async { + addSource('/home/test/lib/lib.dart', ''' +class A {} +class B {} +'''); + await resolveTestUnit(''' +import 'lib.dart' show A; +main() { + A a; + B b; + print('\$a \$b'); +} +'''); + await assertHasFix(''' +import 'lib.dart' show A, B; +main() { + A a; + B b; + print('\$a \$b'); +} +'''); + } + + test_sdk() async { + await resolveTestUnit(''' +import 'dart:collection' show HashMap; +main() { + HashMap s = null; + LinkedHashMap f = null; + print('\$s \$f'); +} +'''); + await assertHasFix(''' +import 'dart:collection' show HashMap, LinkedHashMap; +main() { + HashMap s = null; + LinkedHashMap f = null; + print('\$s \$f'); +} +'''); + } +}
diff --git a/pkg/analysis_server/test/src/services/correction/fix/insert_semicolon_test.dart b/pkg/analysis_server/test/src/services/correction/fix/insert_semicolon_test.dart new file mode 100644 index 0000000..77123f3 --- /dev/null +++ b/pkg/analysis_server/test/src/services/correction/fix/insert_semicolon_test.dart
@@ -0,0 +1,34 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:analysis_server/src/services/correction/fix.dart'; +import 'package:analyzer_plugin/utilities/fixes/fixes.dart'; +import 'package:test_reflective_loader/test_reflective_loader.dart'; + +import 'fix_processor.dart'; + +main() { + defineReflectiveSuite(() { + defineReflectiveTests(InsertSemicolonTest); + }); +} + +@reflectiveTest +class InsertSemicolonTest extends FixProcessorTest { + @override + FixKind get kind => DartFixKind.INSERT_SEMICOLON; + + test_expectedToken_semicolon() async { + await resolveTestUnit(''' +main() { + print(0) +} +'''); + await assertHasFix(''' +main() { + print(0); +} +'''); + } +}
diff --git a/pkg/analysis_server/test/src/services/correction/fix/make_class_abstract_test.dart b/pkg/analysis_server/test/src/services/correction/fix/make_class_abstract_test.dart new file mode 100644 index 0000000..7dbf4e9 --- /dev/null +++ b/pkg/analysis_server/test/src/services/correction/fix/make_class_abstract_test.dart
@@ -0,0 +1,51 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:analysis_server/src/services/correction/fix.dart'; +import 'package:analyzer_plugin/utilities/fixes/fixes.dart'; +import 'package:test_reflective_loader/test_reflective_loader.dart'; + +import 'fix_processor.dart'; + +main() { + defineReflectiveSuite(() { + defineReflectiveTests(MakeClassAbstractTest); + }); +} + +@reflectiveTest +class MakeClassAbstractTest extends FixProcessorTest { + @override + FixKind get kind => DartFixKind.MAKE_CLASS_ABSTRACT; + + test_declaresAbstractMethod() async { + await resolveTestUnit(''' +class A { + m(); +} +'''); + await assertHasFix(''' +abstract class A { + m(); +} +'''); + } + + test_inheritsAbstractMethod() async { + await resolveTestUnit(''' +abstract class A { + m(); +} +class B extends A { +} +'''); + await assertHasFix(''' +abstract class A { + m(); +} +abstract class B extends A { +} +'''); + } +}
diff --git a/pkg/analysis_server/test/src/services/correction/fix/make_field_not_final_test.dart b/pkg/analysis_server/test/src/services/correction/fix/make_field_not_final_test.dart new file mode 100644 index 0000000..6027ac6 --- /dev/null +++ b/pkg/analysis_server/test/src/services/correction/fix/make_field_not_final_test.dart
@@ -0,0 +1,59 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:analysis_server/src/services/correction/fix.dart'; +import 'package:analyzer_plugin/utilities/fixes/fixes.dart'; +import 'package:test_reflective_loader/test_reflective_loader.dart'; + +import 'fix_processor.dart'; + +main() { + defineReflectiveSuite(() { + defineReflectiveTests(MakeFieldNotFinalTest); + }); +} + +@reflectiveTest +class MakeFieldNotFinalTest extends FixProcessorTest { + @override + FixKind get kind => DartFixKind.MAKE_FIELD_NOT_FINAL; + + test_hasType() async { + await resolveTestUnit(''' +class A { + final int fff = 1; + main() { + fff = 2; + } +} +'''); + await assertHasFix(''' +class A { + int fff = 1; + main() { + fff = 2; + } +} +'''); + } + + test_noType() async { + await resolveTestUnit(''' +class A { + final fff = 1; + main() { + fff = 2; + } +} +'''); + await assertHasFix(''' +class A { + var fff = 1; + main() { + fff = 2; + } +} +'''); + } +}
diff --git a/pkg/analysis_server/test/src/services/correction/fix/make_final_test.dart b/pkg/analysis_server/test/src/services/correction/fix/make_final_test.dart new file mode 100644 index 0000000..31bc18d --- /dev/null +++ b/pkg/analysis_server/test/src/services/correction/fix/make_final_test.dart
@@ -0,0 +1,108 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:analysis_server/src/services/correction/fix.dart'; +import 'package:analysis_server/src/services/correction/fix_internal.dart'; +import 'package:analyzer_plugin/utilities/fixes/fixes.dart'; +import 'package:test_reflective_loader/test_reflective_loader.dart'; + +import 'fix_processor.dart'; + +main() { + defineReflectiveSuite(() { + defineReflectiveTests(MakeFinalTest); + }); +} + +@reflectiveTest +class MakeFinalTest extends FixProcessorLintTest { + @override + FixKind get kind => DartFixKind.MAKE_FINAL; + + @override + String get lintCode => LintNames.prefer_final_fields; + + test_field_type() async { + await resolveTestUnit(''' +class C { + int /*LINT*/f = 2; +} +'''); + await assertHasFix(''' +class C { + final int /*LINT*/f = 2; +} +'''); + } + + test_field_var() async { + await resolveTestUnit(''' +class C { + var /*LINT*/f = 2; +} +'''); + await assertHasFix(''' +class C { + final /*LINT*/f = 2; +} +'''); + } + + test_local_type() async { + await resolveTestUnit(''' +bad() { + int /*LINT*/x = 2; +} +'''); + await assertHasFix(''' +bad() { + final int /*LINT*/x = 2; +} +'''); + } + + test_local_var() async { + await resolveTestUnit(''' +bad() { + var /*LINT*/x = 2; +} +'''); + await assertHasFix(''' +bad() { + final /*LINT*/x = 2; +} +'''); + } + + test_noKeyword() async { + await resolveTestUnit(''' +class C { + /*LINT*/f = 2; +} +'''); + await assertHasFix(''' +class C { + /*LINT*/final f = 2; +} +'''); + } + + test_topLevel_type() async { + await resolveTestUnit(''' +int /*LINT*/x = 2; +'''); + await assertHasFix(''' +final int /*LINT*/x = 2; +'''); + } + + test_topLevel_var() async { + await resolveTestUnit(''' +var /*LINT*/x = 2; +'''); + await assertHasFix(''' +final /*LINT*/x = 2; +'''); + } +}
diff --git a/pkg/analysis_server/test/src/services/correction/fix/move_type_arguments_to_class_test.dart b/pkg/analysis_server/test/src/services/correction/fix/move_type_arguments_to_class_test.dart new file mode 100644 index 0000000..b7622e9 --- /dev/null +++ b/pkg/analysis_server/test/src/services/correction/fix/move_type_arguments_to_class_test.dart
@@ -0,0 +1,123 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:analysis_server/src/services/correction/fix.dart'; +import 'package:analyzer_plugin/utilities/fixes/fixes.dart'; +import 'package:test_reflective_loader/test_reflective_loader.dart'; + +import 'fix_processor.dart'; + +main() { + defineReflectiveSuite(() { + defineReflectiveTests(MoveTypeArgumentsToClassTest); + }); +} + +@reflectiveTest +class MoveTypeArgumentsToClassTest extends FixProcessorTest { + @override + FixKind get kind => DartFixKind.MOVE_TYPE_ARGUMENTS_TO_CLASS; + + test_explicitConst() async { + await resolveTestUnit(''' +main() { + const C.named<int>(); +} +class C<E> { + const C.named(); +} +'''); + await assertHasFix(''' +main() { + const C<int>.named(); +} +class C<E> { + const C.named(); +} +'''); + } + + test_explicitNew() async { + await resolveTestUnit(''' +main() { + new C.named<int>(); +} +class C<E> { + C.named(); +} +'''); + await assertHasFix(''' +main() { + new C<int>.named(); +} +class C<E> { + C.named(); +} +'''); + } + + test_explicitNew_alreadyThere() async { + await resolveTestUnit(''' +main() { + new C<String>.named<int>(); +} +class C<E> { + C.named(); +} +'''); + await assertNoFix(); + } + + test_explicitNew_wrongNumber() async { + await resolveTestUnit(''' +main() { + new C.named<int, String>(); +} +class C<E> { + C.named(); +} +'''); + await assertNoFix(); + } + + test_implicitConst() async { + await resolveTestUnit(''' +main() { + const C c = C.named<int>(); + print(c); +} +class C<E> { + const C.named(); +} +'''); + await assertHasFix(''' +main() { + const C c = C<int>.named(); + print(c); +} +class C<E> { + const C.named(); +} +'''); + } + + test_implicitNew() async { + await resolveTestUnit(''' +main() { + C.named<int>(); +} +class C<E> { + C.named(); +} +'''); + await assertHasFix(''' +main() { + C<int>.named(); +} +class C<E> { + C.named(); +} +'''); + } +}
diff --git a/pkg/analysis_server/test/src/services/correction/fix/remove_await_test.dart b/pkg/analysis_server/test/src/services/correction/fix/remove_await_test.dart new file mode 100644 index 0000000..6121171 --- /dev/null +++ b/pkg/analysis_server/test/src/services/correction/fix/remove_await_test.dart
@@ -0,0 +1,51 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:analysis_server/src/services/correction/fix.dart'; +import 'package:analysis_server/src/services/correction/fix_internal.dart'; +import 'package:analyzer_plugin/utilities/fixes/fixes.dart'; +import 'package:test_reflective_loader/test_reflective_loader.dart'; + +import 'fix_processor.dart'; + +main() { + defineReflectiveSuite(() { + defineReflectiveTests(RemoveAwaitTest); + }); +} + +@reflectiveTest +class RemoveAwaitTest extends FixProcessorLintTest { + @override + FixKind get kind => DartFixKind.REMOVE_AWAIT; + + @override + String get lintCode => LintNames.await_only_futures; + + test_intLiteral() async { + await resolveTestUnit(''' +bad() async { + print(/*LINT*/await 23); +} +'''); + await assertHasFix(''' +bad() async { + print(/*LINT*/23); +} +'''); + } + + test_stringLiteral() async { + await resolveTestUnit(''' +bad() async { + print(/*LINT*/await 'hola'); +} +'''); + await assertHasFix(''' +bad() async { + print(/*LINT*/'hola'); +} +'''); + } +}
diff --git a/pkg/analysis_server/test/src/services/correction/fix/remove_dead_code_test.dart b/pkg/analysis_server/test/src/services/correction/fix/remove_dead_code_test.dart new file mode 100644 index 0000000..eec8f7c --- /dev/null +++ b/pkg/analysis_server/test/src/services/correction/fix/remove_dead_code_test.dart
@@ -0,0 +1,71 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:analysis_server/src/services/correction/fix.dart'; +import 'package:analyzer_plugin/utilities/fixes/fixes.dart'; +import 'package:test_reflective_loader/test_reflective_loader.dart'; + +import 'fix_processor.dart'; + +main() { + defineReflectiveSuite(() { + defineReflectiveTests(RemoveDeadCodeTest); + }); +} + +@reflectiveTest +class RemoveDeadCodeTest extends FixProcessorTest { + @override + FixKind get kind => DartFixKind.REMOVE_DEAD_CODE; + + test_condition() async { + await resolveTestUnit(''' +main(int p) { + if (true || p > 5) { + print(1); + } +} +'''); + await assertHasFix(''' +main(int p) { + if (true) { + print(1); + } +} +'''); + } + + test_statements_one() async { + await resolveTestUnit(''' +int main() { + print(0); + return 42; + print(1); +} +'''); + await assertHasFix(''' +int main() { + print(0); + return 42; +} +'''); + } + + test_statements_two() async { + await resolveTestUnit(''' +int main() { + print(0); + return 42; + print(1); + print(2); +} +'''); + await assertHasFix(''' +int main() { + print(0); + return 42; +} +'''); + } +}
diff --git a/pkg/analysis_server/test/src/services/correction/fix/remove_empty_catch_test.dart b/pkg/analysis_server/test/src/services/correction/fix/remove_empty_catch_test.dart new file mode 100644 index 0000000..b5784b8 --- /dev/null +++ b/pkg/analysis_server/test/src/services/correction/fix/remove_empty_catch_test.dart
@@ -0,0 +1,54 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:analysis_server/src/services/correction/fix.dart'; +import 'package:analysis_server/src/services/correction/fix_internal.dart'; +import 'package:analyzer_plugin/utilities/fixes/fixes.dart'; +import 'package:test_reflective_loader/test_reflective_loader.dart'; + +import 'fix_processor.dart'; + +main() { + defineReflectiveSuite(() { + defineReflectiveTests(RemoveEmptyCatchTest); + }); +} + +@reflectiveTest +class RemoveEmptyCatchTest extends FixProcessorLintTest { + @override + FixKind get kind => DartFixKind.REMOVE_EMPTY_CATCH; + + @override + String get lintCode => LintNames.empty_catches; + + test_newLine() async { + await resolveTestUnit(''' +void foo() { + try {} + catch (e) {/*LINT*/} + finally {} +} +'''); + await assertHasFix(''' +void foo() { + try {} + finally {} +} +'''); + } + + test_sameLine() async { + await resolveTestUnit(''' +void foo() { + try {} catch (e) {/*LINT*/} finally {} +} +'''); + await assertHasFix(''' +void foo() { + try {} finally {} +} +'''); + } +}
diff --git a/pkg/analysis_server/test/src/services/correction/fix/remove_empty_constructor_body_test.dart b/pkg/analysis_server/test/src/services/correction/fix/remove_empty_constructor_body_test.dart new file mode 100644 index 0000000..3030ea2 --- /dev/null +++ b/pkg/analysis_server/test/src/services/correction/fix/remove_empty_constructor_body_test.dart
@@ -0,0 +1,38 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:analysis_server/src/services/correction/fix.dart'; +import 'package:analysis_server/src/services/correction/fix_internal.dart'; +import 'package:analyzer_plugin/utilities/fixes/fixes.dart'; +import 'package:test_reflective_loader/test_reflective_loader.dart'; + +import 'fix_processor.dart'; + +main() { + defineReflectiveSuite(() { + defineReflectiveTests(RemoveEmptyConstructorBodyTest); + }); +} + +@reflectiveTest +class RemoveEmptyConstructorBodyTest extends FixProcessorLintTest { + @override + FixKind get kind => DartFixKind.REMOVE_EMPTY_CONSTRUCTOR_BODY; + + @override + String get lintCode => LintNames.empty_constructor_bodies; + + test_empty() async { + await resolveTestUnit(''' +class C { + C() {/*LINT*/} +} +'''); + await assertHasFix(''' +class C { + C(); +} +'''); + } +}
diff --git a/pkg/analysis_server/test/src/services/correction/fix/remove_empty_else_test.dart b/pkg/analysis_server/test/src/services/correction/fix/remove_empty_else_test.dart new file mode 100644 index 0000000..1019af5 --- /dev/null +++ b/pkg/analysis_server/test/src/services/correction/fix/remove_empty_else_test.dart
@@ -0,0 +1,60 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:analysis_server/src/services/correction/fix.dart'; +import 'package:analysis_server/src/services/correction/fix_internal.dart'; +import 'package:analyzer_plugin/utilities/fixes/fixes.dart'; +import 'package:test_reflective_loader/test_reflective_loader.dart'; + +import 'fix_processor.dart'; + +main() { + defineReflectiveSuite(() { + defineReflectiveTests(RemoveEmptyElseTest); + }); +} + +@reflectiveTest +class RemoveEmptyElseTest extends FixProcessorLintTest { + @override + FixKind get kind => DartFixKind.REMOVE_EMPTY_ELSE; + + @override + String get lintCode => LintNames.avoid_empty_else; + + test_newLine() async { + await resolveTestUnit(''' +void foo(bool cond) { + if (cond) { + // + } + else /*LINT*/; +} +'''); + await assertHasFix(''' +void foo(bool cond) { + if (cond) { + // + } +} +'''); + } + + test_sameLine() async { + await resolveTestUnit(''' +void foo(bool cond) { + if (cond) { + // + } else /*LINT*/; +} +'''); + await assertHasFix(''' +void foo(bool cond) { + if (cond) { + // + } +} +'''); + } +}
diff --git a/pkg/analysis_server/test/src/services/correction/fix/remove_empty_statement_test.dart b/pkg/analysis_server/test/src/services/correction/fix/remove_empty_statement_test.dart new file mode 100644 index 0000000..18a278c --- /dev/null +++ b/pkg/analysis_server/test/src/services/correction/fix/remove_empty_statement_test.dart
@@ -0,0 +1,42 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:analysis_server/src/services/correction/fix.dart'; +import 'package:analysis_server/src/services/correction/fix_internal.dart'; +import 'package:analyzer_plugin/utilities/fixes/fixes.dart'; +import 'package:test_reflective_loader/test_reflective_loader.dart'; + +import 'fix_processor.dart'; + +main() { + defineReflectiveSuite(() { + defineReflectiveTests(RemoveEmptyStatementTest); + }); +} + +@reflectiveTest +class RemoveEmptyStatementTest extends FixProcessorLintTest { + @override + FixKind get kind => DartFixKind.REMOVE_EMPTY_STATEMENT; + + @override + String get lintCode => LintNames.empty_statements; + + test_insideBlock() async { + await resolveTestUnit(''' +void foo() { + while(true) { + /*LINT*/; + } +} +'''); + await assertHasFix(''' +void foo() { + while(true) { + /*LINT*/ + } +} +'''); + } +}
diff --git a/pkg/analysis_server/test/src/services/correction/fix/remove_initializer_test.dart b/pkg/analysis_server/test/src/services/correction/fix/remove_initializer_test.dart new file mode 100644 index 0000000..b686d62 --- /dev/null +++ b/pkg/analysis_server/test/src/services/correction/fix/remove_initializer_test.dart
@@ -0,0 +1,56 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:analysis_server/src/services/correction/fix.dart'; +import 'package:analysis_server/src/services/correction/fix_internal.dart'; +import 'package:analyzer_plugin/utilities/fixes/fixes.dart'; +import 'package:test_reflective_loader/test_reflective_loader.dart'; + +import 'fix_processor.dart'; + +main() { + defineReflectiveSuite(() { + defineReflectiveTests(RemoveInitializerTest); + }); +} + +@reflectiveTest +class RemoveInitializerTest extends FixProcessorLintTest { + @override + FixKind get kind => DartFixKind.REMOVE_INITIALIZER; + + @override + String get lintCode => LintNames.avoid_init_to_null; + + test_field() async { + await resolveTestUnit(''' +class Test { + int /*LINT*/x = null; +} +'''); + await assertHasFix(''' +class Test { + int /*LINT*/x; +} +'''); + } + + test_listOfVariableDeclarations() async { + await resolveTestUnit(''' +String a = 'a', /*LINT*/b = null, c = 'c'; +'''); + await assertHasFix(''' +String a = 'a', /*LINT*/b, c = 'c'; +'''); + } + + test_topLevel() async { + await resolveTestUnit(''' +var /*LINT*/x = null; +'''); + await assertHasFix(''' +var /*LINT*/x; +'''); + } +}
diff --git a/pkg/analysis_server/test/src/services/correction/fix/remove_interpolation_braces_test.dart b/pkg/analysis_server/test/src/services/correction/fix/remove_interpolation_braces_test.dart new file mode 100644 index 0000000..2fdfad9a --- /dev/null +++ b/pkg/analysis_server/test/src/services/correction/fix/remove_interpolation_braces_test.dart
@@ -0,0 +1,40 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:analysis_server/src/services/correction/fix.dart'; +import 'package:analysis_server/src/services/correction/fix_internal.dart'; +import 'package:analyzer_plugin/utilities/fixes/fixes.dart'; +import 'package:test_reflective_loader/test_reflective_loader.dart'; + +import 'fix_processor.dart'; + +main() { + defineReflectiveSuite(() { + defineReflectiveTests(RemoveInterpolationBracesTest); + }); +} + +@reflectiveTest +class RemoveInterpolationBracesTest extends FixProcessorLintTest { + @override + FixKind get kind => DartFixKind.REMOVE_INTERPOLATION_BRACES; + + @override + String get lintCode => LintNames.unnecessary_brace_in_string_interp; + + test_withSpace() async { + await resolveTestUnit(r''' +main() { + var v = 42; + print('v: /*LINT*/${ v}'); +} +'''); + await assertHasFix(r''' +main() { + var v = 42; + print('v: /*LINT*/$v'); +} +''', length: 4); + } +}
diff --git a/pkg/analysis_server/test/src/services/correction/fix/remove_method_declaration_test.dart b/pkg/analysis_server/test/src/services/correction/fix/remove_method_declaration_test.dart new file mode 100644 index 0000000..443d382 --- /dev/null +++ b/pkg/analysis_server/test/src/services/correction/fix/remove_method_declaration_test.dart
@@ -0,0 +1,78 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:analysis_server/src/services/correction/fix.dart'; +import 'package:analysis_server/src/services/correction/fix_internal.dart'; +import 'package:analyzer_plugin/utilities/fixes/fixes.dart'; +import 'package:test_reflective_loader/test_reflective_loader.dart'; + +import 'fix_processor.dart'; + +main() { + defineReflectiveSuite(() { + defineReflectiveTests(RemoveMethodDeclarationTest); + }); +} + +@reflectiveTest +class RemoveMethodDeclarationTest extends FixProcessorLintTest { + @override + FixKind get kind => DartFixKind.REMOVE_METHOD_DECLARATION; + + @override + String get lintCode => LintNames.unnecessary_override; + + test_getter() async { + await resolveTestUnit(''' +class A { + int x; +} +class B extends A { + @override + int get /*LINT*/x => super.x; +} +'''); + await assertHasFix(''' +class A { + int x; +} +class B extends A { +} +'''); + } + + test_method() async { + await resolveTestUnit(''' +class A { + @override + String /*LINT*/toString() => super.toString(); +} +'''); + await assertHasFix(''' +class A { +} +'''); + } + + test_setter() async { + await resolveTestUnit(''' +class A { + int x; +} +class B extends A { + @override + set /*LINT*/x(int other) { + this.x = other; + } +} +'''); + await assertHasFix(''' +class A { + int x; +} +class B extends A { +} +'''); + } +}
diff --git a/pkg/analysis_server/test/src/services/correction/fix/remove_parameters_in_getter_declaration_test.dart b/pkg/analysis_server/test/src/services/correction/fix/remove_parameters_in_getter_declaration_test.dart new file mode 100644 index 0000000..20606f5 --- /dev/null +++ b/pkg/analysis_server/test/src/services/correction/fix/remove_parameters_in_getter_declaration_test.dart
@@ -0,0 +1,47 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:analysis_server/src/services/correction/fix.dart'; +import 'package:analyzer_plugin/utilities/fixes/fixes.dart'; +import 'package:test_reflective_loader/test_reflective_loader.dart'; + +import 'fix_processor.dart'; + +main() { + defineReflectiveSuite(() { + defineReflectiveTests(RemoveParametersInGetterDeclarationTest); + }); +} + +@reflectiveTest +class RemoveParametersInGetterDeclarationTest extends FixProcessorTest { + @override + FixKind get kind => DartFixKind.REMOVE_PARAMETERS_IN_GETTER_DECLARATION; + + test_emptyList() async { + await resolveTestUnit(''' +class A { + int get foo() => 0; +} +'''); + await assertHasFix(''' +class A { + int get foo => 0; +} +'''); + } + + test_nonEmptyList() async { + await resolveTestUnit(''' +class A { + int get foo(int a) => 0; +} +'''); + await assertHasFix(''' +class A { + int get foo => 0; +} +'''); + } +}
diff --git a/pkg/analysis_server/test/src/services/correction/fix/remove_parentheses_in_getter_invocation_test.dart b/pkg/analysis_server/test/src/services/correction/fix/remove_parentheses_in_getter_invocation_test.dart new file mode 100644 index 0000000..65e1c39 --- /dev/null +++ b/pkg/analysis_server/test/src/services/correction/fix/remove_parentheses_in_getter_invocation_test.dart
@@ -0,0 +1,40 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:analysis_server/src/services/correction/fix.dart'; +import 'package:analyzer_plugin/utilities/fixes/fixes.dart'; +import 'package:test_reflective_loader/test_reflective_loader.dart'; + +import 'fix_processor.dart'; + +main() { + defineReflectiveSuite(() { + defineReflectiveTests(RemoveParenthesesInGetterInvocationTest); + }); +} + +@reflectiveTest +class RemoveParenthesesInGetterInvocationTest extends FixProcessorTest { + @override + FixKind get kind => DartFixKind.REMOVE_PARENTHESIS_IN_GETTER_INVOCATION; + + test_noArguments() async { + await resolveTestUnit(''' +class A { + int get foo => 0; +} +main(A a) { + a.foo(); +} +'''); + await assertHasFix(''' +class A { + int get foo => 0; +} +main(A a) { + a.foo; +} +'''); + } +}
diff --git a/pkg/analysis_server/test/src/services/correction/fix/remove_this_expression_test.dart b/pkg/analysis_server/test/src/services/correction/fix/remove_this_expression_test.dart new file mode 100644 index 0000000..5ea13d4 --- /dev/null +++ b/pkg/analysis_server/test/src/services/correction/fix/remove_this_expression_test.dart
@@ -0,0 +1,106 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:analysis_server/src/services/correction/fix.dart'; +import 'package:analysis_server/src/services/correction/fix_internal.dart'; +import 'package:analyzer_plugin/utilities/fixes/fixes.dart'; +import 'package:test_reflective_loader/test_reflective_loader.dart'; + +import 'fix_processor.dart'; + +main() { + defineReflectiveSuite(() { + defineReflectiveTests(RemoveThisExpressionTest); + }); +} + +@reflectiveTest +class RemoveThisExpressionTest extends FixProcessorLintTest { + @override + FixKind get kind => DartFixKind.REMOVE_THIS_EXPRESSION; + + @override + String get lintCode => LintNames.unnecessary_this; + + test_methodInvocation_oneCharacterOperator() async { + await resolveTestUnit(''' +class A { + void foo() { + /*LINT*/this.foo(); + } +} +'''); + await assertHasFix(''' +class A { + void foo() { + /*LINT*/foo(); + } +} +'''); + } + + test_methodInvocation_twoCharactersOperator() async { + await resolveTestUnit(''' +class A { + void foo() { + /*LINT*/this?.foo(); + } +} +'''); + await assertHasFix(''' +class A { + void foo() { + /*LINT*/foo(); + } +} +'''); + } + + test_notAThisExpression() async { + await resolveTestUnit(''' +void foo() { + final /*LINT*/this.id; +} +'''); + await assertNoFix(); + } + + test_propertyAccess_oneCharacterOperator() async { + await resolveTestUnit(''' +class A { + int x; + void foo() { + /*LINT*/this.x = 2; + } +} +'''); + await assertHasFix(''' +class A { + int x; + void foo() { + /*LINT*/x = 2; + } +} +'''); + } + + test_propertyAccess_twoCharactersOperator() async { + await resolveTestUnit(''' +class A { + int x; + void foo() { + /*LINT*/this?.x = 2; + } +} +'''); + await assertHasFix(''' +class A { + int x; + void foo() { + /*LINT*/x = 2; + } +} +'''); + } +}
diff --git a/pkg/analysis_server/test/src/services/correction/fix/remove_type_annotation_test.dart b/pkg/analysis_server/test/src/services/correction/fix/remove_type_annotation_test.dart new file mode 100644 index 0000000..54deb8b --- /dev/null +++ b/pkg/analysis_server/test/src/services/correction/fix/remove_type_annotation_test.dart
@@ -0,0 +1,164 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:analysis_server/src/services/correction/fix.dart'; +import 'package:analysis_server/src/services/correction/fix_internal.dart'; +import 'package:analyzer_plugin/utilities/fixes/fixes.dart'; +import 'package:test_reflective_loader/test_reflective_loader.dart'; + +import 'fix_processor.dart'; + +main() { + defineReflectiveSuite(() { + defineReflectiveTests(AvoidAnnotatingWithDynamicTest); + defineReflectiveTests(AvoidReturnTypesOnSettersTest); + defineReflectiveTests(AvoidTypesOnClosureParametersTest); + defineReflectiveTests(TypeInitFormalsTest); + }); +} + +@reflectiveTest +class AvoidAnnotatingWithDynamicTest extends RemoveTypeAnnotationTest { + @override + String get lintCode => LintNames.avoid_annotating_with_dynamic; + + test_insideFunctionTypedFormalParameter() async { + await resolveTestUnit(''' +bad(void foo(/*LINT*/dynamic x)) { + return null; +} +'''); + await assertHasFix(''' +bad(void foo(/*LINT*/x)) { + return null; +} +'''); + } + + test_namedParameter() async { + await resolveTestUnit(''' +bad({/*LINT*/dynamic defaultValue}) { + return null; +} +'''); + await assertHasFix(''' +bad({/*LINT*/defaultValue}) { + return null; +} +'''); + } + + test_normalParameter() async { + await resolveTestUnit(''' +bad(/*LINT*/dynamic defaultValue) { + return null; +} +'''); + await assertHasFix(''' +bad(/*LINT*/defaultValue) { + return null; +} +'''); + } + + test_optionalParameter() async { + await resolveTestUnit(''' +bad([/*LINT*/dynamic defaultValue]) { + return null; +} +'''); + await assertHasFix(''' +bad([/*LINT*/defaultValue]) { + return null; +} +'''); + } +} + +@reflectiveTest +class AvoidReturnTypesOnSettersTest extends RemoveTypeAnnotationTest { + @override + String get lintCode => LintNames.avoid_return_types_on_setters; + + test_void() async { + await resolveTestUnit(''' +/*LINT*/void set speed2(int ms) {} +'''); + await assertHasFix(''' +/*LINT*/set speed2(int ms) {} +'''); + } +} + +@reflectiveTest +class AvoidTypesOnClosureParametersTest extends RemoveTypeAnnotationTest { + @override + String get lintCode => LintNames.avoid_types_on_closure_parameters; + + test_namedParameter() async { + await resolveTestUnit(''' +var x = ({/*LINT*/Future<int> defaultValue}) { + return null; +}; +'''); + await assertHasFix(''' +var x = ({/*LINT*/defaultValue}) { + return null; +}; +'''); + } + + test_normalParameter() async { + await resolveTestUnit(''' +var x = (/*LINT*/Future<int> defaultValue) { + return null; +}; +'''); + await assertHasFix(''' +var x = (/*LINT*/defaultValue) { + return null; +}; +'''); + } + + test_optionalParameter() async { + await resolveTestUnit(''' +var x = ([/*LINT*/Future<int> defaultValue]) { + return null; +}; +'''); + await assertHasFix(''' +var x = ([/*LINT*/defaultValue]) { + return null; +}; +'''); + } +} + +@reflectiveTest +class TypeInitFormalsTest extends RemoveTypeAnnotationTest { + @override + String get lintCode => LintNames.type_init_formals; + + test_void() async { + await resolveTestUnit(''' +class C { + int f; + C(/*LINT*/int this.f); +} +'''); + await assertHasFix(''' +class C { + int f; + C(/*LINT*/this.f); +} +'''); + } +} + +@reflectiveTest +abstract class RemoveTypeAnnotationTest extends FixProcessorLintTest { + @override + FixKind get kind => DartFixKind.REMOVE_TYPE_ANNOTATION; +}
diff --git a/pkg/analysis_server/test/src/services/correction/fix/remove_type_arguments_test.dart b/pkg/analysis_server/test/src/services/correction/fix/remove_type_arguments_test.dart new file mode 100644 index 0000000..b27594f --- /dev/null +++ b/pkg/analysis_server/test/src/services/correction/fix/remove_type_arguments_test.dart
@@ -0,0 +1,99 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:analysis_server/src/services/correction/fix.dart'; +import 'package:analyzer_plugin/utilities/fixes/fixes.dart'; +import 'package:test_reflective_loader/test_reflective_loader.dart'; + +import 'fix_processor.dart'; + +main() { + defineReflectiveSuite(() { + defineReflectiveTests(RemoveTypeArgumentsTest); + }); +} + +@reflectiveTest +class RemoveTypeArgumentsTest extends FixProcessorTest { + @override + FixKind get kind => DartFixKind.REMOVE_TYPE_ARGUMENTS; + + test_explicitConst() async { + await resolveTestUnit(''' +main() { + const C.named<int>(); +} +class C<E> { + const C.named(); +} +'''); + await assertHasFix(''' +main() { + const C.named(); +} +class C<E> { + const C.named(); +} +'''); + } + + test_explicitNew() async { + await resolveTestUnit(''' +main() { + new C.named<int>(); +} +class C<E> { + C.named(); +} +'''); + await assertHasFix(''' +main() { + new C.named(); +} +class C<E> { + C.named(); +} +'''); + } + + test_implicitConst() async { + await resolveTestUnit(''' +main() { + const C c = C.named<int>(); + print(c); +} +class C<E> { + const C.named(); +} +'''); + await assertHasFix(''' +main() { + const C c = C.named(); + print(c); +} +class C<E> { + const C.named(); +} +'''); + } + + test_implicitNew() async { + await resolveTestUnit(''' +main() { + C.named<int>(); +} +class C<E> { + C.named(); +} +'''); + await assertHasFix(''' +main() { + C.named(); +} +class C<E> { + C.named(); +} +'''); + } +}
diff --git a/pkg/analysis_server/test/src/services/correction/fix/remove_unnecessary_cast_test.dart b/pkg/analysis_server/test/src/services/correction/fix/remove_unnecessary_cast_test.dart new file mode 100644 index 0000000..9218c3b --- /dev/null +++ b/pkg/analysis_server/test/src/services/correction/fix/remove_unnecessary_cast_test.dart
@@ -0,0 +1,68 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:analysis_server/src/services/correction/fix.dart'; +import 'package:analyzer/src/error/codes.dart'; +import 'package:analyzer_plugin/utilities/fixes/fixes.dart'; +import 'package:test_reflective_loader/test_reflective_loader.dart'; + +import 'fix_processor.dart'; + +main() { + defineReflectiveSuite(() { + defineReflectiveTests(RemoveUnnecessaryCastTest); + }); +} + +@reflectiveTest +class RemoveUnnecessaryCastTest extends FixProcessorTest { + @override + FixKind get kind => DartFixKind.REMOVE_UNNECESSARY_CAST; + + test_assignment() async { + await resolveTestUnit(''' +main(Object p) { + if (p is String) { + String v = ((p as String)); + print(v); + } +} +'''); + await assertHasFix(''' +main(Object p) { + if (p is String) { + String v = p; + print(v); + } +} +'''); + } + + test_assignment_all() async { + await resolveTestUnit(''' +main(Object p, Object q) { + if (p is String) { + String v = ((p as String)); + print(v); + } + if (q is int) { + int v = ((q as int)); + print(v); + } +} +'''); + await assertHasFixAllFix(HintCode.UNNECESSARY_CAST, ''' +main(Object p, Object q) { + if (p is String) { + String v = p; + print(v); + } + if (q is int) { + int v = q; + print(v); + } +} +'''); + } +}
diff --git a/pkg/analysis_server/test/src/services/correction/fix/remove_unused_catch_clause_test.dart b/pkg/analysis_server/test/src/services/correction/fix/remove_unused_catch_clause_test.dart new file mode 100644 index 0000000..8bd4f51 --- /dev/null +++ b/pkg/analysis_server/test/src/services/correction/fix/remove_unused_catch_clause_test.dart
@@ -0,0 +1,40 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:analysis_server/src/services/correction/fix.dart'; +import 'package:analyzer_plugin/utilities/fixes/fixes.dart'; +import 'package:test_reflective_loader/test_reflective_loader.dart'; + +import 'fix_processor.dart'; + +main() { + defineReflectiveSuite(() { + defineReflectiveTests(RemoveUnusedCatchClauseTest); + }); +} + +@reflectiveTest +class RemoveUnusedCatchClauseTest extends FixProcessorTest { + @override + FixKind get kind => DartFixKind.REMOVE_UNUSED_CATCH_CLAUSE; + + test_removeUnusedCatchClause() async { + await resolveTestUnit(''' +main() { + try { + throw 42; + } on int catch (e) { + } +} +'''); + await assertHasFix(''' +main() { + try { + throw 42; + } on int { + } +} +'''); + } +}
diff --git a/pkg/analysis_server/test/src/services/correction/fix/remove_unused_catch_stack_test.dart b/pkg/analysis_server/test/src/services/correction/fix/remove_unused_catch_stack_test.dart new file mode 100644 index 0000000..da067cd --- /dev/null +++ b/pkg/analysis_server/test/src/services/correction/fix/remove_unused_catch_stack_test.dart
@@ -0,0 +1,40 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:analysis_server/src/services/correction/fix.dart'; +import 'package:analyzer_plugin/utilities/fixes/fixes.dart'; +import 'package:test_reflective_loader/test_reflective_loader.dart'; + +import 'fix_processor.dart'; + +main() { + defineReflectiveSuite(() { + defineReflectiveTests(RemoveUnusedCatchStackTest); + }); +} + +@reflectiveTest +class RemoveUnusedCatchStackTest extends FixProcessorTest { + @override + FixKind get kind => DartFixKind.REMOVE_UNUSED_CATCH_STACK; + + test_removeUnusedCatchStack() async { + await resolveTestUnit(''' +main() { + try { + throw 42; + } catch (e, stack) { + } +} +'''); + await assertHasFix(''' +main() { + try { + throw 42; + } catch (e) { + } +} +'''); + } +}
diff --git a/pkg/analysis_server/test/src/services/correction/fix/remove_unused_import_test.dart b/pkg/analysis_server/test/src/services/correction/fix/remove_unused_import_test.dart new file mode 100644 index 0000000..96ee02f --- /dev/null +++ b/pkg/analysis_server/test/src/services/correction/fix/remove_unused_import_test.dart
@@ -0,0 +1,127 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:analysis_server/src/services/correction/fix.dart'; +import 'package:analyzer/src/error/codes.dart'; +import 'package:analyzer_plugin/utilities/fixes/fixes.dart'; +import 'package:test_reflective_loader/test_reflective_loader.dart'; + +import 'fix_processor.dart'; + +main() { + defineReflectiveSuite(() { + defineReflectiveTests(RemoveUnusedImportTest); + }); +} + +@reflectiveTest +class RemoveUnusedImportTest extends FixProcessorTest { + @override + FixKind get kind => DartFixKind.REMOVE_UNUSED_IMPORT; + + test_all_diverseImports() async { + await resolveTestUnit(''' +import 'dart:math'; +import 'dart:math'; +import 'dart:async'; +main() { +} +'''); + await assertHasFixAllFix(HintCode.UNUSED_IMPORT, ''' +main() { +} +'''); + } + + test_all_diverseImports2() async { + await resolveTestUnit(''' +import 'dart:async'; +import 'dart:math' as math; +import 'dart:async'; + +var tau = math.pi * 2; + +main() { +} +'''); + await assertHasFixAllFix(HintCode.UNUSED_IMPORT, ''' +import 'dart:math' as math; + +var tau = math.pi * 2; + +main() { +} +'''); + } + + test_all_singleLine() async { + await resolveTestUnit(''' +import 'dart:math'; import 'dart:math'; import 'dart:math'; +main() { +} +'''); + await assertHasFixAllFix(HintCode.UNUSED_IMPORT, ''' +main() { +} +'''); + } + + test_anotherImportOnLine() async { + await resolveTestUnit(''' +import 'dart:math'; import 'dart:async'; + +main() { + Future f; + print(f); +} +'''); + await assertHasFix(''' +import 'dart:async'; + +main() { + Future f; + print(f); +} +'''); + } + + test_multipleOfSame_all() async { + await resolveTestUnit(''' +import 'dart:math'; +import 'dart:math'; +import 'dart:math'; +main() { +} +'''); + await assertHasFixAllFix(HintCode.UNUSED_IMPORT, ''' +main() { +} +'''); + } + + test_severalLines() async { + await resolveTestUnit(''' +import + 'dart:math'; +main() { +} +'''); + await assertHasFix(''' +main() { +} +'''); + } + + test_single() async { + await resolveTestUnit(''' +import 'dart:math'; +main() { +} +'''); + await assertHasFix(''' +main() { +} +'''); + } +}
diff --git a/pkg/analysis_server/test/src/services/correction/fix/rename_to_camel_case_test.dart b/pkg/analysis_server/test/src/services/correction/fix/rename_to_camel_case_test.dart new file mode 100644 index 0000000..45f6677 --- /dev/null +++ b/pkg/analysis_server/test/src/services/correction/fix/rename_to_camel_case_test.dart
@@ -0,0 +1,113 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:analysis_server/src/services/correction/fix.dart'; +import 'package:analysis_server/src/services/correction/fix_internal.dart'; +import 'package:analyzer_plugin/utilities/fixes/fixes.dart'; +import 'package:test_reflective_loader/test_reflective_loader.dart'; + +import 'fix_processor.dart'; + +main() { + defineReflectiveSuite(() { + defineReflectiveTests(RenameToCamelCaseTest); + }); +} + +@reflectiveTest +class RenameToCamelCaseTest extends FixProcessorLintTest { + @override + FixKind get kind => DartFixKind.RENAME_TO_CAMEL_CASE; + + @override + String get lintCode => LintNames.non_constant_identifier_names; + + test_localVariable() async { + await resolveTestUnit(''' +main() { + int /*LINT*/my_integer_variable = 42; + int foo; + print(my_integer_variable); + print(foo); +} +'''); + await assertHasFix(''' +main() { + int /*LINT*/myIntegerVariable = 42; + int foo; + print(myIntegerVariable); + print(foo); +} +'''); + } + + test_parameter_closure() async { + await resolveTestUnit(''' +main() { + [0, 1, 2].forEach((/*LINT*/my_integer_variable) { + print(my_integer_variable); + }); +} +'''); + await assertHasFix(''' +main() { + [0, 1, 2].forEach((/*LINT*/myIntegerVariable) { + print(myIntegerVariable); + }); +} +'''); + } + + test_parameter_function() async { + await resolveTestUnit(''' +main(int /*LINT*/my_integer_variable) { + print(my_integer_variable); +} +'''); + await assertHasFix(''' +main(int /*LINT*/myIntegerVariable) { + print(myIntegerVariable); +} +'''); + } + + test_parameter_method() async { + await resolveTestUnit(''' +class A { + main(int /*LINT*/my_integer_variable) { + print(my_integer_variable); + } +} +'''); + await assertHasFix(''' +class A { + main(int /*LINT*/myIntegerVariable) { + print(myIntegerVariable); + } +} +'''); + } + + test_parameter_optionalNamed() async { + await resolveTestUnit(''' +foo({int /*LINT*/my_integer_variable}) { + print(my_integer_variable); +} +'''); + await assertNoFix(); + } + + test_parameter_optionalPositional() async { + await resolveTestUnit(''' +main([int /*LINT*/my_integer_variable]) { + print(my_integer_variable); +} +'''); + await assertHasFix(''' +main([int /*LINT*/myIntegerVariable]) { + print(myIntegerVariable); +} +'''); + } +}
diff --git a/pkg/analysis_server/test/src/services/correction/fix/replace_boolean_with_bool_test.dart b/pkg/analysis_server/test/src/services/correction/fix/replace_boolean_with_bool_test.dart new file mode 100644 index 0000000..29fe96e --- /dev/null +++ b/pkg/analysis_server/test/src/services/correction/fix/replace_boolean_with_bool_test.dart
@@ -0,0 +1,52 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:analysis_server/src/services/correction/fix.dart'; +import 'package:analyzer/src/error/codes.dart'; +import 'package:analyzer_plugin/utilities/fixes/fixes.dart'; +import 'package:test_reflective_loader/test_reflective_loader.dart'; + +import 'fix_processor.dart'; + +main() { + defineReflectiveSuite(() { + defineReflectiveTests(ReplaceBooleanWithBoolTest); + }); +} + +@reflectiveTest +class ReplaceBooleanWithBoolTest extends FixProcessorTest { + @override + FixKind get kind => DartFixKind.REPLACE_BOOLEAN_WITH_BOOL; + + test_all() async { + await resolveTestUnit(''' +main() { + boolean v; + boolean w; +} +'''); + await assertHasFixAllFix(StaticWarningCode.UNDEFINED_CLASS_BOOLEAN, ''' +main() { + bool v; + bool w; +} +'''); + } + + test_single() async { + await resolveTestUnit(''' +main() { + boolean v; + print(v); +} +'''); + await assertHasFix(''' +main() { + bool v; + print(v); +} +'''); + } +}
diff --git a/pkg/analysis_server/test/src/services/correction/fix/replace_final_with_const_test.dart b/pkg/analysis_server/test/src/services/correction/fix/replace_final_with_const_test.dart new file mode 100644 index 0000000..77fa5a7 --- /dev/null +++ b/pkg/analysis_server/test/src/services/correction/fix/replace_final_with_const_test.dart
@@ -0,0 +1,34 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:analysis_server/src/services/correction/fix.dart'; +import 'package:analysis_server/src/services/correction/fix_internal.dart'; +import 'package:analyzer_plugin/utilities/fixes/fixes.dart'; +import 'package:test_reflective_loader/test_reflective_loader.dart'; + +import 'fix_processor.dart'; + +main() { + defineReflectiveSuite(() { + defineReflectiveTests(ReplaceFinalWithConstTest); + }); +} + +@reflectiveTest +class ReplaceFinalWithConstTest extends FixProcessorLintTest { + @override + FixKind get kind => DartFixKind.REPLACE_FINAL_WITH_CONST; + + @override + String get lintCode => LintNames.prefer_const_declarations; + + test_method() async { + await resolveTestUnit(''' +/*LINT*/final int a = 1; +'''); + await assertHasFix(''' +/*LINT*/const int a = 1; +'''); + } +}
diff --git a/pkg/analysis_server/test/src/services/correction/fix/replace_return_type_future_test.dart b/pkg/analysis_server/test/src/services/correction/fix/replace_return_type_future_test.dart new file mode 100644 index 0000000..244178e --- /dev/null +++ b/pkg/analysis_server/test/src/services/correction/fix/replace_return_type_future_test.dart
@@ -0,0 +1,151 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:analysis_server/src/services/correction/fix.dart'; +import 'package:analyzer/src/error/codes.dart'; +import 'package:analyzer_plugin/utilities/fixes/fixes.dart'; +import 'package:test_reflective_loader/test_reflective_loader.dart'; + +import 'fix_processor.dart'; + +main() { + defineReflectiveSuite(() { + defineReflectiveTests(ReplaceReturnTypeFutureTest); + }); +} + +@reflectiveTest +class ReplaceReturnTypeFutureTest extends FixProcessorTest { + @override + FixKind get kind => DartFixKind.REPLACE_RETURN_TYPE_FUTURE; + + test_adjacentNodes_withImport() async { + await resolveTestUnit(''' +import 'dart:async'; +var v;int main() async => 0; +'''); + await assertHasFix(''' +import 'dart:async'; +var v;Future<int> main() async => 0; +''', errorFilter: (error) { + return error.errorCode == StaticTypeWarningCode.ILLEGAL_ASYNC_RETURN_TYPE; + }); + } + + test_adjacentNodes_withoutImport() async { + await resolveTestUnit(''' +var v;int main() async => 0; +'''); + await assertHasFix(''' +var v;Future<int> main() async => 0; +''', errorFilter: (error) { + return error.errorCode == StaticTypeWarningCode.ILLEGAL_ASYNC_RETURN_TYPE; + }); + } + + test_complexTypeName_withImport() async { + await resolveTestUnit(''' +import 'dart:async'; +List<int> main() async { +} +'''); + await assertHasFix(''' +import 'dart:async'; +Future<List<int>> main() async { +} +''', errorFilter: (error) { + return error.errorCode == StaticTypeWarningCode.ILLEGAL_ASYNC_RETURN_TYPE; + }); + } + + @failingTest + test_complexTypeName_withoutImport() async { + await resolveTestUnit(''' +List<int> main() async { +} +'''); + await assertHasFix(''' +import 'dart:async'; + +Future<List<int>> main() async { +} +''', errorFilter: (error) { + return error.errorCode == StaticTypeWarningCode.ILLEGAL_ASYNC_RETURN_TYPE; + }); + } + + test_importedWithPrefix() async { + await resolveTestUnit(''' +import 'dart:async' as al; +int main() async { +} +'''); + await assertHasFix(''' +import 'dart:async' as al; +al.Future<int> main() async { +} +''', errorFilter: (error) { + return error.errorCode == StaticTypeWarningCode.ILLEGAL_ASYNC_RETURN_TYPE; + }); + } + + test_simpleTypeName_withImport() async { + await resolveTestUnit(''' +import 'dart:async'; +int main() async => 0; +'''); + await assertHasFix(''' +import 'dart:async'; +Future<int> main() async => 0; +''', errorFilter: (error) { + return error.errorCode == StaticTypeWarningCode.ILLEGAL_ASYNC_RETURN_TYPE; + }); + } + + @failingTest + test_simpleTypeName_withoutImport() async { + await resolveTestUnit(''' +int main() async => 0; +'''); + await assertHasFix(''' +import 'dart:async'; + +Future<int> main() async => 0; +''', errorFilter: (error) { + return error.errorCode == StaticTypeWarningCode.ILLEGAL_ASYNC_RETURN_TYPE; + }); + } + + test_withLibraryDirective_withImport() async { + await resolveTestUnit(''' +library main; +import 'dart:async'; +int main() async { +} +'''); + await assertHasFix(''' +library main; +import 'dart:async'; +Future<int> main() async { +} +''', errorFilter: (error) { + return error.errorCode == StaticTypeWarningCode.ILLEGAL_ASYNC_RETURN_TYPE; + }); + } + + test_withLibraryDirective_withoutImport() async { + await resolveTestUnit(''' +library main; +int main() async { +} +'''); + await assertHasFix(''' +library main; +Future<int> main() async { +} +''', errorFilter: (error) { + return error.errorCode == StaticTypeWarningCode.ILLEGAL_ASYNC_RETURN_TYPE; + }); + } +}
diff --git a/pkg/analysis_server/test/src/services/correction/fix/replace_var_with_dynamic_test.dart b/pkg/analysis_server/test/src/services/correction/fix/replace_var_with_dynamic_test.dart new file mode 100644 index 0000000..f0463c8 --- /dev/null +++ b/pkg/analysis_server/test/src/services/correction/fix/replace_var_with_dynamic_test.dart
@@ -0,0 +1,37 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:analysis_server/src/services/correction/fix.dart'; +import 'package:analyzer/src/dart/error/syntactic_errors.dart'; +import 'package:analyzer_plugin/utilities/fixes/fixes.dart'; +import 'package:test_reflective_loader/test_reflective_loader.dart'; + +import 'fix_processor.dart'; + +main() { + defineReflectiveSuite(() { + defineReflectiveTests(ReplaceVarWithDynamicTest); + }); +} + +@reflectiveTest +class ReplaceVarWithDynamicTest extends FixProcessorTest { + @override + FixKind get kind => DartFixKind.REPLACE_VAR_WITH_DYNAMIC; + + test_simple() async { + await resolveTestUnit(''' +class A { + Map<String, var> m; +} +'''); + await assertHasFix(''' +class A { + Map<String, dynamic> m; +} +''', errorFilter: (error) { + return error.errorCode == ParserErrorCode.VAR_AS_TYPE_NAME; + }); + } +}
diff --git a/pkg/analysis_server/test/src/services/correction/fix/replace_with_brackets_test.dart b/pkg/analysis_server/test/src/services/correction/fix/replace_with_brackets_test.dart new file mode 100644 index 0000000..93cae94 --- /dev/null +++ b/pkg/analysis_server/test/src/services/correction/fix/replace_with_brackets_test.dart
@@ -0,0 +1,56 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:analysis_server/src/services/correction/fix.dart'; +import 'package:analysis_server/src/services/correction/fix_internal.dart'; +import 'package:analyzer_plugin/utilities/fixes/fixes.dart'; +import 'package:test_reflective_loader/test_reflective_loader.dart'; + +import 'fix_processor.dart'; + +main() { + defineReflectiveSuite(() { + defineReflectiveTests(ReplaceWithBracketsTest); + }); +} + +@reflectiveTest +class ReplaceWithBracketsTest extends FixProcessorLintTest { + @override + FixKind get kind => DartFixKind.REPLACE_WITH_BRACKETS; + + @override + String get lintCode => LintNames.empty_statements; + + test_outOfBlock_otherLine() async { + await resolveTestUnit(''' +void foo() { + while(true) + /*LINT*/; + print('hi'); +} +'''); + await assertHasFix(''' +void foo() { + while(true) {} + print('hi'); +} +'''); + } + + test_outOfBlock_sameLine() async { + await resolveTestUnit(''' +void foo() { + while(true)/*LINT*/; + print('hi'); +} +'''); + await assertHasFix(''' +void foo() { + while(true) {} + print('hi'); +} +'''); + } +}
diff --git a/pkg/analysis_server/test/src/services/correction/fix/replace_with_conditional_assignment_test.dart b/pkg/analysis_server/test/src/services/correction/fix/replace_with_conditional_assignment_test.dart new file mode 100644 index 0000000..e5baaec --- /dev/null +++ b/pkg/analysis_server/test/src/services/correction/fix/replace_with_conditional_assignment_test.dart
@@ -0,0 +1,112 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:analysis_server/src/services/correction/fix.dart'; +import 'package:analysis_server/src/services/correction/fix_internal.dart'; +import 'package:analyzer_plugin/utilities/fixes/fixes.dart'; +import 'package:test_reflective_loader/test_reflective_loader.dart'; + +import 'fix_processor.dart'; + +main() { + defineReflectiveSuite(() { + defineReflectiveTests(ReplaceWithConditionalAssignmentTest); + }); +} + +@reflectiveTest +class ReplaceWithConditionalAssignmentTest extends FixProcessorLintTest { + @override + FixKind get kind => DartFixKind.REPLACE_WITH_CONDITIONAL_ASSIGNMENT; + + @override + String get lintCode => LintNames.prefer_conditional_assignment; + + test_withCodeBeforeAndAfter() async { + await resolveTestUnit(''' +class Person { + String _fullName; + void foo() { + print('hi'); + /*LINT*/if (_fullName == null) { + _fullName = getFullUserName(this); + } + print('hi'); + } +} +'''); + await assertHasFix(''' +class Person { + String _fullName; + void foo() { + print('hi'); + /*LINT*/_fullName ??= getFullUserName(this); + print('hi'); + } +} +'''); + } + + test_withOneBlock() async { + await resolveTestUnit(''' +class Person { + String _fullName; + void foo() { + /*LINT*/if (_fullName == null) { + _fullName = getFullUserName(this); + } + } +} +'''); + await assertHasFix(''' +class Person { + String _fullName; + void foo() { + /*LINT*/_fullName ??= getFullUserName(this); + } +} +'''); + } + + test_withoutBlock() async { + await resolveTestUnit(''' +class Person { + String _fullName; + void foo() { + /*LINT*/if (_fullName == null) + _fullName = getFullUserName(this); + } +} +'''); + await assertHasFix(''' +class Person { + String _fullName; + void foo() { + /*LINT*/_fullName ??= getFullUserName(this); + } +} +'''); + } + + test_withTwoBlock() async { + await resolveTestUnit(''' +class Person { + String _fullName; + void foo() { + /*LINT*/if (_fullName == null) {{ + _fullName = getFullUserName(this); + }} + } +} +'''); + await assertHasFix(''' +class Person { + String _fullName; + void foo() { + /*LINT*/_fullName ??= getFullUserName(this); + } +} +'''); + } +}
diff --git a/pkg/analysis_server/test/src/services/correction/fix/replace_with_identifier_test.dart b/pkg/analysis_server/test/src/services/correction/fix/replace_with_identifier_test.dart new file mode 100644 index 0000000..6dfc38c --- /dev/null +++ b/pkg/analysis_server/test/src/services/correction/fix/replace_with_identifier_test.dart
@@ -0,0 +1,34 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:analysis_server/src/services/correction/fix.dart'; +import 'package:analysis_server/src/services/correction/fix_internal.dart'; +import 'package:analyzer_plugin/utilities/fixes/fixes.dart'; +import 'package:test_reflective_loader/test_reflective_loader.dart'; + +import 'fix_processor.dart'; + +main() { + defineReflectiveSuite(() { + defineReflectiveTests(ReplaceWithIdentifierTest); + }); +} + +@reflectiveTest +class ReplaceWithIdentifierTest extends FixProcessorLintTest { + @override + FixKind get kind => DartFixKind.REPLACE_WITH_IDENTIFIER; + + @override + String get lintCode => LintNames.avoid_types_on_closure_parameters; + + test_functionTypedFormalParameter() async { + await resolveTestUnit(''' +var functionWithFunction = (/*LINT*/int f(int x)) => f(0); +'''); + await assertHasFix(''' +var functionWithFunction = (/*LINT*/f) => f(0); +'''); + } +}
diff --git a/pkg/analysis_server/test/src/services/correction/fix/replace_with_literal_test.dart b/pkg/analysis_server/test/src/services/correction/fix/replace_with_literal_test.dart new file mode 100644 index 0000000..7ec1088 --- /dev/null +++ b/pkg/analysis_server/test/src/services/correction/fix/replace_with_literal_test.dart
@@ -0,0 +1,113 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:analysis_server/src/services/correction/fix.dart'; +import 'package:analysis_server/src/services/correction/fix_internal.dart'; +import 'package:analyzer_plugin/utilities/fixes/fixes.dart'; +import 'package:test_reflective_loader/test_reflective_loader.dart'; + +import 'fix_processor.dart'; + +main() { + defineReflectiveSuite(() { + defineReflectiveTests(ReplaceWithLiteralTest); + }); +} + +@reflectiveTest +class ReplaceWithLiteralTest extends FixProcessorLintTest { + @override + FixKind get kind => DartFixKind.REPLACE_WITH_LITERAL; + + @override + String get lintCode => LintNames.prefer_collection_literals; + + test_linkedHashMap_withCommentsInGeneric() async { + await resolveTestUnit(''' +import 'dart:collection'; + +final a = /*LINT*/new LinkedHashMap<int,/*comment*/int>(); +'''); + await assertHasFix(''' +import 'dart:collection'; + +final a = /*LINT*/<int,/*comment*/int>{}; +'''); + } + + test_linkedHashMap_withDynamicGenerics() async { + await resolveTestUnit(''' +import 'dart:collection'; + +final a = /*LINT*/new LinkedHashMap<dynamic,dynamic>(); +'''); + await assertHasFix(''' +import 'dart:collection'; + +final a = /*LINT*/<dynamic,dynamic>{}; +'''); + } + + test_linkedHashMap_withGeneric() async { + await resolveTestUnit(''' +import 'dart:collection'; + +final a = /*LINT*/new LinkedHashMap<int,int>(); +'''); + await assertHasFix(''' +import 'dart:collection'; + +final a = /*LINT*/<int,int>{}; +'''); + } + + test_linkedHashMap_withoutGeneric() async { + await resolveTestUnit(''' +import 'dart:collection'; + +final a = /*LINT*/new LinkedHashMap(); +'''); + await assertHasFix(''' +import 'dart:collection'; + +final a = /*LINT*/{}; +'''); + } + + test_list_withGeneric() async { + await resolveTestUnit(''' +final a = /*LINT*/new List<int>(); +'''); + await assertHasFix(''' +final a = /*LINT*/<int>[]; +'''); + } + + test_list_withoutGeneric() async { + await resolveTestUnit(''' +final a = /*LINT*/new List(); +'''); + await assertHasFix(''' +final a = /*LINT*/[]; +'''); + } + + test_map_withGeneric() async { + await resolveTestUnit(''' +final a = /*LINT*/new Map<int,int>(); +'''); + await assertHasFix(''' +final a = /*LINT*/<int,int>{}; +'''); + } + + test_map_withoutGeneric() async { + await resolveTestUnit(''' +final a = /*LINT*/new Map(); +'''); + await assertHasFix(''' +final a = /*LINT*/{}; +'''); + } +}
diff --git a/pkg/analysis_server/test/src/services/correction/fix/replace_with_null_aware_test.dart b/pkg/analysis_server/test/src/services/correction/fix/replace_with_null_aware_test.dart new file mode 100644 index 0000000..f758081 --- /dev/null +++ b/pkg/analysis_server/test/src/services/correction/fix/replace_with_null_aware_test.dart
@@ -0,0 +1,60 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:analysis_server/src/services/correction/fix.dart'; +import 'package:analyzer_plugin/utilities/fixes/fixes.dart'; +import 'package:test_reflective_loader/test_reflective_loader.dart'; + +import 'fix_processor.dart'; + +main() { + defineReflectiveSuite(() { + defineReflectiveTests(ReplaceWithNullAwareTest); + }); +} + +@reflectiveTest +class ReplaceWithNullAwareTest extends FixProcessorTest { + @override + FixKind get kind => DartFixKind.REPLACE_WITH_NULL_AWARE; + + test_chain() async { + await resolveTestUnit(''' +main(x) { + x?.a.b.c; +} +'''); + await assertHasFix(''' +main(x) { + x?.a?.b?.c; +} +'''); + } + + test_methodInvocation() async { + await resolveTestUnit(''' +main(x) { + x?.a.b(); +} +'''); + await assertHasFix(''' +main(x) { + x?.a?.b(); +} +'''); + } + + test_propertyAccess() async { + await resolveTestUnit(''' +main(x) { + x?.a().b; +} +'''); + await assertHasFix(''' +main(x) { + x?.a()?.b; +} +'''); + } +}
diff --git a/pkg/analysis_server/test/src/services/correction/fix/replace_with_tear_off_test.dart b/pkg/analysis_server/test/src/services/correction/fix/replace_with_tear_off_test.dart new file mode 100644 index 0000000..ccc757a --- /dev/null +++ b/pkg/analysis_server/test/src/services/correction/fix/replace_with_tear_off_test.dart
@@ -0,0 +1,97 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:analysis_server/src/services/correction/fix.dart'; +import 'package:analysis_server/src/services/correction/fix_internal.dart'; +import 'package:analyzer_plugin/utilities/fixes/fixes.dart'; +import 'package:test_reflective_loader/test_reflective_loader.dart'; + +import 'fix_processor.dart'; + +main() { + defineReflectiveSuite(() { + defineReflectiveTests(ReplaceWithTearOffTest); + }); +} + +@reflectiveTest +class ReplaceWithTearOffTest extends FixProcessorLintTest { + @override + FixKind get kind => DartFixKind.REPLACE_WITH_TEAR_OFF; + + @override + String get lintCode => LintNames.unnecessary_lambdas; + + test_function_oneParameter() async { + await resolveTestUnit(''' +final x = /*LINT*/(name) { + print(name); +}; +'''); + await assertHasFix(''' +final x = /*LINT*/print; +'''); + } + + test_function_zeroParameters() async { + await resolveTestUnit(''' +void foo(){} +Function finalVar() { + return /*LINT*/() { + foo(); + }; +} +'''); + await assertHasFix(''' +void foo(){} +Function finalVar() { + return /*LINT*/foo; +} +'''); + } + + test_lambda_asArgument() async { + await resolveTestUnit(''' +void foo() { + bool isPair(int a) => a % 2 == 0; + final finalList = <int>[]; + finalList.where(/*LINT*/(number) => + isPair(number)); +} +'''); + await assertHasFix(''' +void foo() { + bool isPair(int a) => a % 2 == 0; + final finalList = <int>[]; + finalList.where(/*LINT*/isPair); +} +'''); + } + + test_method_oneParameter() async { + await resolveTestUnit(''' +var a = /*LINT*/(x) => finalList.remove(x); +'''); + await assertHasFix(''' +var a = /*LINT*/finalList.remove; +'''); + } + + test_method_zeroParameter() async { + await resolveTestUnit(''' +final Object a; +Function finalVar() { + return /*LINT*/() { + return a.toString(); + }; +} +'''); + await assertHasFix(''' +final Object a; +Function finalVar() { + return /*LINT*/a.toString; +} +'''); + } +}
diff --git a/pkg/analysis_server/test/src/services/correction/fix/test_all.dart b/pkg/analysis_server/test/src/services/correction/fix/test_all.dart new file mode 100644 index 0000000..de6f043 --- /dev/null +++ b/pkg/analysis_server/test/src/services/correction/fix/test_all.dart
@@ -0,0 +1,180 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:test_reflective_loader/test_reflective_loader.dart'; + +import 'add_async_test.dart' as add_async; +import 'add_explicit_cast_test.dart' as add_explicit_cast; +import 'add_field_formal_parameters_test.dart' as add_field_formal_parameters; +import 'add_missing_parameter_named_test.dart' as add_missing_parameter_named; +import 'add_missing_parameter_positional_test.dart' + as add_missing_parameter_positional; +import 'add_missing_parameter_required_test.dart' + as add_missing_parameter_required; +import 'add_missing_required_argument_test.dart' + as add_missing_required_argument; +import 'add_ne_null_test.dart' as add_ne_null; +import 'add_override_test.dart' as add_override; +import 'add_required_test.dart' as add_required; +import 'add_static_test.dart' as add_static; +import 'add_super_constructor_invocation_test.dart' + as add_super_constructor_invocation; +import 'change_to_nearest_precise_value_test.dart' + as change_to_nearest_precise_value; +import 'change_to_static_access_test.dart' as change_to_static_access; +import 'change_to_test.dart' as change_to; +import 'change_type_annotation_test.dart' as change_type_annotation; +import 'convert_flutter_child_test.dart' as convert_flutter_child; +import 'convert_flutter_children_test.dart' as convert_flutter_children; +import 'convert_to_named_arguments_test.dart' as convert_to_named_arguments; +import 'create_class_test.dart' as create_class; +import 'create_constructor_for_final_fields_test.dart' + as create_constructor_for_final_field; +import 'create_constructor_super_test.dart' as create_constructor_super; +import 'create_constructor_test.dart' as create_constructor; +import 'create_field_test.dart' as create_field; +import 'create_file_test.dart' as create_file; +import 'create_function_test.dart' as create_function; +import 'create_getter_test.dart' as create_getter; +import 'create_local_variable_test.dart' as create_local_variable; +import 'create_method_test.dart' as create_method; +import 'create_missing_overrides_test.dart' as create_missing_overrides; +import 'create_mixin_test.dart' as create_mixin; +import 'create_no_such_method_test.dart' as create_no_such_method; +import 'extend_class_for_mixin_test.dart' as extend_class_for_mixin; +import 'fix_test.dart' as fix; +import 'import_async_test.dart' as import_async; +import 'import_library_prefix_test.dart' as import_library_prefix; +import 'import_library_project_test.dart' as import_library_project; +import 'import_library_sdk_test.dart' as import_library_sdk; +import 'import_library_show_test.dart' as import_library_show; +import 'insert_semicolon_test.dart' as insert_semicolon; +import 'make_class_abstract_test.dart' as make_class_abstract; +import 'make_field_not_final_test.dart' as make_field_not_final; +import 'make_final_test.dart' as make_final; +import 'move_type_arguments_to_class_test.dart' as move_type_arguments_to_class; +import 'remove_await_test.dart' as remove_await; +import 'remove_dead_code_test.dart' as remove_dead_code; +import 'remove_empty_catch_test.dart' as remove_empty_catch; +import 'remove_empty_constructor_body_test.dart' + as remove_empty_constructor_body; +import 'remove_empty_else_test.dart' as remove_empty_else; +import 'remove_empty_statement_test.dart' as remove_empty_statement; +import 'remove_initializer_test.dart' as remove_initializer; +import 'remove_interpolation_braces_test.dart' as remove_interpolation_braces; +import 'remove_method_declaration_test.dart' as remove_method_declaration; +import 'remove_parameters_in_getter_declaration_test.dart' + as remove_parameters_in_getter_declaration; +import 'remove_parentheses_in_getter_invocation_test.dart' + as remove_parentheses_in_getter_invocation; +import 'remove_this_expression_test.dart' as remove_this_expression; +import 'remove_type_annotation_test.dart' as remove_type_annotation; +import 'remove_type_arguments_test.dart' as remove_type_arguments; +import 'remove_unnecessary_cast_test.dart' as remove_unnecessary_cast; +import 'remove_unused_catch_clause_test.dart' as remove_unused_catch_clause; +import 'remove_unused_catch_stack_test.dart' as remove_unused_catch_stack; +import 'remove_unused_import_test.dart' as remove_unused_import; +import 'rename_to_camel_case_test.dart' as rename_to_camel_case; +import 'replace_boolean_with_bool_test.dart' as replace_boolean_with_bool; +import 'replace_final_with_const_test.dart' as replace_final_with_const; +import 'replace_return_type_future_test.dart' as replace_return_type_future; +import 'replace_var_with_dynamic_test.dart' as replace_var_with_dynamic; +import 'replace_with_brackets_test.dart' as replace_with_brackets; +import 'replace_with_conditional_assignment_test.dart' + as replace_with_conditional_assignment; +import 'replace_with_identifier_test.dart' as replace_with_identifier; +import 'replace_with_literal_test.dart' as replace_with_literal; +import 'replace_with_null_aware_test.dart' as replace_with_null_aware; +import 'replace_with_tear_off_test.dart' as replace_with_tear_off; +import 'update_sdk_constraints_test.dart' as update_sdk_constraints; +import 'use_const_test.dart' as use_const; +import 'use_effective_integer_division_test.dart' + as use_effective_integer_division; +import 'use_eq_eq_null_test.dart' as use_eq_eq_null; +import 'use_is_not_empty_test.dart' as use_is_not_empty; +import 'use_not_eq_null_test.dart' as use_not_eq_null; + +main() { + defineReflectiveSuite(() { + add_async.main(); + add_explicit_cast.main(); + add_field_formal_parameters.main(); + add_missing_parameter_named.main(); + add_missing_parameter_positional.main(); + add_missing_parameter_required.main(); + add_missing_required_argument.main(); + add_ne_null.main(); + add_override.main(); + add_required.main(); + add_static.main(); + add_super_constructor_invocation.main(); + change_to.main(); + change_to_nearest_precise_value.main(); + change_to_static_access.main(); + change_type_annotation.main(); + convert_flutter_child.main(); + convert_flutter_children.main(); + convert_to_named_arguments.main(); + create_class.main(); + create_constructor_for_final_field.main(); + create_constructor_super.main(); + create_constructor.main(); + create_field.main(); + create_file.main(); + create_function.main(); + create_getter.main(); + create_local_variable.main(); + create_method.main(); + create_missing_overrides.main(); + create_mixin.main(); + create_no_such_method.main(); + extend_class_for_mixin.main(); + fix.main(); + import_async.main(); + import_library_prefix.main(); + import_library_project.main(); + import_library_sdk.main(); + import_library_show.main(); + insert_semicolon.main(); + make_class_abstract.main(); + make_field_not_final.main(); + make_final.main(); + move_type_arguments_to_class.main(); + remove_await.main(); + remove_dead_code.main(); + remove_empty_catch.main(); + remove_empty_constructor_body.main(); + remove_empty_else.main(); + remove_empty_statement.main(); + remove_initializer.main(); + remove_interpolation_braces.main(); + remove_method_declaration.main(); + remove_parameters_in_getter_declaration.main(); + remove_parentheses_in_getter_invocation.main(); + remove_this_expression.main(); + remove_type_annotation.main(); + remove_type_arguments.main(); + remove_unnecessary_cast.main(); + remove_unused_catch_clause.main(); + remove_unused_catch_stack.main(); + remove_unused_import.main(); + rename_to_camel_case.main(); + replace_boolean_with_bool.main(); + replace_final_with_const.main(); + replace_return_type_future.main(); + replace_var_with_dynamic.main(); + replace_with_brackets.main(); + replace_with_conditional_assignment.main(); + replace_with_literal.main(); + replace_with_identifier.main(); + replace_with_null_aware.main(); + replace_with_tear_off.main(); + update_sdk_constraints.main(); + use_const.main(); + use_effective_integer_division.main(); + use_eq_eq_null.main(); + use_is_not_empty.main(); + use_not_eq_null.main(); + }, name: 'fix'); +}
diff --git a/pkg/analysis_server/test/src/services/correction/fix/update_sdk_constraints_test.dart b/pkg/analysis_server/test/src/services/correction/fix/update_sdk_constraints_test.dart new file mode 100644 index 0000000..4b957b3 --- /dev/null +++ b/pkg/analysis_server/test/src/services/correction/fix/update_sdk_constraints_test.dart
@@ -0,0 +1,55 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:analysis_server/src/services/correction/fix.dart'; +import 'package:analyzer_plugin/utilities/fixes/fixes.dart'; +import 'package:test_reflective_loader/test_reflective_loader.dart'; + +import 'fix_processor.dart'; + +main() { + defineReflectiveSuite(() { + defineReflectiveTests(UpdateSdkConstraintsTest); + }); +} + +@reflectiveTest +class UpdateSdkConstraintsTest extends FixProcessorTest { + @override + FixKind get kind => DartFixKind.UPDATE_SDK_CONSTRAINTS; + + test_any() async { + await testUpdate(from: 'any', to: '^2.1.0'); + } + + test_caret() async { + await testUpdate(from: '^2.0.0', to: '^2.1.0'); + } + + test_compound() async { + await testUpdate(from: "'>=2.0.0 <3.0.0'", to: "'>=2.1.0 <3.0.0'"); + } + + test_gt() async { + await testUpdate(from: "'>2.0.0'", to: "'>=2.1.0'"); + } + + test_gte() async { + await testUpdate(from: "'>=2.0.0'", to: "'>=2.1.0'"); + } + + testUpdate({String from, String to}) async { + updateTestPubspecFile(''' +environment: + sdk: $from +'''); + await resolveTestUnit(''' +Future<int> zero() async => 0; +'''); + await assertHasFix(''' +environment: + sdk: $to +''', target: testPubspecPath); + } +}
diff --git a/pkg/analysis_server/test/src/services/correction/fix/use_const_test.dart b/pkg/analysis_server/test/src/services/correction/fix/use_const_test.dart new file mode 100644 index 0000000..9ac1952 --- /dev/null +++ b/pkg/analysis_server/test/src/services/correction/fix/use_const_test.dart
@@ -0,0 +1,36 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:analysis_server/src/services/correction/fix.dart'; +import 'package:analyzer_plugin/utilities/fixes/fixes.dart'; +import 'package:test_reflective_loader/test_reflective_loader.dart'; + +import 'fix_processor.dart'; + +main() { + defineReflectiveSuite(() { + defineReflectiveTests(UseConstTest); + }); +} + +@reflectiveTest +class UseConstTest extends FixProcessorTest { + @override + FixKind get kind => DartFixKind.USE_CONST; + + test_explicitNew() async { + await resolveTestUnit(''' +class A { + const A(); +} +const a = new A(); +'''); + await assertHasFix(''' +class A { + const A(); +} +const a = const A(); +'''); + } +}
diff --git a/pkg/analysis_server/test/src/services/correction/fix/use_effective_integer_division_test.dart b/pkg/analysis_server/test/src/services/correction/fix/use_effective_integer_division_test.dart new file mode 100644 index 0000000..770f505 --- /dev/null +++ b/pkg/analysis_server/test/src/services/correction/fix/use_effective_integer_division_test.dart
@@ -0,0 +1,38 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:analysis_server/src/services/correction/fix.dart'; +import 'package:analyzer_plugin/utilities/fixes/fixes.dart'; +import 'package:test_reflective_loader/test_reflective_loader.dart'; + +import 'fix_processor.dart'; + +main() { + defineReflectiveSuite(() { + defineReflectiveTests(UseEffectiveIntegerDivisionTest); + }); +} + +@reflectiveTest +class UseEffectiveIntegerDivisionTest extends FixProcessorTest { + @override + FixKind get kind => DartFixKind.USE_EFFECTIVE_INTEGER_DIVISION; + + test_normalDivision() async { + await resolveTestUnit(''' +main() { + var a = 5; + var b = 2; + print((a / b).toInt()); +} +'''); + await assertHasFix(''' +main() { + var a = 5; + var b = 2; + print(a ~/ b); +} +'''); + } +}
diff --git a/pkg/analysis_server/test/src/services/correction/fix/use_eq_eq_null_test.dart b/pkg/analysis_server/test/src/services/correction/fix/use_eq_eq_null_test.dart new file mode 100644 index 0000000..de6b873 --- /dev/null +++ b/pkg/analysis_server/test/src/services/correction/fix/use_eq_eq_null_test.dart
@@ -0,0 +1,50 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:analysis_server/src/services/correction/fix.dart'; +import 'package:analyzer/src/error/codes.dart'; +import 'package:analyzer_plugin/utilities/fixes/fixes.dart'; +import 'package:test_reflective_loader/test_reflective_loader.dart'; + +import 'fix_processor.dart'; + +main() { + defineReflectiveSuite(() { + defineReflectiveTests(UseEqEqNullTest); + }); +} + +@reflectiveTest +class UseEqEqNullTest extends FixProcessorTest { + @override + FixKind get kind => DartFixKind.USE_EQ_EQ_NULL; + + test_isNull() async { + await resolveTestUnit(''' +main(p) { + p is Null; +} +'''); + await assertHasFix(''' +main(p) { + p == null; +} +'''); + } + + test_isNull_all() async { + await resolveTestUnit(''' +main(p, q) { + p is Null; + q is Null; +} +'''); + await assertHasFixAllFix(HintCode.TYPE_CHECK_IS_NULL, ''' +main(p, q) { + p == null; + q == null; +} +'''); + } +}
diff --git a/pkg/analysis_server/test/src/services/correction/fix/use_is_not_empty_test.dart b/pkg/analysis_server/test/src/services/correction/fix/use_is_not_empty_test.dart new file mode 100644 index 0000000..ab2da21 --- /dev/null +++ b/pkg/analysis_server/test/src/services/correction/fix/use_is_not_empty_test.dart
@@ -0,0 +1,38 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:analysis_server/src/services/correction/fix.dart'; +import 'package:analysis_server/src/services/correction/fix_internal.dart'; +import 'package:analyzer_plugin/utilities/fixes/fixes.dart'; +import 'package:test_reflective_loader/test_reflective_loader.dart'; + +import 'fix_processor.dart'; + +main() { + defineReflectiveSuite(() { + defineReflectiveTests(UseIsNotEmptyTest); + }); +} + +@reflectiveTest +class UseIsNotEmptyTest extends FixProcessorLintTest { + @override + FixKind get kind => DartFixKind.USE_IS_NOT_EMPTY; + + @override + String get lintCode => LintNames.prefer_is_not_empty; + + test_notIsEmpty() async { + await resolveTestUnit(''' +f(c) { + if (/*LINT*/!c.isEmpty) {} +} +'''); + await assertHasFix(''' +f(c) { + if (/*LINT*/c.isNotEmpty) {} +} +'''); + } +}
diff --git a/pkg/analysis_server/test/src/services/correction/fix/use_not_eq_null_test.dart b/pkg/analysis_server/test/src/services/correction/fix/use_not_eq_null_test.dart new file mode 100644 index 0000000..3fdd82a --- /dev/null +++ b/pkg/analysis_server/test/src/services/correction/fix/use_not_eq_null_test.dart
@@ -0,0 +1,50 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:analysis_server/src/services/correction/fix.dart'; +import 'package:analyzer/src/error/codes.dart'; +import 'package:analyzer_plugin/utilities/fixes/fixes.dart'; +import 'package:test_reflective_loader/test_reflective_loader.dart'; + +import 'fix_processor.dart'; + +main() { + defineReflectiveSuite(() { + defineReflectiveTests(UseNotEqNullTest); + }); +} + +@reflectiveTest +class UseNotEqNullTest extends FixProcessorTest { + @override + FixKind get kind => DartFixKind.USE_NOT_EQ_NULL; + + test_isNotNull() async { + await resolveTestUnit(''' +main(p) { + p is! Null; +} +'''); + await assertHasFix(''' +main(p) { + p != null; +} +'''); + } + + test_isNotNull_all() async { + await resolveTestUnit(''' +main(p, q) { + p is! Null; + q is! Null; +} +'''); + await assertHasFixAllFix(HintCode.TYPE_CHECK_IS_NOT_NULL, ''' +main(p, q) { + p != null; + q != null; +} +'''); + } +}
diff --git a/pkg/analysis_server/test/src/services/correction/test_all.dart b/pkg/analysis_server/test/src/services/correction/test_all.dart new file mode 100644 index 0000000..7c6c49d --- /dev/null +++ b/pkg/analysis_server/test/src/services/correction/test_all.dart
@@ -0,0 +1,15 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:test_reflective_loader/test_reflective_loader.dart'; + +import 'assist/test_all.dart' as assist_all; +import 'fix/test_all.dart' as fix_all; + +main() { + defineReflectiveSuite(() { + assist_all.main(); + fix_all.main(); + }, name: 'correction'); +}
diff --git a/pkg/analysis_server/test/src/services/test_all.dart b/pkg/analysis_server/test/src/services/test_all.dart new file mode 100644 index 0000000..46f575f --- /dev/null +++ b/pkg/analysis_server/test/src/services/test_all.dart
@@ -0,0 +1,13 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:test_reflective_loader/test_reflective_loader.dart'; + +import 'correction/test_all.dart' as correction_all; + +main() { + defineReflectiveSuite(() { + correction_all.main(); + }, name: 'services'); +}
diff --git a/pkg/analysis_server/test/src/test_all.dart b/pkg/analysis_server/test/src/test_all.dart index c25b65a..6a07ced 100644 --- a/pkg/analysis_server/test/src/test_all.dart +++ b/pkg/analysis_server/test/src/test_all.dart
@@ -1,4 +1,4 @@ -// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file +// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. @@ -6,8 +6,10 @@ import 'computer/test_all.dart' as computer_all; import 'domain_abstract_test.dart' as domain_abstract_test; +import 'domains/test_all.dart' as domains_all; import 'flutter/test_all.dart' as flutter_all; import 'plugin/test_all.dart' as plugin_all; +import 'services/test_all.dart' as services_all; import 'utilities/test_all.dart' as utilities_all; import 'watch_manager_test.dart' as watch_manager_test; @@ -18,8 +20,10 @@ defineReflectiveSuite(() { computer_all.main(); domain_abstract_test.main(); + domains_all.main(); flutter_all.main(); plugin_all.main(); + services_all.main(); utilities_all.main(); watch_manager_test.main(); }, name: 'src');
diff --git a/pkg/analysis_server/test/src/utilities/flutter_util.dart b/pkg/analysis_server/test/src/utilities/flutter_util.dart index 6e689e5..286b2c4 100644 --- a/pkg/analysis_server/test/src/utilities/flutter_util.dart +++ b/pkg/analysis_server/test/src/utilities/flutter_util.dart
@@ -27,6 +27,7 @@ '''); newFile('$flutterPkgLibPath/widgets.dart', r''' +export 'src/widgets/async.dart'; export 'src/widgets/basic.dart'; export 'src/widgets/container.dart'; export 'src/widgets/framework.dart'; @@ -159,6 +160,25 @@ } void createSrcWidgets() { + newFile('$flutterPkgLibPath/src/widgets/async.dart', r''' +import 'framework.dart'; + +class AsyncSnapshot<T> {} + +typedef AsyncWidgetBuilder<T> = Widget Function(BuildContext context, AsyncSnapshot<T> snapshot); + +class StreamBuilder<T> { + const StreamBuilder({ + Key key, + this.initialData, + Stream<T> stream, + @required this.builder + }); + final T initialData; + final AsyncWidgetBuilder<T> builder; +} +'''); + newFile('$flutterPkgLibPath/src/widgets/basic.dart', r''' import 'package:flutter/rendering.dart';
diff --git a/pkg/analysis_server/test/src/watch_manager_test.dart b/pkg/analysis_server/test/src/watch_manager_test.dart index 248c5b0..a5a4a93 100644 --- a/pkg/analysis_server/test/src/watch_manager_test.dart +++ b/pkg/analysis_server/test/src/watch_manager_test.dart
@@ -1,4 +1,4 @@ -// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file +// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. @@ -70,7 +70,7 @@ } @reflectiveTest -class WatchManagerTest extends Object with ResourceProviderMixin { +class WatchManagerTest with ResourceProviderMixin { WatchListener listener; WatchManager<Token> manager; @@ -194,7 +194,7 @@ } @reflectiveTest -class WatchNodeTest extends Object with ResourceProviderMixin { +class WatchNodeTest with ResourceProviderMixin { void test_creation_folder() { Folder folder = getFolder('/a/b'); WatchNode node = new WatchNode(folder);
diff --git a/pkg/analysis_server/test/stress/completion/completion_runner.dart b/pkg/analysis_server/test/stress/completion/completion_runner.dart index 3605038..41a69b8 100644 --- a/pkg/analysis_server/test/stress/completion/completion_runner.dart +++ b/pkg/analysis_server/test/stress/completion/completion_runner.dart
@@ -103,8 +103,8 @@ } fileCount++; output.write('.'); - ResolveResult result = - await context.currentSession.getResolvedAst(path); + ResolvedUnitResult result = + await context.currentSession.getResolvedUnit(path); String content = result.content; LineInfo lineInfo = result.lineInfo; List<SimpleIdentifier> identifiers = _identifiersIn(result.unit); @@ -117,7 +117,7 @@ content.substring(identifier.end); resourceProvider.setOverlay(path, content: modifiedContent, modificationStamp: stamp++); - result = await context.currentSession.getResolvedAst(path); + result = await context.currentSession.getResolvedUnit(path); } timer.start();
diff --git a/pkg/analysis_server/test/tool/lsp_spec/dart_test.dart b/pkg/analysis_server/test/tool/lsp_spec/dart_test.dart index 068063c..bcffd7a 100644 --- a/pkg/analysis_server/test/tool/lsp_spec/dart_test.dart +++ b/pkg/analysis_server/test/tool/lsp_spec/dart_test.dart
@@ -4,45 +4,34 @@ import 'package:test/test.dart'; -import '../../../tool/lsp_spec/codegen_dart.dart'; +import '../../../tool/lsp_spec/typescript_parser.dart' as ast; main() { - group('mapType', () { + group('dartType mapping', () { test('handles basic types', () { - expect(mapType(['string']), equals('String')); - expect(mapType(['boolean']), equals('bool')); - expect(mapType(['any']), equals('dynamic')); - expect(mapType(['object']), equals('dynamic')); - expect(mapType(['int']), equals('int')); - expect(mapType(['num']), equals('num')); + expect(_simple('string').dartType, equals('String')); + expect(_simple('boolean').dartType, equals('bool')); + expect(_simple('any').dartType, equals('dynamic')); + expect(_simple('object').dartType, equals('dynamic')); + expect(_simple('int').dartType, equals('int')); + expect(_simple('num').dartType, equals('num')); }); test('handles union types', () { - expect(mapType(['string', 'int']), equals('Either2<String, int>')); - expect(mapType(['string | int']), equals('Either2<String, int>')); + expect(_union(['string', 'int']).dartTypeWithTypeArgs, + equals('Either2<String, int>')); }); test('handles arrays', () { - expect(mapType(['string[]']), equals('List<String>')); - expect(mapType(['Array<string>']), equals('List<String>')); - }); - - test('handles types with args', () { - expect(mapType(['Class<string[]>']), equals('Class<List<String>>')); - expect(mapType(['Array<string | num>']), - equals('List<Either2<String, num>>')); - }); - - test('handles complex nested types', () { - expect( - mapType([ - 'Array<string>', - 'any[]', - 'Response<A>', - 'Request<Array<string | num>>' - ]), - equals( - 'Either4<List<String>, List<dynamic>, Response<A>, Request<List<Either2<String, num>>>>')); + expect(_array('string').dartTypeWithTypeArgs, equals('List<String>')); }); }); } + +ast.Type _simple(String name) => + new ast.Type(new ast.Token(ast.TokenType.IDENTIFIER, name), []); + +ast.ArrayType _array(String name) => new ast.ArrayType(_simple(name)); + +ast.UnionType _union(List<String> names) => + new ast.UnionType(names.map(_simple).toList());
diff --git a/pkg/analysis_server/test/tool/lsp_spec/json_test.dart b/pkg/analysis_server/test/tool/lsp_spec/json_test.dart index e12b850..b352d18 100644 --- a/pkg/analysis_server/test/tool/lsp_spec/json_test.dart +++ b/pkg/analysis_server/test/tool/lsp_spec/json_test.dart
@@ -18,23 +18,21 @@ }); test('returns correct output for union types', () { - final message = - new RequestMessage(new Either2.t1(1), "test", null, "test"); + final message = new RequestMessage( + new Either2<num, String>.t1(1), Method.shutdown, null, "test"); String output = json.encode(message.toJson()); - expect(output, equals('{"id":1,"method":"test","jsonrpc":"test"}')); + expect(output, equals('{"id":1,"method":"shutdown","jsonrpc":"test"}')); }); test('returns correct output for union types containing interface types', () { - final params = new Either2<String, WorkspaceClientCapabilities>.t2( - new WorkspaceClientCapabilities( - true, - null, - null, - null, - )); + final params = new Either2<String, TextDocumentItem>.t2( + new TextDocumentItem('!uri', '!language', 1, '!text')); String output = json.encode(params); - expect(output, equals('{"applyEdit":true}')); + expect( + output, + equals( + '{"uri":"!uri","languageId":"!language","version":1,"text":"!text"}')); }); test('returns correct output for types with lists', () { @@ -45,7 +43,7 @@ final codeAction = new Diagnostic( range, DiagnosticSeverity.Error, - new Either2.t2('test_err'), + 'test_err', '/tmp/source.dart', 'err!!', [new DiagnosticRelatedInformation(location, 'message')], @@ -95,51 +93,81 @@ group('fromJson', () { test('parses JSON for types with unions (left side)', () { - final input = '{"id":1,"method":"test","jsonrpc":"test"}'; - final message = new RequestMessage.fromJson(jsonDecode(input)); + final input = '{"id":1,"method":"shutdown","jsonrpc":"test"}'; + final message = RequestMessage.fromJson(jsonDecode(input)); expect(message.id, equals(new Either2<num, String>.t1(1))); expect(message.id.valueEquals(1), isTrue); expect(message.jsonrpc, "test"); - expect(message.method, "test"); + expect(message.method, Method.shutdown); }); test('parses JSON for types with unions (right side)', () { - final input = '{"id":"one","method":"test","jsonrpc":"test"}'; - final message = new RequestMessage.fromJson(jsonDecode(input)); + final input = '{"id":"one","method":"shutdown","jsonrpc":"test"}'; + final message = RequestMessage.fromJson(jsonDecode(input)); expect(message.id, equals(new Either2<num, String>.t2("one"))); expect(message.id.valueEquals("one"), isTrue); expect(message.jsonrpc, "test"); - expect(message.method, "test"); + expect(message.method, Method.shutdown); + }); + + test('parses JSON with nulls for unions that allow null', () { + final input = '{"id":null,"jsonrpc":"test"}'; + final message = ResponseMessage.fromJson(jsonDecode(input)); + expect(message.id, isNull); + }); + + test('parses JSON with nulls for unions that allow null', () { + final input = '{"method":"test","jsonrpc":"test"}'; + final message = NotificationMessage.fromJson(jsonDecode(input)); + expect(message.params, isNull); }); }); - test('objects with lists and enums can round-trip through to json and back', - () { - final obj = new ClientCapabilities( - new WorkspaceClientCapabilities( - true, - false, - [ResourceOperationKind.Create, ResourceOperationKind.Delete], - FailureHandlingKind.Undo), - new TextDocumentClientCapabilities(true, false, true, false), - null); + test('objects with lists can round-trip through to json and back', () { + final obj = new InitializeParams(1, '!root', null, null, + new ClientCapabilities(null, null, null), '!trace', [ + new WorkspaceFolder('!uri1', '!name1'), + new WorkspaceFolder('!uri2', '!name2'), + ]); final String json = jsonEncode(obj); - final restoredObj = new ClientCapabilities.fromJson(jsonDecode(json)); + final restoredObj = InitializeParams.fromJson(jsonDecode(json)); - expect(restoredObj.workspace.applyEdit, equals(obj.workspace.applyEdit)); - expect(restoredObj.workspace.documentChanges, - equals(obj.workspace.documentChanges)); - expect(restoredObj.workspace.resourceOperations, - equals(obj.workspace.resourceOperations)); - expect(restoredObj.workspace.failureHandling, - equals(obj.workspace.failureHandling)); - expect(restoredObj.textDocument.didSave, equals(obj.textDocument.didSave)); - expect(restoredObj.textDocument.dynamicRegistration, - equals(obj.textDocument.dynamicRegistration)); expect( - restoredObj.textDocument.willSave, equals(obj.textDocument.willSave)); - expect(restoredObj.textDocument.willSaveWaitUntil, - equals(obj.textDocument.willSaveWaitUntil)); - expect(restoredObj.experimental, equals(obj.experimental)); + restoredObj.workspaceFolders, hasLength(obj.workspaceFolders.length)); + for (var i = 0; i < obj.workspaceFolders.length; i++) { + expect(restoredObj.workspaceFolders[i].name, + equals(obj.workspaceFolders[i].name)); + expect(restoredObj.workspaceFolders[i].uri, + equals(obj.workspaceFolders[i].uri)); + } + }); + + test('objects with enums can round-trip through to json and back', () { + final obj = new FoldingRange(1, 2, 3, 4, FoldingRangeKind.Comment); + final String json = jsonEncode(obj); + final restoredObj = FoldingRange.fromJson(jsonDecode(json)); + + expect(restoredObj.startLine, equals(obj.startLine)); + expect(restoredObj.startCharacter, equals(obj.startCharacter)); + expect(restoredObj.endLine, equals(obj.endLine)); + expect(restoredObj.endCharacter, equals(obj.endCharacter)); + expect(restoredObj.kind, equals(obj.kind)); + }); + + test('objects with maps can round-trip through to json and back', () { + final start = new Position(1, 1); + final end = new Position(2, 2); + final range = new Range(start, end); + final obj = new WorkspaceEdit(<String, List<TextEdit>>{ + 'fileA': [new TextEdit(range, 'text A')], + 'fileB': [new TextEdit(range, 'text B')] + }, null); + final String json = jsonEncode(obj); + final restoredObj = WorkspaceEdit.fromJson(jsonDecode(json)); + + expect(restoredObj.documentChanges, equals(obj.documentChanges)); + expect(restoredObj.changes, equals(obj.changes)); + expect(restoredObj.changes.keys, equals(obj.changes.keys)); + expect(restoredObj.changes.values, equals(obj.changes.values)); }); }
diff --git a/pkg/analysis_server/test/tool/lsp_spec/matchers.dart b/pkg/analysis_server/test/tool/lsp_spec/matchers.dart new file mode 100644 index 0000000..72ee321 --- /dev/null +++ b/pkg/analysis_server/test/tool/lsp_spec/matchers.dart
@@ -0,0 +1,82 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:analysis_server/lsp_protocol/protocol_generated.dart'; +import 'package:matcher/matcher.dart'; + +import '../../../tool/lsp_spec/typescript_parser.dart'; + +Matcher isSimpleType(String name) => new SimpleTypeMatcher(name); + +class SimpleTypeMatcher extends Matcher { + final String _expectedName; + const SimpleTypeMatcher(this._expectedName); + + bool matches(item, Map matchState) { + return item is Type && item.name == _expectedName; + } + + Description describe(Description description) => + description.add('a type with the name $_expectedName'); + + Description describeMismatch( + item, Description mismatchDescription, Map matchState, bool verbose) { + if (item is Type) { + return mismatchDescription + .add('has the name ') + .addDescriptionOf(item.name); + } else { + return mismatchDescription.add('is not a Type'); + } + } +} + +Matcher isArrayOf(Matcher matcher) => + new ArrayTypeMatcher(wrapMatcher(matcher)); + +class ArrayTypeMatcher extends Matcher { + final Matcher _elementTypeMatcher; + const ArrayTypeMatcher(this._elementTypeMatcher); + + bool matches(item, Map matchState) { + return item is ArrayType && + _elementTypeMatcher.matches(item.elementType, matchState); + } + + Description describe(Description description) => + description.add('an array of ').addDescriptionOf(_elementTypeMatcher); + + Description describeMismatch( + item, Description mismatchDescription, Map matchState, bool verbose) { + if (item is ArrayType) { + return _elementTypeMatcher.describeMismatch( + item, mismatchDescription, matchState, verbose); + } else { + return mismatchDescription.add('is not an ArrayType'); + } + } +} + +Matcher isMapOf(Matcher indexMatcher, Matcher valueMatcher) => + new MapTypeMatcher(wrapMatcher(indexMatcher), wrapMatcher(valueMatcher)); + +class MapTypeMatcher extends Matcher { + final Matcher _indexMatcher, _valueMatcher; + const MapTypeMatcher(this._indexMatcher, this._valueMatcher); + + bool matches(item, Map matchState) { + return item is MapType && + _indexMatcher.matches(item.indexType, matchState) && + _valueMatcher.matches(item.valueType, matchState); + } + + Description describe(Description description) => description + .add('a MapType where index is ') + .addDescriptionOf(_indexMatcher) + .add(' and value is ') + .addDescriptionOf(_valueMatcher); +} + +Matcher isResponseError(ErrorCodes code) => const TypeMatcher<ResponseError>() + .having((e) => e.code, 'code', equals(code));
diff --git a/pkg/analysis_server/test/tool/lsp_spec/test_all.dart b/pkg/analysis_server/test/tool/lsp_spec/test_all.dart new file mode 100644 index 0000000..1edfb80 --- /dev/null +++ b/pkg/analysis_server/test/tool/lsp_spec/test_all.dart
@@ -0,0 +1,19 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:test_reflective_loader/test_reflective_loader.dart'; + +import 'dart_test.dart' as dart_test; +import 'json_test.dart' as json_test; +import 'markdown_test.dart' as markdown_test; +import 'typescript_test.dart' as typescript_test; + +main() { + defineReflectiveSuite(() { + dart_test.main(); + json_test.main(); + markdown_test.main(); + typescript_test.main(); + }, name: 'lsp-tool'); +}
diff --git a/pkg/analysis_server/test/tool/lsp_spec/typescript_test.dart b/pkg/analysis_server/test/tool/lsp_spec/typescript_test.dart index 1fad598..d03b5fb 100644 --- a/pkg/analysis_server/test/tool/lsp_spec/typescript_test.dart +++ b/pkg/analysis_server/test/tool/lsp_spec/typescript_test.dart
@@ -4,7 +4,8 @@ import 'package:test/test.dart'; -import '../../../tool/lsp_spec/typescript.dart'; +import '../../../tool/lsp_spec/typescript_parser.dart'; +import 'matchers.dart'; main() { group('typescript parser', () { @@ -20,22 +21,57 @@ options?: OptionKind[]; } '''; - final List<ApiItem> output = extractTypes(input); + final List<AstNode> output = parseFile(input); expect(output, hasLength(1)); expect(output[0], const TypeMatcher<Interface>()); final Interface interface = output[0]; expect(interface.name, equals('SomeOptions')); - expect(interface.comment, equals('Some options.')); + expect(interface.commentText, equals('Some options.')); expect(interface.baseTypes, hasLength(0)); expect(interface.members, hasLength(1)); expect(interface.members[0], const TypeMatcher<Field>()); final Field field = interface.members[0]; expect(field.name, equals('options')); - expect(field.comment, equals('''Options used by something.''')); + expect(field.commentText, equals('''Options used by something.''')); expect(field.allowsNull, isFalse); expect(field.allowsUndefined, isTrue); - expect(field.types, hasLength(1)); - expect(field.types[0], equals('OptionKind[]')); + expect(field.type, isArrayOf(isSimpleType('OptionKind'))); + }); + + test('parses an interface with a field with an inline/unnamed type', () { + final String input = ''' +export interface Capabilities { + textDoc?: { + deprecated?: bool; + }; +} + '''; + final List<AstNode> output = parseFile(input); + // Length is two because we'll fabricate the type of textDoc. + expect(output, hasLength(2)); + + // Check there was a full fabricarted interface for this type. + expect(output[0], const TypeMatcher<Interface>()); + Interface interface = output[0]; + expect(interface.name, equals('CapabilitiesTextDoc')); + expect(interface.members, hasLength(1)); + expect(interface.members[0], const TypeMatcher<Field>()); + Field field = interface.members[0]; + expect(field.name, equals('deprecated')); + expect(field.allowsNull, isFalse); + expect(field.allowsUndefined, isTrue); + expect(field.type, isSimpleType('bool')); + expect(field.allowsUndefined, isTrue); + + expect(output[1], const TypeMatcher<Interface>()); + interface = output[1]; + expect(interface.name, equals('Capabilities')); + expect(interface.members, hasLength(1)); + expect(interface.members[0], const TypeMatcher<Field>()); + field = interface.members[0]; + expect(field.name, equals('textDoc')); + expect(field.allowsNull, isFalse); + expect(field.type, isSimpleType('CapabilitiesTextDoc')); }); test('parses an interface with multiple fields', () { @@ -51,7 +87,7 @@ options1: any; } '''; - final List<ApiItem> output = extractTypes(input); + final List<AstNode> output = parseFile(input); expect(output, hasLength(1)); expect(output[0], const TypeMatcher<Interface>()); final Interface interface = output[0]; @@ -60,7 +96,7 @@ expect(interface.members[i], const TypeMatcher<Field>()); final Field field = interface.members[i]; expect(field.name, equals('options$i')); - expect(field.comment, equals('''Options$i used by something.''')); + expect(field.commentText, equals('''Options$i used by something.''')); }); }); @@ -70,7 +106,7 @@ data?: D; } '''; - final List<ApiItem> output = extractTypes(input); + final List<AstNode> output = parseFile(input); expect(output, hasLength(1)); expect(output[0], const TypeMatcher<Interface>()); final Interface interface = output[0]; @@ -78,21 +114,21 @@ final Field field = interface.members.first; expect(field, const TypeMatcher<Field>()); expect(field.name, equals('data')); - expect(field.allowsUndefined, true); - expect(field.allowsNull, false); - expect(field.types, equals(['D'])); + expect(field.allowsUndefined, isTrue); + expect(field.allowsNull, isFalse); + expect(field.type, isSimpleType('D')); }); test('parses an interface with Arrays in Array<T> format', () { final String input = ''' -export interface RequestMessage { +export interface MyMessage { /** * The method's params. */ params?: Array<any> | object; } '''; - final List<ApiItem> output = extractTypes(input); + final List<AstNode> output = parseFile(input); expect(output, hasLength(1)); expect(output[0], const TypeMatcher<Interface>()); final Interface interface = output[0]; @@ -100,10 +136,32 @@ final Field field = interface.members.first; expect(field, const TypeMatcher<Field>()); expect(field.name, equals('params')); - expect(field.comment, equals('''The method's params.''')); - expect(field.allowsUndefined, true); - expect(field.allowsNull, false); - expect(field.types, equals(['Array<any>', 'object'])); + expect(field.commentText, equals('''The method's params.''')); + expect(field.allowsUndefined, isTrue); + expect(field.allowsNull, isFalse); + expect(field.type, const TypeMatcher<UnionType>()); + UnionType union = field.type; + expect(union.types, hasLength(2)); + expect(union.types[0], isArrayOf(isSimpleType('any'))); + expect(union.types[1], isSimpleType('object')); + }); + + test('parses an interface with a map into a MapType', () { + final String input = ''' +export interface WorkspaceEdit { + changes: { [uri: string]: TextEdit[]; }; +} + '''; + final List<AstNode> output = parseFile(input); + expect(output, hasLength(1)); + expect(output[0], const TypeMatcher<Interface>()); + final Interface interface = output[0]; + expect(interface.members, hasLength(1)); + final Field field = interface.members.first; + expect(field, const TypeMatcher<Field>()); + expect(field.name, equals('changes')); + expect(field.type, + isMapOf(isSimpleType('string'), isArrayOf(isSimpleType('TextEdit')))); }); test('flags nullable undefined values', () { @@ -115,7 +173,7 @@ canBeUndefined?: string; } '''; - final List<ApiItem> output = extractTypes(input); + final List<AstNode> output = parseFile(input); final Interface interface = output[0]; expect(interface.members, hasLength(4)); interface.members.forEach((m) => expect(m, const TypeMatcher<Field>())); @@ -155,9 +213,9 @@ a: a; } '''; - final List<ApiItem> output = extractTypes(input); + final List<AstNode> output = parseFile(input); final Interface interface = output[0]; - expect(interface.comment, equals(''' + expect(interface.commentText, equals(''' Describes the what this class in lots of words that wrap onto multiple lines that will need re-wrapping to format nicely when converted into Dart. Blank lines should remain in-tact, as should: @@ -176,12 +234,12 @@ final String input = ''' export type DocumentSelector = DocumentFilter[]; '''; - final List<ApiItem> output = extractTypes(input); + final List<AstNode> output = parseFile(input); expect(output, hasLength(1)); expect(output[0], const TypeMatcher<TypeAlias>()); final TypeAlias typeAlias = output[0]; expect(typeAlias.name, equals('DocumentSelector')); - expect(typeAlias.baseType, equals('DocumentFilter[]')); + expect(typeAlias.baseType, isArrayOf(isSimpleType('DocumentFilter'))); }); test('parses a namespace of constants', () { @@ -203,7 +261,7 @@ export const Rename: ResourceOperationKind = 'rename'; } '''; - final List<ApiItem> output = extractTypes(input); + final List<AstNode> output = parseFile(input); expect(output, hasLength(1)); expect(output[0], const TypeMatcher<Namespace>()); final Namespace namespace = output[0]; @@ -213,16 +271,16 @@ delete = namespace.members[1], rename = namespace.members[2]; expect(create.name, equals('Create')); - expect(create.type, equals('ResourceOperationKind')); - expect( - create.comment, equals('Supports creating new files and folders.')); + expect(create.type, isSimpleType('ResourceOperationKind')); + expect(create.commentText, + equals('Supports creating new files and folders.')); expect(rename.name, equals('Rename')); - expect(rename.type, equals('ResourceOperationKind')); - expect(rename.comment, + expect(rename.type, isSimpleType('ResourceOperationKind')); + expect(rename.commentText, equals('Supports renaming existing files and folders.')); expect(delete.name, equals('Delete')); - expect(delete.type, equals('ResourceOperationKind')); - expect(delete.comment, + expect(delete.type, isSimpleType('ResourceOperationKind')); + expect(delete.commentText, equals('Supports deleting existing files and folders.')); }); });
diff --git a/pkg/analysis_server/tool/instrumentation/log/log.dart b/pkg/analysis_server/tool/instrumentation/log/log.dart index 011581a..10dfd90 100644 --- a/pkg/analysis_server/tool/instrumentation/log/log.dart +++ b/pkg/analysis_server/tool/instrumentation/log/log.dart
@@ -870,7 +870,7 @@ /** * A log entry representing a communication between the server and a plugin. */ -abstract class PluginEntryMixin { +mixin PluginEntryMixin { /** * The components describing the plugin associated with this entry. */
diff --git a/pkg/analysis_server/tool/lsp_spec/codegen_dart.dart b/pkg/analysis_server/tool/lsp_spec/codegen_dart.dart index 79b2b63..c95ca9c 100644 --- a/pkg/analysis_server/tool/lsp_spec/codegen_dart.dart +++ b/pkg/analysis_server/tool/lsp_spec/codegen_dart.dart
@@ -3,16 +3,30 @@ // BSD-style license that can be found in the LICENSE file. import 'package:dart_style/dart_style.dart'; -import 'package:meta/meta.dart'; import 'typescript.dart'; +import 'typescript_parser.dart'; final formatter = new DartFormatter(); Map<String, Interface> _interfaces = {}; +// TODO(dantup): Rename namespaces -> enums since they're always that now. Map<String, Namespace> _namespaces = {}; Map<String, TypeAlias> _typeAliases = {}; -String generateDartForTypes(List<ApiItem> types) { +/// Whether our enum class allows any value (eg. should always return true +/// from canParse() for the correct type). This is to allow us to have some +/// type safety for these values but without restricting which values are allowed. +/// This is to support things like custom error codes and also future changes +/// in the spec (it's important the server doesn't crash on deserialising +/// newer values). +bool enumClassAllowsAnyValue(String name) { + // TODO(dantup): This should return true by default, and allow opt-out for + // those things we know are not supported. This behaviour matches the old + // code in order to simplify diffs while migrating. + return name == 'ErrorCodes' || name == 'CodeActionKind'; +} + +String generateDartForTypes(List<AstNode> types) { // Keep maps of items we may need to look up quickly later. types .whereType<TypeAlias>() @@ -29,8 +43,15 @@ return formattedCode.trim() + '\n'; // Ensure a single trailing newline. } -List<String> _extractTypesFromUnion(String type) { - return type.split('|').map((t) => t.trim()).toList(); +TypeBase resolveTypeAlias(TypeBase type, {resolveEnumClasses: false}) { + if (type is Type && _typeAliases.containsKey(type.name)) { + final alias = _typeAliases[type.name]; + // Only follow the type if we're not an enum, or we wanted to follow enums. + if (!_namespaces.containsKey(alias.name) || resolveEnumClasses) { + return alias.baseType; + } + } + return type; } String _formatCode(String code) { @@ -52,45 +73,28 @@ return interface.members .whereType<Field>() .followedBy(interface.baseTypes - .map((name) => _getAllFields(_interfaces[name])) + // This cast is safe because base types are always real types. + .map((type) => _getAllFields(_interfaces[(type as Type).name])) .expand((ts) => ts)) .toList(); } -String _getListType(String type) { - return type.substring('List<'.length, type.length - 1); -} - /// Returns a copy of the list sorted by name. -List<ApiItem> _getSorted(List<ApiItem> items) { +List<AstNode> _getSorted(List<AstNode> items) { final sortedList = items.toList(); sortedList.sort((item1, item2) => item1.name.compareTo(item2.name)); return sortedList; } -List<String> _getUnionTypes(String type) { - return type - .substring('EitherX<'.length, type.length - 1) - .split(',') - .map((s) => s.trim()) - .toList(); -} - -bool _isList(String type) { - return type.startsWith('List<') && type.endsWith('>'); -} - -bool _isLiteral(String type) { +bool _isSimpleType(TypeBase type) { const literals = ['num', 'String', 'bool']; - return literals.contains(type); + return type is Type && literals.contains(type.dartType); } -bool _isSpecType(String type) { - return _interfaces.containsKey(type) || _namespaces.containsKey(type); -} - -bool _isUnion(String type) { - return type.startsWith('Either') && type.endsWith('>'); +bool _isSpecType(TypeBase type) { + return type is Type && + (_interfaces.containsKey(type.name) || + (_namespaces.containsKey(type.name))); } /// Maps reserved words and identifiers that cause issues in field names. @@ -104,57 +108,6 @@ return map[identifier] ?? identifier; } -/// Maps a TypeScript type on to a Dart type, including following TypeAliases. -@visibleForTesting -String mapType(List<String> types) { - const mapping = <String, String>{ - 'boolean': 'bool', - 'string': 'String', - 'number': 'num', - 'any': 'dynamic', - 'object': 'dynamic', - // Special cases that are hard to parse or anonymous types. - '{ [uri: string]: TextEdit[]; }': 'Map<String, List<TextEdit>>', - '{ language: string; value: string }': 'MarkedStringWithLanguage' - }; - if (types.length > 4) { - throw 'Unions of more than 4 types are not supported.'; - } - if (types.length >= 2) { - final typeArgs = types.map((t) => mapType([t])).join(', '); - return 'Either${types.length}<$typeArgs>'; - } - - final type = types.first; - if (type.endsWith('[]')) { - return 'List<${mapType([type.substring(0, type.length - 2)])}>'; - } else if (type.startsWith('Array<') && type.endsWith('>')) { - return 'List<${mapType([type.substring(6, type.length - 1)])}>'; - } else if (type.contains('<')) { - // For types with type args, we need to map the type and each type arg. - final declaredType = _stripTypeArgs(type); - final typeArgs = type - .substring(declaredType.length + 1, type.length - 1) - .split(',') - .map((t) => t.trim()); - return '${mapType([ - declaredType - ])}<${typeArgs.map((t) => mapType([t])).join(', ')}>'; - } else if (type.contains('|')) { - // It's possible we ended up with nested unions that the parsing. - // TODO(dantup): This is now partly done during parsing and partly done - // here. Maybe consider removing from typescript.dart and just carrying a - // String through so the logic is all in one place in this function? - return mapType(_extractTypesFromUnion(type)); - } else if (_typeAliases.containsKey(type)) { - return mapType([_typeAliases[type].baseType]); - } else if (mapping.containsKey(type)) { - return mapType([mapping[type]]); - } else { - return type; - } -} - String _rewriteCommentReference(String comment) { final commentReferencePattern = new RegExp(r'\[([\w ]+)\]\(#(\w+)\)'); return comment.replaceAllMapped(commentReferencePattern, (m) { @@ -168,10 +121,6 @@ }); } -String _stripTypeArgs(String typeName) => typeName.contains('<') - ? typeName.substring(0, typeName.indexOf('<')) - : typeName; - Iterable<String> _wrapLines(List<String> lines, int maxLength) sync* { lines = lines.map((l) => l.trimRight()).toList(); for (var line in lines) { @@ -205,8 +154,7 @@ _getAllFields(interface).where((f) => !f.allowsUndefined); for (var field in requiredFields) { buffer.write(" && obj.containsKey('${field.name}') && "); - _writeTypeCheckCondition( - buffer, "obj['${field.name}']", mapType(field.types)); + _writeTypeCheckCondition(buffer, "obj['${field.name}']", field.type); } buffer ..writeln(';') @@ -216,7 +164,7 @@ void _writeConst(IndentableStringBuffer buffer, Const cons) { _writeDocCommentsAndAnnotations(buffer, cons); - buffer.writeIndentedln('static const ${cons.name} = ${cons.value};'); + buffer.writeIndentedln('static const ${cons.name} = ${cons.valueAsLiteral};'); } void _writeConstructor(IndentableStringBuffer buffer, Interface interface) { @@ -225,7 +173,7 @@ return; } buffer - ..writeIndented('${_stripTypeArgs(interface.name)}(') + ..writeIndented('${interface.name}(') ..write(allFields.map((field) => 'this.${field.name}').join(', ')) ..write(')'); final fieldsWithValidation = @@ -252,51 +200,65 @@ } void _writeDocCommentsAndAnnotations( - IndentableStringBuffer buffer, ApiItem item) { - var comment = item.comment?.trim(); - if (comment == null || comment.length == 0) { - return; + IndentableStringBuffer buffer, AstNode node) { + var comment = node.commentText?.trim(); + if (comment != null && comment.isNotEmpty) { + comment = _rewriteCommentReference(comment); + Iterable<String> lines = comment.split('\n'); + // Wrap at 80 - 4 ('/// ') - indent characters. + lines = _wrapLines(lines, (80 - 4 - buffer.totalIndent).clamp(0, 80)); + lines.forEach((l) => buffer.writeIndentedln('/// $l'.trim())); } - comment = _rewriteCommentReference(comment); - Iterable<String> lines = comment.split('\n'); - // Wrap at 80 - 4 ('/// ') - indent characters. - lines = _wrapLines(lines, (80 - 4 - buffer.totalIndent).clamp(0, 80)); - lines.forEach((l) => buffer.writeIndentedln('/// $l'.trim())); - if (item.isDeprecated) { + if (node.isDeprecated) { buffer.writeIndentedln('@core.deprecated'); } } void _writeEnumClass(IndentableStringBuffer buffer, Namespace namespace) { _writeDocCommentsAndAnnotations(buffer, namespace); + final consts = namespace.members.cast<Const>().toList(); + final allowsAnyValue = enumClassAllowsAnyValue(namespace.name); + final constructorName = allowsAnyValue ? '' : '._'; + final typeOfValues = + resolveTypeAlias(consts.first.type, resolveEnumClasses: true); + buffer ..writeln('class ${namespace.name} {') ..indent() - ..writeIndentedln('const ${namespace.name}._(this._value);') + ..writeIndentedln('const ${namespace.name}$constructorName(this._value);') ..writeIndentedln('const ${namespace.name}.fromJson(this._value);') ..writeln() - ..writeIndentedln('final Object _value;') + ..writeIndentedln('final ${typeOfValues.dartTypeWithTypeArgs} _value;') ..writeln() ..writeIndentedln('static bool canParse(Object obj) {') - ..indent() - ..writeIndentedln('switch (obj) {') ..indent(); - namespace.members.whereType<Const>().forEach((cons) { - buffer..writeIndentedln('case ${cons.value}:'); - }); + if (allowsAnyValue) { + buffer.writeIndentedln('return '); + _writeTypeCheckCondition(buffer, 'obj', consts.first.type); + buffer.writeln(';'); + } else { + buffer + ..writeIndentedln('switch (obj) {') + ..indent(); + consts.forEach((cons) { + buffer..writeIndentedln('case ${cons.valueAsLiteral}:'); + }); + buffer + ..indent() + ..writeIndentedln('return true;') + ..outdent() + ..outdent() + ..writeIndentedln('}') + ..writeIndentedln('return false;'); + } buffer - ..indent() - ..writeIndentedln('return true;') - ..outdent() - ..writeIndentedln('}') - ..writeIndentedln('return false;') ..outdent() ..writeIndentedln('}'); namespace.members.whereType<Const>().forEach((cons) { _writeDocCommentsAndAnnotations(buffer, cons); buffer ..writeIndentedln( - 'static const ${_makeValidIdentifier(cons.name)} = const ${namespace.name}._(${cons.value});'); + 'static const ${_makeValidIdentifier(cons.name)} = const ${namespace.name}$constructorName(${cons.valueAsLiteral});'); }); buffer ..writeln() @@ -313,58 +275,107 @@ ..writeln(); } +void _writeEquals(IndentableStringBuffer buffer, Interface interface) { + buffer + ..writeIndentedln('@override') + ..writeIndentedln('bool operator ==(other) {') + ..indent() + ..writeIndentedln('if (other is ${interface.name}) {') + ..indent() + ..writeIndented('return '); + for (var field in _getAllFields(interface)) { + final type = field.type; + if (type is ArrayType) { + final elementType = type.elementType; + final elementDartType = elementType.dartTypeWithTypeArgs; + buffer.write( + 'listEqual(${field.name}, other.${field.name}, ($elementDartType a, $elementDartType b) => a == b) && '); + } else if (type is MapType) { + final valueType = type.valueType; + final valueDartType = valueType.dartTypeWithTypeArgs; + buffer.write( + 'mapEqual(${field.name}, other.${field.name}, ($valueDartType a, $valueDartType b) => a == b) && '); + } else { + buffer.write('${field.name} == other.${field.name} && '); + } + } + buffer + ..writeln('true;') + ..outdent() + ..writeIndentedln('}') + ..writeIndentedln('return false;') + ..outdent() + ..writeIndentedln('}'); +} + void _writeField(IndentableStringBuffer buffer, Field field) { _writeDocCommentsAndAnnotations(buffer, field); buffer ..writeIndented('final ') - ..write(mapType(field.types)) + ..write(field.type.dartTypeWithTypeArgs) ..writeln(' ${field.name};'); } void _writeFromJsonCode( - IndentableStringBuffer buffer, List<String> types, String valueCode) { - final type = mapType(types); - if (_isLiteral(type)) { + IndentableStringBuffer buffer, TypeBase type, String valueCode, + {bool allowsNull}) { + type = resolveTypeAlias(type); + + if (_isSimpleType(type)) { buffer.write("$valueCode"); } else if (_isSpecType(type)) { // Our own types have fromJson() constructors we can call. - buffer.write("$valueCode != null ? new $type.fromJson($valueCode) : null"); - } else if (_isList(type)) { - // Lists need to be mapped so we can recursively call (they may need fromJson). + buffer.write( + "$valueCode != null ? ${type.dartType}.fromJson${type.typeArgsString}($valueCode) : null"); + } else if (type is ArrayType) { + // Lists need to be map()'d so we can recursively call writeFromJsonCode + // as they may need fromJson on each element. buffer.write("$valueCode?.map((item) => "); - final listType = _getListType(type); - _writeFromJsonCode(buffer, [listType], 'item'); - buffer.write(')?.cast<$listType>()?.toList()'); - } else if (_isUnion(type)) { - _writeFromJsonCodeForUnion(buffer, types, valueCode); + _writeFromJsonCode(buffer, type.elementType, 'item', + allowsNull: allowsNull); + buffer + .write(')?.cast<${type.elementType.dartTypeWithTypeArgs}>()?.toList()'); + } else if (type is MapType) { + // Maps need to be map()'d so we can recursively call writeFromJsonCode as + // they may need fromJson on each key or value. + buffer.write('$valueCode?.map((key, value) => new MapEntry('); + _writeFromJsonCode(buffer, type.indexType, 'key', allowsNull: allowsNull); + buffer.write(', '); + _writeFromJsonCode(buffer, type.valueType, 'value', allowsNull: allowsNull); + buffer.write( + '))?.cast<${type.indexType.dartTypeWithTypeArgs}, ${type.valueType.dartTypeWithTypeArgs}>()'); + } else if (type is UnionType) { + _writeFromJsonCodeForUnion(buffer, type, valueCode, allowsNull: allowsNull); } else { buffer.write("$valueCode"); } } void _writeFromJsonCodeForUnion( - IndentableStringBuffer buffer, List<String> types, String valueCode) { - final unionTypeName = mapType(types); + IndentableStringBuffer buffer, UnionType union, String valueCode, + {bool allowsNull}) { // Write a check against each type, eg.: // x is y ? new Either.tx(x) : (...) var hasIncompleteCondition = false; var unclosedParens = 0; - for (var i = 0; i < types.length; i++) { - final dartType = mapType([types[i]]); + for (var i = 0; i < union.types.length; i++) { + final type = union.types[i]; + final isDynamic = type.dartType == 'dynamic'; // Dynamic matches all type checks, so only emit it if required. - if (dartType != 'dynamic') { - _writeTypeCheckCondition(buffer, valueCode, dartType); + if (!isDynamic) { + _writeTypeCheckCondition(buffer, valueCode, type); buffer.write(' ? '); } // The code to construct a value with this "side" of the union. - buffer.write('new $unionTypeName.t${i + 1}('); - _writeFromJsonCode(buffer, [dartType], valueCode); // Call recursively! + buffer.write('new ${union.dartTypeWithTypeArgs}.t${i + 1}('); + _writeFromJsonCode(buffer, type, valueCode, + allowsNull: allowsNull); // Call recursively! buffer.write(')'); // If we output the type condition at the top, prepare for the next condition. - if (dartType != 'dynamic') { + if (!isDynamic) { buffer.write(' : ('); hasIncompleteCondition = true; unclosedParens++; @@ -375,8 +386,12 @@ // Fill the final parens with a throw because if we fell through all of the // cases then the value we had didn't match any of the types in the union. if (hasIncompleteCondition) { + if (allowsNull) { + buffer.write('$valueCode == null ? null : ('); + unclosedParens++; + } buffer.write( - "throw '''\${$valueCode} was not one of (${types.join(', ')})'''"); + "throw '''\${$valueCode} was not one of (${union.types.map((t) => t.dartTypeWithTypeArgs).join(', ')})'''"); } buffer.write(')' * unclosedParens); } @@ -384,31 +399,48 @@ void _writeFromJsonConstructor( IndentableStringBuffer buffer, Interface interface) { final allFields = _getAllFields(interface); - if (allFields.isEmpty) { - return; - } buffer - ..writeIndentedln( - 'factory ${_stripTypeArgs(interface.name)}.fromJson(Map<String, dynamic> json) {') + ..writeIndentedln('static ${interface.nameWithTypeArgs} ' + 'fromJson${interface.typeArgsString}(Map<String, dynamic> json) {') ..indent(); for (final field in allFields) { buffer.writeIndented('final ${field.name} = '); - _writeFromJsonCode(buffer, field.types, "json['${field.name}']"); + _writeFromJsonCode(buffer, field.type, "json['${field.name}']", + allowsNull: field.allowsNull || field.allowsUndefined); buffer.writeln(';'); } buffer - ..writeIndented('return new ${interface.name}(') + ..writeIndented('return new ${interface.nameWithTypeArgs}(') ..write(allFields.map((field) => '${field.name}').join(', ')) ..writeln(');') ..outdent() ..writeIndented('}'); } +void _writeHashCode(IndentableStringBuffer buffer, Interface interface) { + buffer + ..writeIndentedln('@override') + ..writeIndentedln('int get hashCode {') + ..indent() + ..writeIndented('int hash = 0;'); + for (var field in _getAllFields(interface)) { + buffer + .write('hash = JenkinsSmiHash.combine(hash, ${field.name}.hashCode);'); + } + buffer + ..writeln('return JenkinsSmiHash.finish(hash);') + ..outdent() + ..writeIndentedln('}'); +} + void _writeInterface(IndentableStringBuffer buffer, Interface interface) { _writeDocCommentsAndAnnotations(buffer, interface); - buffer.writeIndented('class ${interface.name} '); - var allBaseTypes = interface.baseTypes.followedBy(['ToJsonable']); + buffer.writeIndented('class ${interface.nameWithTypeArgs} '); + final allBaseTypes = + interface.baseTypes.map((t) => t.dartTypeWithTypeArgs).toList(); + allBaseTypes.addAll(getSpecialBaseTypes(interface)); + allBaseTypes.add('ToJsonable'); if (allBaseTypes.isNotEmpty) { buffer.writeIndented('implements ${allBaseTypes.join(', ')} '); } @@ -428,6 +460,9 @@ buffer.writeln(); _writeToJsonMethod(buffer, interface); _writeCanParseMethod(buffer, interface); + _writeEquals(buffer, interface); + _writeHashCode(buffer, interface); + _writeToString(buffer, interface); buffer ..outdent() ..writeIndentedln('}') @@ -440,14 +475,10 @@ // undefined and never explicitly null), we'll only add the value if set. if (field.allowsUndefined) { buffer - ..writeIndentedlnIf( - field.isDeprecated, '// ignore: deprecated_member_use') ..writeIndentedln('if (${field.name} != null) {') ..indent(); } - buffer - ..writeIndentedlnIf(field.isDeprecated, '// ignore: deprecated_member_use') - ..writeIndented('''$mapName['${field.name}'] = ${field.name}'''); + buffer..writeIndented('''$mapName['${field.name}'] = ${field.name}'''); if (!field.allowsUndefined && !field.allowsNull) { buffer.write(''' ?? (throw '${field.name} is required but was not set')'''); } @@ -473,29 +504,6 @@ _getSorted(members).forEach((m) => _writeMember(buffer, m)); } -void _writeNamespace(IndentableStringBuffer buffer, Namespace namespace) { - // Namespaces are just groups of constants. For some uses we can write these - // as enum classes for extra type safety, but not for all - for example - // CodeActionKind can be an arbitrary String even though it also defines - // constants for common values. We can tell which can have their own values - // because they're marked with type aliases, with the exception of ErrorCodes! - if (!_typeAliases.containsKey(namespace.name) && - namespace.name != 'ErrorCodes') { - _writeEnumClass(buffer, namespace); - return; - } - - _writeDocCommentsAndAnnotations(buffer, namespace); - buffer - ..writeln('abstract class ${namespace.name} {') - ..indent(); - _writeMembers(buffer, namespace.members); - buffer - ..outdent() - ..writeln('}') - ..writeln(); -} - void _writeToJsonMethod(IndentableStringBuffer buffer, Interface interface) { // It's important the name we use for the map here isn't in use in the object // already. 'result' was, so we prefix it with some underscores. @@ -512,11 +520,17 @@ ..writeIndentedln('}'); } -void _writeType(IndentableStringBuffer buffer, ApiItem type) { +void _writeToString(IndentableStringBuffer buffer, Interface interface) { + buffer + ..writeIndentedln('@override') + ..writeIndentedln('String toString() => jsonEncoder.convert(toJson());'); +} + +void _writeType(IndentableStringBuffer buffer, AstNode type) { if (type is Interface) { _writeInterface(buffer, type); } else if (type is Namespace) { - _writeNamespace(buffer, type); + _writeEnumClass(buffer, type); } else if (type is TypeAlias) { // For now type aliases are not supported, so are collected at the start // of the process in a map, and just replaced with the aliased type during @@ -528,38 +542,51 @@ } void _writeTypeCheckCondition( - IndentableStringBuffer buffer, String valueCode, String dartType) { - if (dartType == 'dynamic') { + IndentableStringBuffer buffer, String valueCode, TypeBase type) { + type = resolveTypeAlias(type, resolveEnumClasses: true); + + final resolvedDartType = type.dartTypeWithTypeArgs; + if (resolvedDartType == 'dynamic') { buffer.write('true'); - } else if (_isLiteral(dartType)) { - buffer.write('$valueCode is $dartType'); - } else if (_isSpecType(dartType)) { - buffer.write('$dartType.canParse($valueCode)'); - } else if (_isList(dartType)) { - final listType = _getListType(dartType); + } else if (_isSimpleType(type)) { + buffer.write('$valueCode is $resolvedDartType'); + } else if (_isSpecType(type)) { + buffer.write('$resolvedDartType.canParse($valueCode)'); + } else if (type is ArrayType) { buffer.write('($valueCode is List'); - if (dartType != 'dynamic') { + if (resolvedDartType != 'dynamic') { // TODO(dantup): If we're happy to assume we never have two lists in a union // we could skip this bit. buffer .write(' && ($valueCode.length == 0 || $valueCode.every((item) => '); - _writeTypeCheckCondition(buffer, 'item', listType); + _writeTypeCheckCondition(buffer, 'item', type.elementType); buffer.write('))'); } buffer.write(')'); - } else if (_isUnion(dartType)) { + } else if (type is MapType) { + buffer.write('($valueCode is Map'); + if (resolvedDartType != 'dynamic') { + buffer + ..write(' && ($valueCode.length == 0 || (') + ..write('$valueCode.keys.every((item) => '); + _writeTypeCheckCondition(buffer, 'item', type.indexType); + buffer..write('&& $valueCode.values.every((item) => '); + _writeTypeCheckCondition(buffer, 'item', type.valueType); + buffer.write(')))'); + } + buffer.write(')'); + } else if (type is UnionType) { // To type check a union, we just recursively check against each of its types. - final unionTypes = _getUnionTypes(dartType); buffer.write('('); - for (var i = 0; i < unionTypes.length; i++) { + for (var i = 0; i < type.types.length; i++) { if (i != 0) { buffer.write(' || '); } - _writeTypeCheckCondition(buffer, valueCode, mapType([unionTypes[i]])); + _writeTypeCheckCondition(buffer, valueCode, type.types[i]); } buffer.write(')'); } else { - throw 'Unable to type check $valueCode against $dartType'; + throw 'Unable to type check $valueCode against $resolvedDartType'; } } @@ -582,10 +609,4 @@ write(_indentString); writeln(obj); } - - void writeIndentedlnIf(bool condition, Object obj) { - if (condition) { - writeIndentedln(obj); - } - } }
diff --git a/pkg/analysis_server/tool/lsp_spec/generate_all.dart b/pkg/analysis_server/tool/lsp_spec/generate_all.dart index caa6aea..8e93a31 100644 --- a/pkg/analysis_server/tool/lsp_spec/generate_all.dart +++ b/pkg/analysis_server/tool/lsp_spec/generate_all.dart
@@ -11,6 +11,7 @@ import 'codegen_dart.dart'; import 'markdown.dart'; import 'typescript.dart'; +import 'typescript_parser.dart'; main() async { final String script = Platform.script.toFilePath(); @@ -20,14 +21,48 @@ new Directory(outFolder).createSync(); final String spec = await fetchSpec(); - final List<ApiItem> types = extractAllTypes(extractTypeScriptBlocks(spec)); - types.addAll(_getSpecialCaseTypes()); + final List<AstNode> types = extractTypeScriptBlocks(spec) + .where(shouldIncludeScriptBlock) + .map(parseFile) + .expand((f) => f) + .where(includeTypeDefinitionInOutput) + .toList(); + + // Generate an enum for all of the request methods to avoid strings. + types.add(extractMethodsEnum(spec)); + final String output = generateDartForTypes(types); new File(path.join(outFolder, 'protocol_generated.dart')) .writeAsStringSync(_generatedFileHeader + output); } +Namespace extractMethodsEnum(String spec) { + Const toConstant(String value) { + final comment = new Comment( + new Token(TokenType.COMMENT, '''Constant for the '$value' method.''')); + + // Generate a safe name for the member from the string. Those that start with + // $/ will have the prefix removed and all slashes should be replaced with + // underscores. + final safeMemberName = value.replaceAll(r'$/', '').replaceAll('/', '_'); + + return new Const( + comment, + new Token.identifier(safeMemberName), + new Type.identifier('string'), + new Token(TokenType.STRING, "'$value'"), + ); + } + + final comment = new Comment(new Token(TokenType.COMMENT, + 'Valid LSP methods known at the time of code generation from the spec.')); + final methodConstants = extractMethodNames(spec).map(toConstant).toList(); + + return new Namespace( + comment, new Token.identifier('Method'), methodConstants); +} + const _generatedFileHeader = ''' // Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a @@ -37,9 +72,17 @@ // To regenerate the file, use the script // "pkg/analysis_server/tool/lsp_spec/generate_all.dart". +// ignore_for_file: deprecated_member_use +// ignore_for_file: unnecessary_brace_in_string_interps + import 'dart:core' hide deprecated; import 'dart:core' as core show deprecated; +import 'dart:convert' show JsonEncoder; import 'package:analysis_server/lsp_protocol/protocol_special.dart'; +import 'package:analysis_server/src/protocol/protocol_internal.dart' show listEqual, mapEqual; +import 'package:analyzer/src/generated/utilities_general.dart'; + +const jsonEncoder = const JsonEncoder.withIndent(' '); '''; @@ -51,16 +94,18 @@ return resp.body; } -/// Fabricates types for things that don't parse well from the TS spec, -/// such as anonymous types: -/// type MarkedString = string | { language: string; value: string }; -List<ApiItem> _getSpecialCaseTypes() { - return [ - // For MarkedString, we drop the string-only version since we can always - // supply a language and it makes the type a little simpler. - new Interface('MarkedString', null, [], [ - new Field('language', null, ['string'], false, false), - new Field('value', null, ['string'], false, false) - ]) - ]; +/// Returns whether a script block should be parsed or not. +bool shouldIncludeScriptBlock(String input) { + // We can't parse literal arrays, but this script block is just an example + // and not actually referenced anywhere. + if (input.trim() == r"export const EOL: string[] = ['\n', '\r\n', '\r'];") { + return false; + } + + // There are some code blocks that just have example JSON in them. + if (input.startsWith('{') && input.endsWith('}')) { + return false; + } + + return true; }
diff --git a/pkg/analysis_server/tool/lsp_spec/markdown.dart b/pkg/analysis_server/tool/lsp_spec/markdown.dart index ae99df1..bf93adc 100644 --- a/pkg/analysis_server/tool/lsp_spec/markdown.dart +++ b/pkg/analysis_server/tool/lsp_spec/markdown.dart
@@ -4,6 +4,9 @@ final _typeScriptBlockPattern = new RegExp(r'\B```typescript([\S\s]*?)\n```', multiLine: true); +final _methodNamesPattern = new RegExp( + r'''_(?:Notification|Request):?_:?\r?\n\* method: '(.*?)'\r?\n''', + multiLine: true); /// Extracts fenced code blocks that are explicitly marked as TypeScript from a /// markdown document. @@ -13,3 +16,10 @@ .map((m) => m.group(1).trim()) .toList(); } + +List<String> extractMethodNames(String spec) { + return _methodNamesPattern + .allMatches(spec) + .map((m) => m.group(1).trim()) + .toList(); +}
diff --git a/pkg/analysis_server/tool/lsp_spec/typescript.dart b/pkg/analysis_server/tool/lsp_spec/typescript.dart index 017c666..dd6e854 100644 --- a/pkg/analysis_server/tool/lsp_spec/typescript.dart +++ b/pkg/analysis_server/tool/lsp_spec/typescript.dart
@@ -2,26 +2,20 @@ // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. -// TODO(dantup): Regex seemed like a good choice when parsing the first few... -// maybe it's not so great now. We should parse this properly if it turns out -// there are issues with what we have here. -const String _blockBody = r'\{([\s\S]*?)\s*\n\s*\}'; -const String _comment = r'(?:\/\*\*((?:[\S\s](?!\*\/))+?)\s\*\/)?\s*'; +import 'typescript_parser.dart'; -List<ApiItem> extractAllTypes(List<String> code) { - return extractTypes(code.join('\n')); -} - -List<ApiItem> extractTypes(String code) { - final types = ApiItem.extractFrom(code); - _removeUnwantedTypes(types); - return types; -} - -String _cleanComment(String comment) { +String cleanComment(String comment) { if (comment == null) { return null; } + + // Remove the start/end comment markers. + if (comment.startsWith('/**') && comment.endsWith('*/')) { + comment = comment.substring(3, comment.length - 2); + } else if (comment.startsWith('//')) { + comment = comment.substring(2); + } + final _commentLinePrefixes = new RegExp(r'\n\s*\* ?'); final _nonConcurrentNewlines = new RegExp(r'\n(?![\n\s\-*])'); final _newLinesThatRequireReinserting = new RegExp(r'\n (\w)'); @@ -41,10 +35,11 @@ /// Fixes up some enum types that are not as specific as they could be in the /// spec. For example, Diagnostic.severity is typed "number" but can be mapped /// to the DiagnosticSeverity enum class. -String _getImprovedType(String interfaceName, String fieldName) { +String getImprovedType(String interfaceName, String fieldName) { const Map<String, Map<String, String>> _improvedTypeMappings = { "Diagnostic": { "severity": "DiagnosticSeverity", + "code": "String", }, "TextDocumentSyncOptions": { "change": "TextDocumentSyncKind", @@ -61,6 +56,20 @@ "FoldingRange": { "kind": "FoldingRangeKind", }, + "ResponseError": { + "code": "ErrorCodes", + }, + "NotificationMessage": { + "method": "Method", + "params": "object", + }, + "RequestMessage": { + "method": "Method", + "params": "object", + }, + "SymbolInformation": { + "kind": "SymbolKind", + }, }; final interface = _improvedTypeMappings[interfaceName]; @@ -68,246 +77,38 @@ return interface != null ? interface[fieldName] : null; } -List<String> _getSpecialBaseClasses(String name) { - const fileOperationTypes = [ - 'TextDocumentEdit', - 'CreateFile', - 'RenameFile', - 'DeleteFile' - ]; - if (fileOperationTypes.contains(name)) { - return ['FileOperation']; +List<String> getSpecialBaseTypes(Interface interface) { + if (interface.name == 'RequestMessage' || + interface.name == 'NotificationMessage') { + return ['IncomingMessage']; } else { return []; } } -List<String> _parseTypes(String baseTypes, String sep) { - // Special case for a single complicated type we can't parse easily... - if (baseTypes == - '(TextDocumentEdit[] | (TextDocumentEdit | CreateFile | RenameFile | DeleteFile)[])') { - return ['FileOperation[]']; - } - return baseTypes?.split(sep)?.map((t) => t.trim())?.toList() ?? []; -} - -/// Removes types that are in the spec that we don't want. -void _removeUnwantedTypes(List<ApiItem> types) { +/// Removes types that are in the spec that we don't want to emit. +bool includeTypeDefinitionInOutput(AstNode node) { // These types are not used for v3.0 (Feb 2017) and by dropping them we don't // have to handle any cases where both a namespace and interfaces are declared // with the same name. - types.removeWhere((item) => item.name == 'InitializeError'); + return node.name != 'InitializeError' && + // We don't emit MarkedString because it gets mapped to a simple String + // when getting the .dartType for it. + // .startsWith() because there are inline types that will be generated. + !node.name.startsWith('MarkedString'); } -/// Base class for Interface, Field, Constant, etc. parsed from the LSP spec. -abstract class ApiItem { - String name, comment; - bool isDeprecated; - ApiItem(this.name, String comment) - : comment = _cleanComment(comment), - isDeprecated = comment?.contains('@deprecated') ?? false; - - static List<ApiItem> extractFrom(String code) { - List<ApiItem> types = []; - types.addAll(Interface.extractFrom(code)); - types.addAll(Namespace.extractFrom(code)); - types.addAll(TypeAlias.extractFrom(code)); - return types; +/// Removes types that are in the spec that we don't want in other signatures. +bool allowTypeInSignatures(TypeBase type) { + // Don't allow arrays of MarkedStrings, but do allow simple MarkedStrings. + // The only place that uses these are Hovers and we only send one value + // (to match the MarkupString equiv) so the array just makes the types + // unnecessarily complicated. + if (type is ArrayType) { + final elementType = type.elementType; + if (elementType is Type && elementType.name == 'MarkedString') { + return false; + } } -} - -/// A Constant parsed from the LSP spec. -class Const extends Member { - final String type, value; - Const(String name, String comment, this.type, this.value) - : super(name, comment); - - static List<Const> extractFrom(String code) { - final RegExp _constPattern = new RegExp(_comment + - r'''(?:export\s+)?const\s+(\w+)(?::\s+([\w\[\]'".-]+?))?\s*=\s*([\w\[\]'".-]+)\s*(?:;|$)'''); - - final consts = _constPattern.allMatches(code).map((m) { - final String comment = m.group(1); - final String name = m.group(2); - final String type = m.group(3); - final String value = m.group(4); - return new Const(name, comment, type, value); - }).toList(); - return consts; - } - - static List<Const> extractFromEnumValue(String code) { - final RegExp _constPattern = - new RegExp(_comment + r'''(\w+)\s*=\s*([\w\[\]'".-]+)\s*(?:,|$)'''); - - final consts = _constPattern.allMatches(code).map((m) { - final String comment = m.group(1); - final String name = m.group(2); - final String value = m.group(3); - return new Const(name, comment, null, value); - }).toList(); - return consts; - } -} - -/// A Field for an Interface parsed from the LSP spec. -class Field extends Member { - final List<String> types; - final bool allowsNull, allowsUndefined; - Field(String name, String comment, this.types, this.allowsNull, - this.allowsUndefined) - : super(name, comment); - - static List<Field> extractFrom(String interfaceName, String code) { - final RegExp _fieldPattern = new RegExp(_comment + - r'([\w\[\]]+\??)\s*:\s*([\w\[\] \|\{\}\(\)<>:;]+)\s*(?:;|$)'); - - final fields = _fieldPattern.allMatches(code).where((m) { - // Skip over the indexer in FormattingOptions since we don't need this - // (for now) and it's complicated to represent. - if (m.group(0).contains('[key: string]: boolean | number | string;')) { - return false; - } - return true; - }).map((m) { - String comment = m.group(1); - String name = m.group(2); - String typesString = m.group(3).trim(); - // Our regex may result in semicolons on the end... - // TODO(dantup): Fix this, or make a simple parser. - if (typesString.endsWith(';')) { - typesString = typesString.substring(0, typesString.length - 1); - } - // Some fields have weird comments like this in the spec: - // {@link MessageType} - // These seem to be the correct type of the field, while the field is - // marked with number. - if (comment != null) { - final RegExp _linkTypePattern = new RegExp(r'See \{@link (\w+)\}\.?'); - final linkTypeMatch = _linkTypePattern.firstMatch(comment); - if (linkTypeMatch != null) { - typesString = linkTypeMatch.group(1); - comment = comment.replaceAll(_linkTypePattern, ''); - } - } - List<String> types = _parseTypes(typesString, '|'); - final bool allowsNull = types.contains('null'); - if (allowsNull) { - types.remove('null'); - } - final bool allowsUndefined = name.endsWith('?'); - if (allowsUndefined) { - name = name.substring(0, name.length - 1); - } - // Perform simple type improvements for enums values that are typed as - // num/string in the spec but are enums. - // the spec. - if (types.length == 1) { - types[0] = _getImprovedType(interfaceName, name) ?? types[0]; - } - return new Field(name, comment, types, allowsNull, allowsUndefined); - }).toList(); - return fields; - } -} - -/// An Interface parsed from the LSP spec. -class Interface extends ApiItem { - final List<String> baseTypes; - final List<Member> members; - Interface(String name, String comment, this.baseTypes, this.members) - : super(name, comment); - - static List<Interface> extractFrom(String code) { - final RegExp _interfacePattern = new RegExp(_comment + - r'(?:export\s+)?(?:interface|class)\s+([\w<>]+)(?:\s+extends\s+([\w, ]+?))?\s*' + - _blockBody); - - final interfaces = _interfacePattern.allMatches(code).map((match) { - final String comment = match.group(1); - final String name = match.group(2); - final List<String> baseTypes = _parseTypes(match.group(3), ','); - final String body = match.group(4); - final List<Member> members = Member.extractFrom(name, body); - - // Add any special base classes we've added to simplify types. - baseTypes.addAll(_getSpecialBaseClasses(name)); - - return new Interface(name, comment, baseTypes, members); - }).toList(); - return interfaces; - } -} - -/// A Field or Constant parsed from the LSP type. -abstract class Member extends ApiItem { - Member(String name, String comment) : super(name, comment); - - static List<Member> extractFrom(String interfaceName, String code) { - List<Member> members = []; - members.addAll(Field.extractFrom(interfaceName, code)); - members.addAll(Const.extractFrom(code)); - return members; - } -} - -/// An Enum or Namsepace containing constants parsed from the LSP spec. -class Namespace extends ApiItem { - final List<Member> members; - Namespace(String name, String comment, this.members) : super(name, comment); - - static List<Namespace> extractFrom(String code) { - final enums = <Namespace>[]; - enums.addAll(_extractNamespacesFrom(code)); - enums.addAll(_extractEnumsFrom(code)); - return enums; - } - - static List<Namespace> _extractEnumsFrom(String code) { - final RegExp _namespacePattern = - new RegExp(_comment + r'(?:export\s+)?enum\s+(\w+)\s*' + _blockBody); - - final namespaces = _namespacePattern.allMatches(code).map((match) { - final String comment = match.group(1); - final String name = match.group(2); - final String body = match.group(3); - - final List<Member> members = Const.extractFromEnumValue(body); - return new Namespace(name, comment, members); - }).toList(); - return namespaces; - } - - static List<Namespace> _extractNamespacesFrom(String code) { - final RegExp _namespacePattern = new RegExp( - _comment + r'(?:export\s+)?namespace\s+(\w+)\s*' + _blockBody); - - final namespaces = _namespacePattern.allMatches(code).map((match) { - final String comment = match.group(1); - final String name = match.group(2); - final String body = match.group(3); - final List<Member> members = Member.extractFrom(name, body); - return new Namespace(name, comment, members); - }).toList(); - return namespaces; - } -} - -/// A type alias parsed from the LSP spec. -class TypeAlias extends ApiItem { - final String baseType; - TypeAlias(name, comment, this.baseType) : super(name, comment); - - static List<TypeAlias> extractFrom(String code) { - final RegExp _typeAliasPattern = - new RegExp(_comment + r'type\s+([\w]+)\s+=\s+([\w\[\]]+)\s*;'); - - final typeAliases = _typeAliasPattern.allMatches(code).map((match) { - final String comment = match.group(1); - final String name = match.group(2); - final String baseType = match.group(3); - return new TypeAlias(name, comment, baseType); - }).toList(); - return typeAliases; - } + return true; }
diff --git a/pkg/analysis_server/tool/lsp_spec/typescript_parser.dart b/pkg/analysis_server/tool/lsp_spec/typescript_parser.dart new file mode 100644 index 0000000..5a6a844 --- /dev/null +++ b/pkg/analysis_server/tool/lsp_spec/typescript_parser.dart
@@ -0,0 +1,910 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'dart:math'; + +import 'package:analysis_server/src/services/correction/strings.dart' + show capitalize; + +import 'codegen_dart.dart'; +import 'typescript.dart'; + +final _validIdentifierCharacters = RegExp('[a-zA-Z0-9_]'); + +bool isNullType(TypeBase t) => t is Type && t.name == 'null'; + +bool isUndefinedType(TypeBase t) => t is Type && t.name == 'undefined'; + +/// A fabricated field name for indexers in case they result in generation +/// of type names for inline types. +const fieldNameForIndexer = 'indexer'; + +List<AstNode> parseFile(String input) { + final scanner = new Scanner(input); + final tokens = scanner.scan(); + final parser = new Parser(tokens); + return parser.parse(); +} + +TypeBase typeOfLiteral(TokenType tokenType) { + final typeName = tokenType == TokenType.STRING + ? 'string' + : tokenType == TokenType.NUMBER + ? 'number' + : throw 'Unknown literal type $tokenType'; + return new Type.identifier(typeName); +} + +class ArrayType extends TypeBase { + final TypeBase elementType; + + ArrayType(this.elementType); + + @override + String get dartType => 'List'; + @override + String get typeArgsString => '<${elementType.dartTypeWithTypeArgs}>'; +} + +class MapType extends TypeBase { + final TypeBase indexType; + final TypeBase valueType; + + MapType(this.indexType, this.valueType); + + @override + String get dartType => 'Map'; + @override + String get typeArgsString => + '<${indexType.dartTypeWithTypeArgs}, ${valueType.dartTypeWithTypeArgs}>'; +} + +class AstNode { + final Comment commentNode; + final bool isDeprecated; + AstNode(this.commentNode) + : isDeprecated = commentNode?.text?.contains('@deprecated') ?? false; + String get commentText => commentNode?.text; + + String get name => null; +} + +class Comment extends AstNode { + final Token token; + final String text; + + Comment(this.token) + : text = cleanComment(token.lexeme), + super(null); +} + +class Const extends Member { + Token nameToken; + TypeBase type; + Token valueToken; + Const(Comment comment, this.nameToken, this.type, this.valueToken) + : super(comment); + String get name => nameToken.lexeme; + + String get valueAsLiteral { + if (type.dartType == 'String') { + // Write strings as raw strings, since some have dollars in them (eg. for + // LSP method names). valueToken.lexeme already includes the quotes as + // read from the spec. + return 'r${valueToken.lexeme}'; + } else { + return valueToken.lexeme; + } + } +} + +class Field extends Member { + final Token nameToken; + final TypeBase type; + final bool allowsNull; + final bool allowsUndefined; + Field( + Comment comment, + this.nameToken, + this.type, + this.allowsNull, + this.allowsUndefined, + ) : super(comment); + + String get name => nameToken.lexeme; +} + +class FixedValueField extends Field { + final Token valueToken; + FixedValueField( + Comment comment, + Token nameToken, + this.valueToken, + TypeBase type, + bool allowsNull, + bool allowsUndefined, + ) : super(comment, nameToken, type, allowsNull, allowsUndefined); +} + +class InlineInterface extends Interface { + InlineInterface( + String name, + List<Member> members, + ) : super(null, new Token.identifier(name), [], [], members); +} + +class Indexer extends Member { + final TypeBase indexType; + final TypeBase valueType; + Indexer( + Comment comment, + this.indexType, + this.valueType, + ) : super(comment); + + String get name => fieldNameForIndexer; +} + +class Interface extends AstNode { + final Token nameToken; + final List<Token> typeArgs; + final List<TypeBase> baseTypes; + final List<Member> members; + + Interface( + Comment comment, + this.nameToken, + this.typeArgs, + this.baseTypes, + this.members, + ) : super(comment); + String get name => nameToken.lexeme; + String get nameWithTypeArgs => '$name$typeArgsString'; + + String get typeArgsString => typeArgs.isNotEmpty + ? '<${typeArgs.map((t) => t.lexeme).join(', ')}>' + : ''; +} + +class Member extends AstNode { + Member(Comment comment) : super(comment); +} + +class Namespace extends AstNode { + final Token nameToken; + final List<Member> members; + Namespace( + Comment comment, + this.nameToken, + this.members, + ) : super(comment); + + String get name => nameToken.lexeme; +} + +class Parser { + final List<Token> _tokens; + int _current = 0; + List<AstNode> _nodes; + Parser(this._tokens); + + bool get _isAtEnd => _peek().type == TokenType.EOF; + + List<AstNode> parse() { + if (_nodes == null) { + _nodes = <AstNode>[]; + while (!_isAtEnd) { + _nodes.add(_topLevel()); + } + } + return _nodes; + } + + /// Returns the current token and moves to the next. + Token _advance() => _tokenAt(_current++); + + /// Checks if the next token is [type] without advancing. + bool _check(TokenType type) => !_isAtEnd && _peek().type == type; + + Comment _comment() { + if (_peek().type != TokenType.COMMENT) { + return null; + } + return Comment(_advance()); + } + + Const _const(String containerName, Comment leadingComment) { + _eatUnwantedKeywords(); + final name = _consume(TokenType.IDENTIFIER, 'Expected identifier'); + TypeBase type; + if (_match([TokenType.COLON])) { + type = _type(containerName, name.lexeme); + } + final value = _match([TokenType.EQUAL]) ? _advance() : null; + + if (type == null && value != null) { + type = typeOfLiteral(value.type); + } + + _consume(TokenType.SEMI_COLON, 'Expected ;'); + return Const(leadingComment, name, type, value); + } + + Indexer _indexer(String containerName, Comment leadingComment) { + final indexer = _field(containerName, leadingComment); + _consume(TokenType.RIGHT_BRACKET, 'Expected ]'); + _consume(TokenType.COLON, 'Expected :'); + + TypeBase type; + type = _type(containerName, fieldNameForIndexer, improveTypes: true); + + //_consume(TokenType.RIGHT_BRACE, 'Expected }'); + _match([TokenType.SEMI_COLON]); + + return new Indexer(leadingComment, indexer.type, type); + } + + /// Ensures the next token is [type] and moves to the next, throwing [message] + /// if not. + Token _consume(TokenType type, String message) { + if (_check(type)) { + return _advance(); + } + + throw '$message\n\n${_peek()}'; + } + + void _eatUnwantedKeywords() { + _match([TokenType.EXPORT_KEYWORD]); + _match([TokenType.READONLY_KEYWORD]); + } + + Namespace _enum(Comment leadingComment) { + final name = _consume(TokenType.IDENTIFIER, 'Expected identifier'); + _consume(TokenType.LEFT_BRACE, 'Expected {'); + final consts = <Const>[]; + while (!_check(TokenType.RIGHT_BRACE)) { + consts.add(_enumValue(name.lexeme)); + // Commas might not be present (eg. for last one). + _match([TokenType.COMMA]); + } + _consume(TokenType.RIGHT_BRACE, 'Expected }'); + + return new Namespace(leadingComment, name, consts); + } + + Const _enumValue(String enumName) { + final leadingComment = _comment(); + _eatUnwantedKeywords(); + final name = _consume(TokenType.IDENTIFIER, 'Expected identifier'); + TypeBase type; + if (_match([TokenType.COLON])) { + type = _type(enumName, name.lexeme); + } + final value = _match([TokenType.EQUAL]) ? _advance() : null; + + if (type == null && value != null) { + type = typeOfLiteral(value.type); + } + return Const(leadingComment, name, type, value); + } + + String _joinNames(String parent, String child) { + return '$parent${capitalize(child)}'; + } + + Field _field(String containerName, Comment leadingComment) { + _eatUnwantedKeywords(); + final name = _consume(TokenType.IDENTIFIER, 'Expected identifier'); + var canBeUndefined = _match([TokenType.QUESTION]); + var canBeNull = false; + _consume(TokenType.COLON, 'Expected :'); + TypeBase type; + Token value; + type = _type(containerName, name.lexeme, + includeUndefined: canBeUndefined, improveTypes: true); + + // Some fields have weird comments like this in the spec: + // {@link MessageType} + // These seem to be the correct type of the field, while the field is + // marked with number. + final commentText = leadingComment?.text; + if (commentText != null) { + final RegExp _linkTypePattern = new RegExp(r'See \{@link (\w+)\}\.?'); + final linkTypeMatch = _linkTypePattern.firstMatch(commentText); + if (linkTypeMatch != null) { + type = new Type.identifier(linkTypeMatch.group(1)); + leadingComment = new Comment(new Token(TokenType.COMMENT, + '// ' + commentText.replaceAll(_linkTypePattern, ''))); + } + } + + // Ideally this would be _consume(), but there are no semi-colons after the + // "inline types" since they're blocks. + _match([TokenType.SEMI_COLON]); + + // Special handling for fields that have fixed values. + if (value != null) { + return new FixedValueField( + leadingComment, name, value, type, canBeNull, canBeUndefined); + } + + if (type is UnionType) { + UnionType union = type; + // Since undefined and null can appear in the union type list but we want to + // handle it specially in the code generation, we promote them to fields on + // the Field. + canBeUndefined |= union.types.any(isUndefinedType); + canBeNull = union.types.any(isNullType); + // Finally, we need to remove them from the union. + final remainingTypes = union.types + .where((t) => !isNullType(t) && !isUndefinedType(t)) + .toList(); + + // We also remove any types that are deprecated and/or we won't use to + // simplify the unions. + remainingTypes.removeWhere((t) => !allowTypeInSignatures(t)); + + type = remainingTypes.length > 1 + ? new UnionType(remainingTypes) + : remainingTypes.single; + } + return Field(leadingComment, name, type, canBeNull, canBeUndefined); + } + + Interface _interface(Comment leadingComment) { + final name = _consume(TokenType.IDENTIFIER, 'Expected identifier'); + final typeArgs = <Token>[]; + if (_match([TokenType.LESS])) { + while (true) { + typeArgs.add(_consume(TokenType.IDENTIFIER, 'Expected identifier')); + if (_check(TokenType.GREATER)) { + break; + } + _consume(TokenType.COMMA, 'Expected , or >'); + } + _consume(TokenType.GREATER, 'Expected >'); + } + final baseTypes = <TypeBase>[]; + if (_match([TokenType.EXTENDS_KEYWORD])) { + while (true) { + baseTypes.add(_type(name.lexeme, null)); + if (_check(TokenType.LEFT_BRACE)) { + break; + } + _consume(TokenType.COMMA, 'Expected , or {'); + } + } + _consume(TokenType.LEFT_BRACE, 'Expected {'); + final members = <Member>[]; + while (!_check(TokenType.RIGHT_BRACE)) { + members.add(_member(name.lexeme)); + } + + // TODO(dantup): Temporary hack until we handle indexers. Remove nulls, which + // are (currently) returned by _field() for indexers. + members.removeWhere((m) => m == null); + + _consume(TokenType.RIGHT_BRACE, 'Expected }'); + + return new Interface(leadingComment, name, typeArgs, baseTypes, members); + } + + /// Returns [true] an advances if the next token is one of [types], otherwise + /// returns [false]. + bool _match(List<TokenType> types) { + for (final type in types) { + if (_check(type)) { + _advance(); + return true; + } + } + + return false; + } + + Member _member(String containerName) { + final leadingComment = _comment(); + _eatUnwantedKeywords(); + + if (_match([TokenType.CONST_KEYWORD])) { + return _const(containerName, leadingComment); + } else if (_match([TokenType.LEFT_BRACKET])) { + return _indexer(containerName, leadingComment); + } else { + return _field(containerName, leadingComment); + } + } + + Namespace _namespace(Comment leadingComment) { + final name = _consume(TokenType.IDENTIFIER, 'Expected identifier'); + _consume(TokenType.LEFT_BRACE, 'Expected {'); + final members = <Member>[]; + while (!_check(TokenType.RIGHT_BRACE)) { + members.add(_member(name.lexeme)); + } + _consume(TokenType.RIGHT_BRACE, 'Expected }'); + + return new Namespace(leadingComment, name, members); + } + + /// Returns the next token without advancing. + Token _peek() => _tokenAt(_current); + + Token _tokenAt(int index) => + index < _tokens.length ? _tokens[index] : Token.EOF; + + AstNode _topLevel() { + final leadingComment = _comment(); + _match([TokenType.EXPORT_KEYWORD]); + + final token = _peek(); + if (_match([TokenType.NAMESPACE_KEYWORD])) { + return _namespace(leadingComment); + } else if (_match([TokenType.INTERFACE_KEYWORD])) { + return _interface(leadingComment); + } else if (_match([TokenType.CLASS_KEYWORD])) { + // Classes are the same as interfaces in this spec. + return _interface(leadingComment); + } else if (_match([TokenType.ENUM_KEYWORD])) { + return _enum(leadingComment); + } else if (token.type == TokenType.IDENTIFIER && token.lexeme == 'type') { + // TODO(dantup): This is a hack... We don't have a TYPE_KEYWORD because + // the spec has `type` as an identifier. + _advance(); // Eat the 'type' keyword. + return _typeAlias(leadingComment); + } else { + throw 'Unexpected token ${_peek()}'; + } + } + + TypeBase _type( + String containerName, + String fieldName, { + bool includeUndefined = false, + bool improveTypes = false, + }) { + var types = <TypeBase>[]; + if (includeUndefined) { + types.add(Type.Undefined); + } + while (true) { + TypeBase type; + if (_match([TokenType.LEFT_BRACE])) { + // Inline interfaces. + final members = <Member>[]; + while (!_check(TokenType.RIGHT_BRACE)) { + members.add(_member(containerName)); + } + + // TODO(dantup): Temporary hack until we handle indexers. Remove nulls, which + // are (currently) returned by _field() for indexers. + members.removeWhere((m) => m == null); + + _consume(TokenType.RIGHT_BRACE, 'Expected }'); + // Some of the inline interfaces have trailing commas (and some do not!) + _match([TokenType.COMMA]); + + // If we have a single member that is an indexer type, we can use a Map. + if (members.length == 1 && members.single is Indexer) { + Indexer indexer = members.single; + type = new MapType(indexer.indexType, indexer.valueType); + } else { + // Add a synthetic interface to the parsers list of nodes to represent this type. + final generatedName = _joinNames(containerName, fieldName); + _nodes.add(new InlineInterface(generatedName, members)); + // Record the type as a simple type that references this interface. + type = new Type.identifier(generatedName); + } + } else if (_match([TokenType.LEFT_PAREN])) { + // Some types are in (parens), so we just parse the contents as a nested type. + type = _type(containerName, fieldName); + _consume(TokenType.RIGHT_PAREN, 'Expected )'); + } else if (_match([TokenType.STRING])) { + // In TS and the spec, literal strings can be types: + // export const PlainText: 'plaintext' = 'plaintext'; + // trace?: 'off' | 'messages' | 'verbose'; + // the best we can do is use their base type (string). + type = Type.identifier('string'); + } else if (_match([TokenType.NUMBER])) { + // In TS and the spec, literal numbers can be types: + // export const Invoked: 1 = 1; + // the best we can do is use their base type (number). + type = Type.identifier('number'); + } else { + var typeName = _consume(TokenType.IDENTIFIER, 'Expected identifier'); + final typeArgs = <Type>[]; + if (_match([TokenType.LESS])) { + while (true) { + typeArgs.add(_type(containerName, fieldName)); + if (_peek() != TokenType.COMMA) { + _consume(TokenType.GREATER, 'Expected >'); + break; + } + } + } + + type = typeName.lexeme == 'Array' + ? new ArrayType(typeArgs.single) + : new Type(typeName, typeArgs); + } + if (_match([TokenType.LEFT_BRACKET])) { + _consume(TokenType.RIGHT_BRACKET, 'Expected ]'); + type = new ArrayType(type); + } + // TODO(dantup): Handle types like This & That. + // For now, map to any. + if (_match([TokenType.AMPERSAND])) { + while (true) { + // Eat as many types/ampersands as we have. + _type(containerName, fieldName); + if (!_check(TokenType.AMPERSAND)) { + break; + } + } + type = Type.Any; + } + + types.add(type); + + if (!_match([TokenType.PIPE])) { + break; + } + } + + // Remove any duplicate types (for ex. if we map multiple types into dynamic) + // we don't want to end up with `dynamic | dynamic`. Key on dartType to + // ensure we different types that will map down to the same type. + final uniqueTypes = new Map.fromEntries( + types.map((t) => new MapEntry(t.dartTypeWithTypeArgs, t)), + ).values.toList(); + + var type = uniqueTypes.length == 1 + ? uniqueTypes.single + : new UnionType(uniqueTypes); + + // Handle improved type mappings for things that aren't very tight in the spec. + if (improveTypes) { + final improvedTypeName = getImprovedType(containerName, fieldName); + if (improvedTypeName != null) { + type = new Type.identifier(improvedTypeName); + } + } + return type; + } + + TypeAlias _typeAlias(Comment leadingComment) { + final name = _consume(TokenType.IDENTIFIER, 'Expected identifier'); + _consume(TokenType.EQUAL, 'Expected ='); + final type = _type(name.lexeme, null); + _consume(TokenType.SEMI_COLON, 'Expected ;'); + + return new TypeAlias(leadingComment, name, type); + } +} + +class Scanner { + final String _source; + int _startOfToken = 0; + int _currentPos = 0; + final _tokens = <Token>[]; + Scanner(this._source); + + bool get _isAtEnd => _currentPos >= _source.length; + bool get _isNextAtEnd => _currentPos + 1 >= _source.length; + + List<Token> scan() { + while (!_isAtEnd) { + _startOfToken = _currentPos; + _scanToken(); + } + return _tokens; + } + + void _addToken(TokenType type) { + final text = _source.substring(_startOfToken, _currentPos); + _tokens.add(Token(type, text)); + } + + String _advance() => _currentPos < _source.length + ? _source[_currentPos++] + : throw 'Cannot advance past end of source'; + + void _identifier() { + const keywords = <String, TokenType>{ + 'class': TokenType.CLASS_KEYWORD, + 'const': TokenType.CONST_KEYWORD, + 'enum': TokenType.ENUM_KEYWORD, + 'export': TokenType.EXPORT_KEYWORD, + 'extends': TokenType.EXTENDS_KEYWORD, + 'interface': TokenType.INTERFACE_KEYWORD, + 'namespace': TokenType.NAMESPACE_KEYWORD, + 'readonly': TokenType.READONLY_KEYWORD, + }; + while (_isAlpha(_peek())) { + _advance(); + } + + final string = _source.substring(_startOfToken, _currentPos); + if (keywords.containsKey(string)) { + _addToken(keywords[string]); + } else { + _addToken(TokenType.IDENTIFIER); + } + } + + bool _isAlpha(String s) => _validIdentifierCharacters.hasMatch(s); + + bool _isDigit(String s) => s != null && (s.codeUnitAt(0) ^ 0x30) <= 9; + + bool _match(String expected) { + if (_isAtEnd || _source[_currentPos] != expected) { + return false; + } + _currentPos++; + return true; + } + + void _number() { + // Optionally process a negative. + _match('-'); + while (_isDigit(_peek())) { + _advance(); + } + + // Handle fractional parts. + if (_peek() == '.' && _isDigit(_peekNext())) { + // Consume the decimal point. + _advance(); + + while (_isDigit(_peek())) { + _advance(); + } + } + + _addToken(TokenType.NUMBER); + } + + String _peek() => _isAtEnd ? null : _source[_currentPos]; + + String _peekNext() => _isNextAtEnd ? null : _source[_currentPos + 1]; + + void _scanToken() { + const singleCharTokens = <String, TokenType>{ + ',': TokenType.COMMA, + ';': TokenType.SEMI_COLON, + ':': TokenType.COLON, + '?': TokenType.QUESTION, + '.': TokenType.DOT, + '(': TokenType.LEFT_PAREN, + ')': TokenType.RIGHT_PAREN, + '[': TokenType.LEFT_BRACKET, + ']': TokenType.RIGHT_BRACKET, + '{': TokenType.LEFT_BRACE, + '}': TokenType.RIGHT_BRACE, + '*': TokenType.STAR, + '&': TokenType.AMPERSAND, + '=': TokenType.EQUAL, + '|': TokenType.PIPE, + }; + + final c = _advance(); + if (singleCharTokens.containsKey(c)) { + _addToken(singleCharTokens[c]); + return; + } + switch (c) { + case '/': + if (_match('*')) { + // Block comment. + while (!_isAtEnd && (_peek() != '*' || _peekNext() != '/')) { + _advance(); + } + // Eat the closing comment markers detected above. + if (!_isAtEnd) { + _advance(); + _advance(); + } + _addToken(TokenType.COMMENT); + } else if (_match('/')) { + // Single line comment. + while (_peek() != '\n' && !_isAtEnd) { + _advance(); + } + _addToken(TokenType.COMMENT); + } else { + _addToken(TokenType.SLASH); + } + break; + case '<': + _addToken(_match('=') ? TokenType.LESS_EQUAL : TokenType.LESS); + break; + case '>': + _addToken(_match('=') ? TokenType.GREATER_EQUAL : TokenType.GREATER); + break; + case ' ': + case '\r': + case '\n': + case '\t': + // Whitespace. + break; + case '"': + case "'": + _string(c); + break; + default: + if (_isDigit(c) || c == '-' && _isDigit(_peek())) { + _number(); + } else if (_isAlpha(c)) { + _identifier(); + } else { + final start = max(0, _currentPos - 20); + final end = min(_currentPos + 20, _source.length); + final snippet = _source.substring(start, end); + throw "Unexpected character '$c'.\n\n$snippet"; + } + break; + } + } + + void _string(String terminator) { + // TODO(dantup): Handle escape sequences, inc. quotes. + while (!_isAtEnd && _peek() != terminator) { + _advance(); + + if (_isAtEnd) { + throw 'Unterminated string.'; + } + } + + // Skip over the closing terminator. + _advance(); + + _addToken(TokenType.STRING); + } +} + +class Token { + static final Token EOF = new Token(TokenType.EOF, ''); + + final TokenType type; + final String lexeme; + + Token(this.type, this.lexeme); + + Token.identifier(String identifier) : this(TokenType.IDENTIFIER, identifier); + + @override + String toString() => '${type.toString().padRight(25)} ' + '${lexeme.padRight(10)}\n'; +} + +enum TokenType { + AMPERSAND, + CLASS_KEYWORD, + COLON, + COMMA, + COMMENT, + CONST_KEYWORD, + DOT, + ENUM_KEYWORD, + EOF, + EQUAL, + EXPORT_KEYWORD, + EXTENDS_KEYWORD, + GREATER_EQUAL, + GREATER, + IDENTIFIER, + INTERFACE_KEYWORD, + LEFT_BRACE, + LEFT_BRACKET, + LEFT_PAREN, + LESS_EQUAL, + LESS, + NAMESPACE_KEYWORD, + NUMBER, + PIPE, + QUESTION, + READONLY_KEYWORD, + RIGHT_BRACE, + RIGHT_BRACKET, + RIGHT_PAREN, + SEMI_COLON, + SLASH, + STAR, + STRING, +} + +class Type extends TypeBase { + static final TypeBase Undefined = new Type.identifier('undefined'); + static final TypeBase Any = new Type.identifier('any'); + final Token nameToken; + final List<TypeBase> typeArgs; + + Type(this.nameToken, this.typeArgs) { + if (this.name == 'Array' || this.name.endsWith('[]')) { + throw 'Type should not be used for arrays, use ArrayType instead'; + } + } + + Type.identifier(String identifier) + : this(new Token.identifier(identifier), []); + + @override + String get dartType { + // Always resolve type aliases when asked for our Dart type. + final resolvedType = resolveTypeAlias(this); + if (resolvedType != this) { + return resolvedType.dartType; + } + + const mapping = <String, String>{ + 'boolean': 'bool', + 'string': 'String', + 'number': 'num', + 'any': 'dynamic', + 'object': 'dynamic', + // Simplify MarkedString from + // string | { language: string; value: string } + // to just String + 'MarkedString': 'String' + }; + + final typeName = mapping[name] ?? name; + return typeName; + } + + String get name => nameToken.lexeme; + + @override + String get typeArgsString { + // Always resolve type aliases when asked for our Dart type. + final resolvedType = resolveTypeAlias(this); + if (resolvedType != this) { + return resolvedType.typeArgsString; + } + + return typeArgs.isNotEmpty + ? '<${typeArgs.map((t) => t.dartTypeWithTypeArgs).join(', ')}>' + : ''; + } +} + +class TypeAlias extends AstNode { + final Token nameToken; + final TypeBase baseType; + TypeAlias( + Comment comment, + this.nameToken, + this.baseType, + ) : super(comment); + + String get name => nameToken.lexeme; +} + +abstract class TypeBase { + String get dartType; + String get dartTypeWithTypeArgs => '$dartType$typeArgsString'; + String get typeArgsString; +} + +class UnionType extends TypeBase { + final List<TypeBase> types; + + UnionType(this.types); + + @override + String get dartType { + if (types.length > 4) { + throw 'Unions of more than 4 types are not supported.'; + } + return 'Either${types.length}'; + } + + @override + String get typeArgsString { + final typeArgs = types.map((t) => t.dartTypeWithTypeArgs).join(', '); + return '<$typeArgs>'; + } +}
diff --git a/pkg/analysis_server/tool/spec/to_html.dart b/pkg/analysis_server/tool/spec/to_html.dart index a6b897b..a2c1b37 100644 --- a/pkg/analysis_server/tool/spec/to_html.dart +++ b/pkg/analysis_server/tool/spec/to_html.dart
@@ -161,7 +161,7 @@ /** * Helper methods for creating HTML elements. */ -abstract class HtmlMixin { +mixin HtmlMixin { void anchor(String id, void callback()) { element('a', {'name': id}, callback); }
diff --git a/pkg/analyzer/CHANGELOG.md b/pkg/analyzer/CHANGELOG.md index 1d0af63..83181c8 100644 --- a/pkg/analyzer/CHANGELOG.md +++ b/pkg/analyzer/CHANGELOG.md
@@ -1,3 +1,17 @@ +## 0.34.0 +* Support for `declarations-casts` has been removed and the `implicit-casts` + option now has the combined semantics of both options. This means that users + that disable `implicit-casts` might now see errors that were not previously + being reported. +* Minor changes to the AnalysisSession and AnalysisDriver APIs to make it easier + for clients to transition away from using the task model. +* Minor changes to the linter API to make it easier for lint rules to define + their own lint codes. +* Add a version of getAncestor that matches by type without a closure. +* Add an AST structure for set literals. +* Bug fixes: #35162, #35230, #34733, #34741, #33553, #35090, #32815, #34387, + #34495, #35043, #33553, #34906, #34489. + ## 0.33.6+1-dev * Added a note to the `UriResolver` documentation alerting clients of an upcoming breaking change.
diff --git a/pkg/analyzer/benchmark/errors_in_all_libraries.dart b/pkg/analyzer/benchmark/errors_in_all_libraries.dart deleted file mode 100644 index e2540fb..0000000 --- a/pkg/analyzer/benchmark/errors_in_all_libraries.dart +++ /dev/null
@@ -1,99 +0,0 @@ -#!/usr/bin/env dart -// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file -// for details. All rights reserved. Use of this source code is governed by a -// BSD-style license that can be found in the LICENSE file. - -/// Resolves this library and everything it transitively imports and generates -/// errors in all of those libraries. Does this in an infinite loop, starting -/// from scratch each time, to show how VM warm-up affects things and to make -/// it easier to connect to this with observatory. -import 'dart:io'; - -import 'package:analyzer/dart/ast/standard_resolution_map.dart'; -import 'package:analyzer/dart/element/element.dart'; -import 'package:analyzer/file_system/physical_file_system.dart'; -import 'package:analyzer/src/context/builder.dart'; -import 'package:analyzer/src/dart/sdk/sdk.dart'; -import 'package:analyzer/src/file_system/file_system.dart'; -import 'package:analyzer/src/generated/engine.dart'; -import 'package:analyzer/src/generated/source.dart'; -import 'package:analyzer/src/generated/source_io.dart'; -import 'package:analyzer/src/source/package_map_resolver.dart'; -import 'package:analyzer/src/source/source_resource.dart'; -import 'package:path/path.dart' as p; - -void main(List<String> args) { - // Assumes you have run "pub get" in the analyzer directory itself and uses - // that "packages" directory as its package root. - var packageRoot = - p.normalize(p.join(p.dirname(p.fromUri(Platform.script)), "packages")); - - var best = new Duration(days: 1); - while (true) { - var start = new DateTime.now(); - AnalysisEngine.instance.clearCaches(); - - AnalysisOptionsImpl options = new AnalysisOptionsImpl(); - options.strongModeHints = true; - - PhysicalResourceProvider resourceProvider = - PhysicalResourceProvider.INSTANCE; - FolderBasedDartSdk sdk = new FolderBasedDartSdk( - resourceProvider, resourceProvider.getFolder(args[0])); - sdk.analysisOptions = options; - - ContextBuilder builder = new ContextBuilder(resourceProvider, null, null); - AnalysisContext context = AnalysisEngine.instance.createAnalysisContext(); - context.sourceFactory = new SourceFactory([ - new DartUriResolver(sdk), - new ResourceUriResolver(resourceProvider), - new PackageMapUriResolver(resourceProvider, - builder.convertPackagesToMap(builder.createPackageMap(packageRoot))) - ]); - context.analysisOptions = options; - - var mainSource = - new FileSource(resourceProvider.getFile(p.fromUri(Platform.script))); - context.applyChanges(new ChangeSet()..addedSource(mainSource)); - - var initialLibrary = - context.resolveCompilationUnit2(mainSource, mainSource); - - // Walk all of the transitively referenced libraries and compute errors. - var errorCount = 0; - var allLibraries = _reachableLibraries( - resolutionMap.elementDeclaredByCompilationUnit(initialLibrary).library); - for (var lib in allLibraries) { - for (var unit in lib.units) { - var source = unit.source; - - // Skip core libraries. - if (source.uri.scheme == 'dart') continue; - - var librarySource = context.getLibrariesContaining(source).single; - context.resolveCompilationUnit2(source, librarySource); - errorCount += context.computeErrors(source).length; - } - } - - var elapsed = new DateTime.now().difference(start); - print("$elapsed : $errorCount errors ${elapsed < best ? "(best)" : ""}"); - if (elapsed < best) best = elapsed; - } -} - -/// Returns all libraries transitively imported or exported from [start]. -List<LibraryElement> _reachableLibraries(LibraryElement start) { - var results = <LibraryElement>[]; - var seen = new Set(); - void find(LibraryElement lib) { - if (seen.contains(lib)) return; - seen.add(lib); - results.add(lib); - lib.importedLibraries.forEach(find); - lib.exportedLibraries.forEach(find); - } - - find(start); - return results; -}
diff --git a/pkg/analyzer/example/parser_driver.dart b/pkg/analyzer/example/parser_driver.dart deleted file mode 100644 index 6515b34..0000000 --- a/pkg/analyzer/example/parser_driver.dart +++ /dev/null
@@ -1,62 +0,0 @@ -#!/usr/bin/env dart -// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file -// for details. All rights reserved. Use of this source code is governed by a -// BSD-style license that can be found in the LICENSE file. - -import 'dart:io'; - -import 'package:analyzer/dart/ast/ast.dart'; -import 'package:analyzer/dart/ast/visitor.dart'; -import 'package:analyzer/error/error.dart'; -import 'package:analyzer/error/listener.dart'; -import 'package:analyzer/file_system/physical_file_system.dart'; -import 'package:analyzer/src/dart/scanner/reader.dart'; -import 'package:analyzer/src/dart/scanner/scanner.dart'; -import 'package:analyzer/src/generated/parser.dart'; - -main(List<String> args) { - print('working dir ${new File('.').resolveSymbolicLinksSync()}'); - - if (args.length == 0) { - print('Usage: parser_driver [files_to_parse]'); - exit(0); - } - - for (var arg in args) { - _parse(new File(arg)); - } -} - -_parse(File file) { - var src = file.readAsStringSync(); - PhysicalResourceProvider resourceProvider = PhysicalResourceProvider.INSTANCE; - var source = resourceProvider.getFile(file.path).createSource(); - var errorListener = new _ErrorCollector(); - var reader = new CharSequenceReader(src); - var scanner = new Scanner(source, reader, errorListener); - var token = scanner.tokenize(); - var parser = new Parser(source, errorListener); - var unit = parser.parseCompilationUnit(token); - - var visitor = new _ASTVisitor(); - unit.accept(visitor); - - for (var error in errorListener.errors) { - print(error); - } -} - -class _ASTVisitor extends GeneralizingAstVisitor { - @override - visitNode(AstNode node) { - print('${node.runtimeType} : <"$node">'); - return super.visitNode(node); - } -} - -class _ErrorCollector extends AnalysisErrorListener { - List<AnalysisError> errors; - _ErrorCollector() : errors = new List<AnalysisError>(); - @override - onError(error) => errors.add(error); -}
diff --git a/pkg/analyzer/example/resolver_driver.dart b/pkg/analyzer/example/resolver_driver.dart deleted file mode 100755 index 6c972a8..0000000 --- a/pkg/analyzer/example/resolver_driver.dart +++ /dev/null
@@ -1,87 +0,0 @@ -#!/usr/bin/env dart -// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file -// for details. All rights reserved. Use of this source code is governed by a -// BSD-style license that can be found in the LICENSE file. - -import 'dart:io'; - -import 'package:analyzer/dart/ast/ast.dart'; -import 'package:analyzer/dart/ast/visitor.dart'; -import 'package:analyzer/dart/element/element.dart'; -import 'package:analyzer/file_system/physical_file_system.dart'; -import 'package:analyzer/src/context/builder.dart'; -import 'package:analyzer/src/dart/sdk/sdk.dart'; -import 'package:analyzer/src/file_system/file_system.dart'; -import 'package:analyzer/src/generated/engine.dart'; -import 'package:analyzer/src/generated/sdk.dart' show DartSdk; -import 'package:analyzer/src/generated/source.dart'; -import 'package:analyzer/src/generated/source_io.dart'; -import 'package:analyzer/src/source/package_map_resolver.dart'; -import 'package:analyzer/src/source/source_resource.dart'; - -void main(List<String> args) { - print('working dir ${new File('.').resolveSymbolicLinksSync()}'); - - if (args.length < 2 || args.length > 3) { - print(_usage); - exit(0); - } - - String packageRoot; - if (args.length == 3) { - packageRoot = args[2]; - } - - PhysicalResourceProvider resourceProvider = PhysicalResourceProvider.INSTANCE; - DartSdk sdk = new FolderBasedDartSdk( - resourceProvider, resourceProvider.getFolder(args[0])); - - var resolvers = [ - new DartUriResolver(sdk), - new ResourceUriResolver(resourceProvider) - ]; - - if (packageRoot != null) { - ContextBuilder builder = new ContextBuilder(resourceProvider, null, null); - resolvers.add(new PackageMapUriResolver(resourceProvider, - builder.convertPackagesToMap(builder.createPackageMap(packageRoot)))); - } - - AnalysisContext context = AnalysisEngine.instance.createAnalysisContext() - ..sourceFactory = new SourceFactory(resolvers); - - Source source = new FileSource(resourceProvider.getFile(args[1])); - ChangeSet changeSet = new ChangeSet()..addedSource(source); - context.applyChanges(changeSet); - LibraryElement libElement = context.computeLibraryElement(source); - print("libElement: $libElement"); - - CompilationUnit resolvedUnit = - context.resolveCompilationUnit(source, libElement); - var visitor = new _ASTVisitor(); - resolvedUnit.accept(visitor); -} - -const _usage = - 'Usage: resolve_driver <path_to_sdk> <file_to_resolve> [<packages_root>]'; - -class _ASTVisitor extends GeneralizingAstVisitor { - @override - visitNode(AstNode node) { - var lines = <String>['${node.runtimeType} : <"$node">']; - if (node is SimpleIdentifier) { - Element element = node.staticElement; - if (element != null) { - lines.add(' element: ${element.runtimeType}'); - LibraryElement library = element.library; - if (library != null) { - var fullName = - element.library.definingCompilationUnit.source.fullName; - lines.add(" from $fullName"); - } - } - } - print(lines.join('\n')); - return super.visitNode(node); - } -}
diff --git a/pkg/analyzer/example/scanner_driver.dart b/pkg/analyzer/example/scanner_driver.dart deleted file mode 100644 index 22a4e0f..0000000 --- a/pkg/analyzer/example/scanner_driver.dart +++ /dev/null
@@ -1,43 +0,0 @@ -#!/usr/bin/env dart -// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file -// for details. All rights reserved. Use of this source code is governed by a -// BSD-style license that can be found in the LICENSE file. - -import 'dart:io'; - -import 'package:analyzer/dart/ast/token.dart'; -import 'package:analyzer/error/listener.dart'; -import 'package:analyzer/file_system/physical_file_system.dart'; -import 'package:analyzer/src/dart/scanner/reader.dart'; -import 'package:analyzer/src/dart/scanner/scanner.dart'; - -main(List<String> args) { - print('working dir ${new File('.').resolveSymbolicLinksSync()}'); - - if (args.length == 0) { - print('Usage: scanner_driver [files_to_scan]'); - exit(0); - } - - for (var arg in args) { - _scan(new File(arg)); - } -} - -_scan(File file) { - var src = file.readAsStringSync(); - PhysicalResourceProvider resourceProvider = PhysicalResourceProvider.INSTANCE; - var source = resourceProvider.getFile(file.path).createSource(); - var reader = new CharSequenceReader(src); - var listener = new BooleanErrorListener(); - var scanner = new Scanner(source, reader, listener); - var token = scanner.tokenize(); - while (token.type != TokenType.EOF) { - print(token); - token = token.next; - } - if (listener.errorReported) { - print('Errors found.'); - exit(1); - } -}
diff --git a/pkg/analyzer/lib/analyzer.dart b/pkg/analyzer/lib/analyzer.dart index ab46a8d..3516414 100644 --- a/pkg/analyzer/lib/analyzer.dart +++ b/pkg/analyzer/lib/analyzer.dart
@@ -2,6 +2,9 @@ // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. +@deprecated +library analyzer; + import 'dart:io'; import 'package:analyzer/dart/ast/ast.dart';
diff --git a/pkg/analyzer/lib/dart/analysis/context_builder.dart b/pkg/analyzer/lib/dart/analysis/context_builder.dart index 69ef376..f99dce5 100644 --- a/pkg/analyzer/lib/dart/analysis/context_builder.dart +++ b/pkg/analyzer/lib/dart/analysis/context_builder.dart
@@ -30,13 +30,22 @@ * the the variable names found in `fromEnvironment` invocations to the * constant value that will be returned. If none is given, then no variables * will be defined. + * + * If a list of [librarySummaryPaths] is provided, then the summary files at + * those paths will be used, when possible, when analyzing the libraries + * contained in the summary files. * * If an [sdkPath] is provided, and if it is a valid path to a directory * containing a valid SDK, then the SDK in the referenced directory will be * used when analyzing the code in the context. + * + * If an [sdkSummaryPath] is provided, then that file will be used as the + * summary file for the SDK. */ AnalysisContext createContext( {@required ContextRoot contextRoot, DeclaredVariables declaredVariables, - String sdkPath}); + List<String> librarySummaryPaths, + String sdkPath, + String sdkSummaryPath}); }
diff --git a/pkg/analyzer/lib/dart/analysis/results.dart b/pkg/analyzer/lib/dart/analysis/results.dart index 2c33745..55defb7 100644 --- a/pkg/analyzer/lib/dart/analysis/results.dart +++ b/pkg/analyzer/lib/dart/analysis/results.dart
@@ -9,43 +9,29 @@ import 'package:analyzer/src/generated/resolver.dart'; import 'package:analyzer/src/generated/source.dart'; -/** - * The result of performing some kind of analysis on a single file. Every result - * that implements this interface will also implement a sub-interface. - * - * Clients may not extend, implement or mix-in this class. - */ +/// The result of performing some kind of analysis on a single file. Every +/// result that implements this interface will also implement a sub-interface. +/// +/// Clients may not extend, implement or mix-in this class. abstract class AnalysisResult { - /** - * The absolute and normalized path of the file that was analyzed. - */ + /// The absolute and normalized path of the file that was analyzed. String get path; - /** - * Return the session used to compute this result. - */ + /// Return the session used to compute this result. AnalysisSession get session; - /** - * The state of the results. - */ + /// The state of the results. ResultState get state; - /** - * The absolute URI of the file that was analyzed. - */ + /// The absolute URI of the file that was analyzed. Uri get uri; } -/** - * An analysis result that includes the errors computed during analysis. - * - * Clients may not extend, implement or mix-in this class. - */ +/// An analysis result that includes the errors computed during analysis. +/// +/// Clients may not extend, implement or mix-in this class. abstract class AnalysisResultWithErrors implements FileResult { - /** - * The analysis errors that were computed during analysis. - */ + /// The analysis errors that were computed during analysis. List<AnalysisError> get errors; } @@ -68,29 +54,21 @@ ResolvedUnitResult get resolvedUnit; } -/** - * The result of computing all of the errors contained in a single file, both - * syntactic and semantic. - * - * Clients may not extend, implement or mix-in this class. - */ +/// The result of computing all of the errors contained in a single file, both +/// syntactic and semantic. +/// +/// Clients may not extend, implement or mix-in this class. abstract class ErrorsResult implements AnalysisResultWithErrors {} -/** - * The result of computing some cheap information for a single file, when full - * parsed file is not required, so [ParseResult] is not necessary. - * - * Clients may not extend, implement or mix-in this class. - */ +/// The result of computing some cheap information for a single file, when full +/// parsed file is not required, so [ParsedUnitResult] is not necessary. +/// +/// Clients may not extend, implement or mix-in this class. abstract class FileResult implements AnalysisResult { - /** - * Whether the file is a part. - */ + /// Whether the file is a part. bool get isPart; - /** - * Information about lines in the content. - */ + /// Information about lines in the content. LineInfo get lineInfo; } @@ -111,23 +89,19 @@ /// those discovered during scanning and parsing. /// /// Clients may not extend, implement or mix-in this class. +// ignore: deprecated_member_use abstract class ParsedUnitResult implements ParseResult {} -/** - * The result of parsing of a single file. The errors returned include only - * those discovered during scanning and parsing. - * - * Clients may not extend, implement or mix-in this class. - */ +/// The result of parsing of a single file. The errors returned include only +/// those discovered during scanning and parsing. +/// +/// Clients may not extend, implement or mix-in this class. +@deprecated abstract class ParseResult implements AnalysisResultWithErrors { - /** - * The content of the file that was scanned and parsed. - */ + /// The content of the file that was scanned and parsed. String get content; - /** - * The parsed, unresolved compilation unit for the [content]. - */ + /// The parsed, unresolved compilation unit for the [content]. CompilationUnit get unit; } @@ -154,85 +128,61 @@ /// include both syntactic and semantic errors. /// /// Clients may not extend, implement or mix-in this class. +// ignore: deprecated_member_use abstract class ResolvedUnitResult implements ResolveResult {} -/** - * The result of building a resolved AST for a single file. The errors returned - * include both syntactic and semantic errors. - * - * Clients may not extend, implement or mix-in this class. - */ +/// The result of building a resolved AST for a single file. The errors returned +/// include both syntactic and semantic errors. +/// +/// Clients may not extend, implement or mix-in this class. +@deprecated abstract class ResolveResult implements AnalysisResultWithErrors { - /** - * The content of the file that was scanned, parsed and resolved. - */ + /// The content of the file that was scanned, parsed and resolved. String get content; - /** - * The element representing the library containing the compilation [unit]. - */ + /// The element representing the library containing the compilation [unit]. LibraryElement get libraryElement; - /** - * The type provider used when resolving the compilation [unit]. - */ + /// The type provider used when resolving the compilation [unit]. TypeProvider get typeProvider; - /** - * The type system used when resolving the compilation [unit]. - */ + /// The type system used when resolving the compilation [unit]. TypeSystem get typeSystem; - /** - * The fully resolved compilation unit for the [content]. - */ + /// The fully resolved compilation unit for the [content]. CompilationUnit get unit; } -/** - * An indication of whether an analysis result is valid, and if not why. - */ +/// An indication of whether an analysis result is valid, and if not why. enum ResultState { - /** - * An indication that analysis could not be performed because the path - * represents a file of a type that cannot be analyzed. - */ + /// An indication that analysis could not be performed because the path + /// represents a file of a type that cannot be analyzed. INVALID_FILE_TYPE, - /** - * An indication that analysis could not be performed because the path does - * not represent a file. It might represent something else, such as a - * directory, or it might not represent anything. - */ + /// An indication that analysis could not be performed because the path does + /// not represent a file. It might represent something else, such as a + /// directory, or it might not represent anything. NOT_A_FILE, - /** - * An indication that analysis completed normally and the results are valid. - */ + /// An indication that analysis completed normally and the results are valid. VALID } -/** - * The result of building the element model for a single file. - * - * Clients may not extend, implement or mix-in this class. - */ +/// The result of building the element model for a single file. +/// +/// Clients may not extend, implement or mix-in this class. abstract class UnitElementResult implements AnalysisResult { - /** - * The element of the file. - */ + /// The element of the file. CompilationUnitElement get element; - /** - * The signature of the library containing the [element]. This is the same - * signature returned by the method [AnalysisSession.getUnitElementSignature] - * when given the path to the compilation unit represented by the [element]. - * - * The signature is based on the APIs of the files of the library (including - * the file itself), and the transitive closure of files imported and exported - * by the library. If the signature of a file has not changed, then there have - * been no changes that would cause any files that depend on it to need to be - * re-analyzed. - */ + /// The signature of the library containing the [element]. This is the same + /// signature returned by the method [AnalysisSession.getUnitElementSignature] + /// when given the path to the compilation unit represented by the [element]. + /// + /// The signature is based on the APIs of the files of the library (including + /// the file itself), and the transitive closure of files imported and + /// exported by the library. If the signature of a file has not changed, then + /// there have been no changes that would cause any files that depend on it + /// to need to be re-analyzed. String get signature; }
diff --git a/pkg/analyzer/lib/dart/analysis/session.dart b/pkg/analyzer/lib/dart/analysis/session.dart index b945ed6..6f31a7b 100644 --- a/pkg/analyzer/lib/dart/analysis/session.dart +++ b/pkg/analyzer/lib/dart/analysis/session.dart
@@ -4,6 +4,7 @@ import 'dart:async'; +import 'package:analyzer/dart/analysis/analysis_context.dart'; import 'package:analyzer/dart/analysis/declared_variables.dart'; import 'package:analyzer/dart/analysis/results.dart'; import 'package:analyzer/dart/analysis/uri_converter.dart'; @@ -14,81 +15,86 @@ import 'package:analyzer/src/generated/resolver.dart'; import 'package:analyzer/src/generated/source.dart'; -/** - * A consistent view of the results of analyzing one or more files. - * - * The methods in this class that return analysis results will throw an - * [InconsistentAnalysisException] if the result to be returned might be - * inconsistent with any previously returned results. - * - * Clients may not extend, implement or mix-in this class. - */ +/// A consistent view of the results of analyzing one or more files. +/// +/// The methods in this class that return analysis results will throw an +/// [InconsistentAnalysisException] if the result to be returned might be +/// inconsistent with any previously returned results. +/// +/// Clients may not extend, implement or mix-in this class. abstract class AnalysisSession { - /** - * The declared environment variables. - */ + /// The analysis context that created this session. + AnalysisContext get analysisContext; + + /// The declared environment variables. DeclaredVariables get declaredVariables; - /** - * Return the [ResourceProvider] that is used to access the file system. - */ + /// Return the [ResourceProvider] that is used to access the file system. ResourceProvider get resourceProvider; - /** - * Return the source factory used to resolve URIs. - * - * Deprecated: Use the methods on [uriConverter] instead. - */ + /// Return the source factory used to resolve URIs. + /// + /// Deprecated: Use the methods on [uriConverter] instead. @deprecated SourceFactory get sourceFactory; - /** - * Return a type provider that is consistent with the results returned by this - * session. - */ + /// Return a type provider that is consistent with the results returned by + /// this session. Future<TypeProvider> get typeProvider; - /** - * Return the type system being used by this session. - */ + /// Return the type system being used by this session. Future<TypeSystem> get typeSystem; - /** - * Return the URI converter used to convert between URI's and file paths. - */ + /// Return the URI converter used to convert between URI's and file paths. UriConverter get uriConverter; - /** - * Return a future that will complete with information about the errors - * contained in the file with the given absolute, normalized [path]. - * - * If the file cannot be analyzed by this session, then the result will have - * a result state indicating the nature of the problem. - */ + /// Return a future that will complete with information about the errors + /// contained in the file with the given absolute, normalized [path]. + /// + /// If the file cannot be analyzed by this session, then the result will have + /// a result state indicating the nature of the problem. Future<ErrorsResult> getErrors(String path); - /** - * Return a future that will complete with the library element representing - * the library with the given [uri]. - */ + /// Return a future that will complete with the library element representing + /// the library with the given [uri]. Future<LibraryElement> getLibraryByUri(String uri); - /** - * Return a future that will complete with information about the results of - * parsing the file with the given absolute, normalized [path]. - */ + /// Return a future that will complete with information about the results of + /// parsing the file with the given absolute, normalized [path]. + /// + /// Deprecated: Use [getParsedUnit] instead. + @deprecated Future<ParseResult> getParsedAst(String path); - /** - * Return information about the results of parsing the file with the given - * absolute, normalized [path]. - */ + /// Return information about the results of parsing the file with the given + /// absolute, normalized [path]. + /// + /// Deprecated: Use [getParsedUnit] instead. + @deprecated ParseResult getParsedAstSync(String path); - /** - * Return a future that will complete with information about the results of - * resolving the file with the given absolute, normalized [path]. - */ + /// Return information about the results of parsing units of the library file + /// with the given absolute, normalized [path]. + /// + /// Throw [ArgumentError] if the given [path] is not the defining compilation + /// unit for a library (that is, is a part of a library). + ParsedLibraryResult getParsedLibrary(String path); + + /// Return information about the results of parsing units of the library file + /// with the given library [element]. + /// + /// Throw [ArgumentError] if the [element] was not produced by this session. + ParsedLibraryResult getParsedLibraryByElement(LibraryElement element); + + /// Return information about the results of parsing the file with the given + /// absolute, normalized [path]. + ParsedUnitResult getParsedUnit(String path); + + /// Return a future that will complete with information about the results of + /// resolving the file with the given absolute, normalized [path]. + /// + /// Deprecated: Use [getResolvedUnit] instead. + @deprecated Future<ResolveResult> getResolvedAst(String path); /// Return a future that will complete with information about the results of @@ -106,46 +112,41 @@ Future<ResolvedLibraryResult> getResolvedLibraryByElement( LibraryElement element); - /** - * Return a future that will complete with the source kind of the file with - * the given absolute, normalized [path]. If the path does not represent a - * file or if the kind of the file cannot be determined, then the future will - * complete with [SourceKind.UNKNOWN]. - */ + /// Return a future that will complete with information about the results of + /// resolving the file with the given absolute, normalized [path]. + Future<ResolvedUnitResult> getResolvedUnit(String path); + + /// Return a future that will complete with the source kind of the file with + /// the given absolute, normalized [path]. If the path does not represent a + /// file or if the kind of the file cannot be determined, then the future will + /// complete with [SourceKind.UNKNOWN]. Future<SourceKind> getSourceKind(String path); - /** - * Return a future that will complete with a list of the top-level - * declarations with the given [name] in all known libraries. - */ + /// Return a future that will complete with a list of the top-level + /// declarations with the given [name] in all known libraries. Future<List<TopLevelDeclarationInSource>> getTopLevelDeclarations( String name); - /** - * Return a future that will complete with information about the results of - * building the element model for the file with the given absolute, normalized - * [path]. - */ + /// Return a future that will complete with information about the results of + /// building the element model for the file with the given absolute, + /// normalized[path]. Future<UnitElementResult> getUnitElement(String path); - /** - * Return a future that will complete with the signature for the file with the - * given absolute, normalized [path], or `null` if the file cannot be analyzed. - * This is the same signature returned in the result from [getUnitElement]. - * - * The signature is based on the APIs of the files of the library (including - * the file itself), and the transitive closure of files imported and exported - * by the library. If the signature of a file has not changed, then there have - * been no changes that would cause any files that depend on it to need to be - * re-analyzed. - */ + /// Return a future that will complete with the signature for the file with + /// the given absolute, normalized [path], or `null` if the file cannot be + /// analyzed. This is the same signature returned in the result from + /// [getUnitElement]. + /// + /// The signature is based on the APIs of the files of the library (including + /// the file itself), and the transitive closure of files imported and + /// exported by the library. If the signature of a file has not changed, then + /// there have been no changes that would cause any files that depend on it to + /// need to be re-analyzed. Future<String> getUnitElementSignature(String path); } -/** - * The exception thrown by an [AnalysisSession] if a result is requested that - * might be inconsistent with any previously returned results. - */ +/// The exception thrown by an [AnalysisSession] if a result is requested that +/// might be inconsistent with any previously returned results. class InconsistentAnalysisException extends AnalysisException { InconsistentAnalysisException() : super('Requested result might be inconsistent with previously '
diff --git a/pkg/analyzer/lib/dart/analysis/utilities.dart b/pkg/analyzer/lib/dart/analysis/utilities.dart new file mode 100644 index 0000000..75ef87b --- /dev/null +++ b/pkg/analyzer/lib/dart/analysis/utilities.dart
@@ -0,0 +1,57 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'dart:async'; + +import 'package:analyzer/dart/analysis/analysis_context.dart'; +import 'package:analyzer/dart/analysis/analysis_context_collection.dart'; +import 'package:analyzer/dart/analysis/results.dart'; +import 'package:analyzer/file_system/file_system.dart'; +import 'package:analyzer/file_system/physical_file_system.dart'; +import 'package:meta/meta.dart'; + +/// Return the result of parsing the file at the given [path]. +/// +/// If a [resourceProvider] is given, it will be used to access the file system. +/// +/// Note that if more than one file is going to be parsed then this function is +/// inefficient. Clients should instead use [AnalysisContextCollection] to +/// create one or more contexts and use those contexts to parse the files. +ParsedUnitResult parseFile( + {@required String path, ResourceProvider resourceProvider}) { + AnalysisContext context = + _createAnalysisContext(path: path, resourceProvider: resourceProvider); + return context.currentSession.getParsedUnit(path); +} + +/// Return the result of resolving the file at the given [path]. +/// +/// If a [resourceProvider] is given, it will be used to access the file system. +/// +/// Note that if more than one file is going to be resolved then this function +/// is inefficient. Clients should instead use [AnalysisContextCollection] to +/// create one or more contexts and use those contexts to resolve the files. +Future<ResolvedUnitResult> resolveFile( + {@required String path, ResourceProvider resourceProvider}) async { + AnalysisContext context = + _createAnalysisContext(path: path, resourceProvider: resourceProvider); + return await context.currentSession.getResolvedUnit(path); +} + +/// Return a newly create analysis context in which the file at the given [path] +/// can be analyzed. +/// +/// If a [resourceProvider] is given, it will be used to access the file system. +AnalysisContext _createAnalysisContext( + {@required String path, ResourceProvider resourceProvider}) { + AnalysisContextCollection collection = new AnalysisContextCollection( + includedPaths: <String>[path], + resourceProvider: resourceProvider ?? PhysicalResourceProvider.INSTANCE, + ); + List<AnalysisContext> contexts = collection.contexts; + if (contexts.length != 1) { + throw new ArgumentError('path must be an absolute path to a single file'); + } + return contexts[0]; +}
diff --git a/pkg/analyzer/lib/dart/ast/ast.dart b/pkg/analyzer/lib/dart/ast/ast.dart index 661d15b..d0c6320 100644 --- a/pkg/analyzer/lib/dart/ast/ast.dart +++ b/pkg/analyzer/lib/dart/ast/ast.dart
@@ -554,6 +554,12 @@ E thisOrAncestorMatching<E extends AstNode>(Predicate<AstNode> predicate); /** + * Return either this node or the most immediate ancestor of this node that + * has the given type, or `null` if there is no such node. + */ + T thisOrAncestorOfType<T extends AstNode>(); + + /** * Return a textual description of this node in a form approximating valid * source. The returned string will not be valid source primarily in the case * where the node itself is not well-formed. @@ -757,6 +763,8 @@ R visitScriptTag(ScriptTag node); + R visitSetLiteral(SetLiteral node); + R visitShowCombinator(ShowCombinator node); R visitSimpleFormalParameter(SimpleFormalParameter node); @@ -4347,8 +4355,6 @@ * ('new' | 'const')? [TypeName] ('.' [SimpleIdentifier])? [ArgumentList] * * Clients may not extend, implement or mix-in this class. - * - * 'new' | 'const' are only optional if the previewDart2 option is enabled. */ abstract class InstanceCreationExpression extends Expression implements ConstructorReferenceNode { @@ -6029,6 +6035,43 @@ } /** + * A literal set. + * + * setLiteral ::= + * 'const'? ('<' [TypeAnnotation] '>')? + * '{' [Expression] (',' [Expression])* ','? '}' + * | 'const'? ('<' [TypeAnnotation] '>')? '{' '}' + * + * Clients may not extend, implement or mix-in this class. + */ +abstract class SetLiteral extends TypedLiteral { + /** + * Return the expressions used to compute the elements of the set. + */ + NodeList<Expression> get elements; + + /** + * Return the left curly bracket. + */ + Token get leftBracket; + + /** + * Set the left curly bracket to the given [token]. + */ + void set leftBracket(Token token); + + /** + * Return the right curly bracket. + */ + Token get rightBracket; + + /** + * Set the right curly bracket to the given [token]. + */ + void set rightBracket(Token token); +} + +/** * A combinator that restricts the names being imported to those in a given list. * * showCombinator ::=
diff --git a/pkg/analyzer/lib/dart/ast/ast_factory.dart b/pkg/analyzer/lib/dart/ast/ast_factory.dart index 5d46028..4d402b0 100644 --- a/pkg/analyzer/lib/dart/ast/ast_factory.dart +++ b/pkg/analyzer/lib/dart/ast/ast_factory.dart
@@ -939,6 +939,15 @@ ScriptTag scriptTag(Token scriptTag); /** + * Returns a newly created set literal. The [constKeyword] can be `null` + * if the literal is not a constant. The [typeArguments] can be `null` if no + * type arguments were declared. The list of [elements] can be `null` if the + * set is empty. + */ + SetLiteral setLiteral(Token constKeyword, TypeArgumentList typeArguments, + Token leftBracket, List<Expression> elements, Token rightBracket); + + /** * Returns a newly created import show combinator. */ ShowCombinator showCombinator(
diff --git a/pkg/analyzer/lib/dart/ast/visitor.dart b/pkg/analyzer/lib/dart/ast/visitor.dart index 6394b8b..53ff333 100644 --- a/pkg/analyzer/lib/dart/ast/visitor.dart +++ b/pkg/analyzer/lib/dart/ast/visitor.dart
@@ -480,6 +480,9 @@ R visitScriptTag(ScriptTag scriptTag) => visitNode(scriptTag); @override + R visitSetLiteral(SetLiteral node) => visitTypedLiteral(node); + + @override R visitShowCombinator(ShowCombinator node) => visitCombinator(node); @override @@ -1123,6 +1126,12 @@ } @override + R visitSetLiteral(SetLiteral node) { + node.visitChildren(this); + return null; + } + + @override R visitShowCombinator(ShowCombinator node) { node.visitChildren(this); return null; @@ -1552,6 +1561,9 @@ R visitScriptTag(ScriptTag node) => null; @override + R visitSetLiteral(SetLiteral node) => null; + + @override R visitShowCombinator(ShowCombinator node) => null; @override @@ -1910,6 +1922,9 @@ R visitScriptTag(ScriptTag node) => _throw(node); @override + R visitSetLiteral(SetLiteral node) => _throw(node); + + @override R visitShowCombinator(ShowCombinator node) => _throw(node); @override @@ -2720,6 +2735,14 @@ } @override + T visitSetLiteral(SetLiteral node) { + stopwatch.start(); + T result = _baseVisitor.visitSetLiteral(node); + stopwatch.stop(); + return result; + } + + @override T visitShowCombinator(ShowCombinator node) { stopwatch.start(); T result = _baseVisitor.visitShowCombinator(node); @@ -3213,6 +3236,9 @@ R visitScriptTag(ScriptTag scriptTag) => visitNode(scriptTag); @override + R visitSetLiteral(SetLiteral node) => visitNode(node); + + @override R visitShowCombinator(ShowCombinator node) => visitNode(node); @override @@ -3296,7 +3322,7 @@ * A helper class used to implement the correct order of visits for a * [BreadthFirstVisitor]. */ -class _BreadthFirstChildVisitor extends UnifyingAstVisitor<Object> { +class _BreadthFirstChildVisitor extends UnifyingAstVisitor<void> { /** * The [BreadthFirstVisitor] being helped by this visitor. */ @@ -3308,8 +3334,7 @@ _BreadthFirstChildVisitor(this.outerVisitor); @override - Object visitNode(AstNode node) { + void visitNode(AstNode node) { outerVisitor._queue.add(node); - return null; } }
diff --git a/pkg/analyzer/lib/dart/constant/value.dart b/pkg/analyzer/lib/dart/constant/value.dart index 2d7ddda..64a29c6 100644 --- a/pkg/analyzer/lib/dart/constant/value.dart +++ b/pkg/analyzer/lib/dart/constant/value.dart
@@ -130,6 +130,14 @@ Map<DartObject, DartObject> toMapValue(); /** + * Return a set corresponding to the value of the object being represented, + * or `null` if + * * this object is not of type 'Set', or + * * the value of the object being represented is `null`. + */ + Set<DartObject> toSetValue(); + + /** * Return a string corresponding to the value of the object being represented, * or `null` if * * this object is not of type 'String',
diff --git a/pkg/analyzer/lib/dart/element/element.dart b/pkg/analyzer/lib/dart/element/element.dart index a282eb8..87e6f0f 100644 --- a/pkg/analyzer/lib/dart/element/element.dart +++ b/pkg/analyzer/lib/dart/element/element.dart
@@ -34,9 +34,11 @@ /// representation of the statements in a method body, but if one of those /// statements declares a local variable then the local variable will be /// represented by an element. +import 'package:analyzer/dart/analysis/session.dart'; import 'package:analyzer/dart/ast/ast.dart'; import 'package:analyzer/dart/constant/value.dart'; import 'package:analyzer/dart/element/type.dart'; +import 'package:analyzer/error/error.dart'; import 'package:analyzer/src/generated/engine.dart' show AnalysisContext; import 'package:analyzer/src/generated/java_engine.dart'; import 'package:analyzer/src/generated/resolver.dart'; @@ -182,6 +184,7 @@ /// the class. ConstructorElement get unnamedConstructor; + @deprecated @override NamedCompilationUnitMember computeNode(); @@ -405,6 +408,7 @@ /// unit. List<ClassElement> get types; + @deprecated @override CompilationUnit computeNode(); @@ -453,6 +457,7 @@ /// library containing this constructor has not yet been resolved. ConstructorElement get redirectedConstructor; + @deprecated @override ConstructorDeclaration computeNode(); } @@ -632,6 +637,9 @@ /// does not have a name, or otherwise does not have an offset. int get nameOffset; + /// Return the analysis session in which this element is defined. + AnalysisSession get session; + @override Source get source; @@ -640,6 +648,7 @@ /// /// This method is expensive, because resolved AST might have been already /// evicted from cache, so parsing and resolving will be performed. + @deprecated CompilationUnit get unit; /// Use the given [visitor] to visit this element. Return the value returned @@ -667,6 +676,7 @@ /// cache, so parsing and resolving will be performed. /// /// <b>Note:</b> This method cannot be used in an async environment. + @deprecated AstNode computeNode(); /// Return the most immediate ancestor of this element for which the @@ -703,10 +713,14 @@ @deprecated static const List<ElementAnnotation> EMPTY_LIST = const <ElementAnnotation>[]; - /// Return a representation of the value of this annotation. - /// - /// Return `null` if the value of this annotation could not be computed - /// because of errors. + /// Return the errors that were produced while computing a value for this + /// annotation, or `null` if no value has been computed. If a value has been + /// produced but no errors were generated, then the list will be empty. + List<AnalysisError> get constantEvaluationErrors; + + /// Return a representation of the value of this annotation, or `null` if the + /// value of this annotation has not been computed or if the value could not + /// be computed because of errors. DartObject get constantValue; /// Return the element representing the field, variable, or const constructor @@ -1055,6 +1069,7 @@ @deprecated bool get isVirtual; + @deprecated @override AstNode computeNode(); } @@ -1097,6 +1112,7 @@ /// and has the name `main`. bool get isEntryPoint; + @deprecated @override FunctionDeclaration computeNode(); } @@ -1118,6 +1134,7 @@ /// type on the right side of the equals. GenericFunctionTypeElement get function; + @deprecated @override TypeAlias computeNode(); @@ -1301,6 +1318,11 @@ /// computed yet. Namespace get publicNamespace; + /// Return the top-level elements defined in each of the compilation units + /// that are included in this library. This includes both public and private + /// elements, but does not include imports, exports, or synthetic elements. + Iterable<Element> get topLevelElements; + /// Return a list containing all of the compilation units this library /// consists of. This includes the defining compilation unit and units /// included using the `part` directive. @@ -1353,6 +1375,7 @@ @deprecated static const List<MethodElement> EMPTY_LIST = const <MethodElement>[]; + @deprecated @override MethodDeclaration computeNode(); @@ -1463,6 +1486,7 @@ /// the given [buffer]. void appendToWithoutDelimiters(StringBuffer buffer); + @deprecated @override FormalParameter computeNode(); } @@ -1597,6 +1621,7 @@ static const List<TopLevelVariableElement> EMPTY_LIST = const <TopLevelVariableElement>[]; + @deprecated @override VariableDeclaration computeNode(); }
diff --git a/pkg/analyzer/lib/error/error.dart b/pkg/analyzer/lib/error/error.dart index b6545a4..4ecccad 100644 --- a/pkg/analyzer/lib/error/error.dart +++ b/pkg/analyzer/lib/error/error.dart
@@ -1,4 +1,4 @@ -// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file +// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. @@ -57,11 +57,11 @@ AnalysisOptionsHintCode.SUPER_MIXINS_SETTING_DEPRECATED, CheckedModeCompileTimeErrorCode.CONST_CONSTRUCTOR_FIELD_TYPE_MISMATCH, CheckedModeCompileTimeErrorCode.CONST_CONSTRUCTOR_PARAM_TYPE_MISMATCH, - CheckedModeCompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION, CheckedModeCompileTimeErrorCode.CONST_FIELD_INITIALIZER_NOT_ASSIGNABLE, CheckedModeCompileTimeErrorCode.LIST_ELEMENT_TYPE_NOT_ASSIGNABLE, CheckedModeCompileTimeErrorCode.MAP_KEY_TYPE_NOT_ASSIGNABLE, CheckedModeCompileTimeErrorCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE, + CheckedModeCompileTimeErrorCode.SET_ELEMENT_TYPE_NOT_ASSIGNABLE, CheckedModeCompileTimeErrorCode.VARIABLE_TYPE_MISMATCH, CompileTimeErrorCode.ABSTRACT_SUPER_MEMBER_REFERENCE, CompileTimeErrorCode.ACCESS_PRIVATE_ENUM_FIELD, @@ -96,9 +96,11 @@ CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION, CompileTimeErrorCode.CONST_EVAL_THROWS_IDBZE, CompileTimeErrorCode.CONST_EVAL_TYPE_BOOL, + CompileTimeErrorCode.CONST_EVAL_TYPE_BOOL_INT, CompileTimeErrorCode.CONST_EVAL_TYPE_BOOL_NUM_STRING, CompileTimeErrorCode.CONST_EVAL_TYPE_INT, CompileTimeErrorCode.CONST_EVAL_TYPE_NUM, + CompileTimeErrorCode.CONST_EVAL_TYPE_TYPE, CompileTimeErrorCode.CONST_FORMAL_PARAMETER, CompileTimeErrorCode.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE, CompileTimeErrorCode @@ -106,6 +108,7 @@ CompileTimeErrorCode.CONST_INSTANCE_FIELD, CompileTimeErrorCode.CONST_MAP_KEY_EXPRESSION_TYPE_IMPLEMENTS_EQUALS, CompileTimeErrorCode.CONST_NOT_INITIALIZED, + CompileTimeErrorCode.CONST_SET_ELEMENT_TYPE_IMPLEMENTS_EQUALS, CompileTimeErrorCode.CONST_WITH_INVALID_TYPE_PARAMETERS, CompileTimeErrorCode.CONST_WITH_NON_CONST, CompileTimeErrorCode.CONST_WITH_NON_CONSTANT_ARGUMENT, @@ -137,7 +140,7 @@ CompileTimeErrorCode.FOR_IN_WITH_CONST_VARIABLE, CompileTimeErrorCode.GENERIC_FUNCTION_TYPED_PARAM_UNSUPPORTED, CompileTimeErrorCode.GENERIC_FUNCTION_TYPE_CANNOT_BE_BOUND, - CompileTimeErrorCode.GENERIC_FUNCTION_CANNOT_BE_TYPE_ARGUMENT, + CompileTimeErrorCode.GENERIC_FUNCTION_TYPE_CANNOT_BE_TYPE_ARGUMENT, CompileTimeErrorCode.IMPLEMENTS_DEFERRED_CLASS, CompileTimeErrorCode.IMPLEMENTS_DISALLOWED_CLASS, CompileTimeErrorCode.IMPLEMENTS_NON_CLASS, @@ -172,6 +175,7 @@ CompileTimeErrorCode.INVALID_REFERENCE_TO_THIS, CompileTimeErrorCode.INVALID_TYPE_ARGUMENT_IN_CONST_LIST, CompileTimeErrorCode.INVALID_TYPE_ARGUMENT_IN_CONST_MAP, + CompileTimeErrorCode.INVALID_TYPE_ARGUMENT_IN_CONST_SET, CompileTimeErrorCode.INVALID_URI, CompileTimeErrorCode.INVALID_USE_OF_COVARIANT, CompileTimeErrorCode.LABEL_IN_OUTER_SCOPE, @@ -179,6 +183,7 @@ CompileTimeErrorCode.MEMBER_WITH_CLASS_NAME, CompileTimeErrorCode.MISSING_CONST_IN_LIST_LITERAL, CompileTimeErrorCode.MISSING_CONST_IN_MAP_LITERAL, + CompileTimeErrorCode.MISSING_CONST_IN_SET_LITERAL, CompileTimeErrorCode.MISSING_DART_LIBRARY, CompileTimeErrorCode.MIXIN_APPLICATION_CONCRETE_SUPER_INVOKED_MEMBER_TYPE, CompileTimeErrorCode.MIXIN_APPLICATION_NOT_IMPLEMENTED_INTERFACE, @@ -211,6 +216,8 @@ CompileTimeErrorCode.NON_CONSTANT_MAP_KEY_FROM_DEFERRED_LIBRARY, CompileTimeErrorCode.NON_CONSTANT_MAP_VALUE, CompileTimeErrorCode.NON_CONSTANT_MAP_VALUE_FROM_DEFERRED_LIBRARY, + CompileTimeErrorCode.NON_CONSTANT_SET_ELEMENT, + CompileTimeErrorCode.NON_CONSTANT_SET_ELEMENT_FROM_DEFERRED_LIBRARY, CompileTimeErrorCode.NON_CONSTANT_VALUE_IN_INITIALIZER, CompileTimeErrorCode.NON_CONSTANT_VALUE_IN_INITIALIZER_FROM_DEFERRED_LIBRARY, CompileTimeErrorCode.NON_CONST_MAP_AS_EXPRESSION_STATEMENT, @@ -318,7 +325,6 @@ HintCode.TYPE_CHECK_IS_NULL, HintCode.UNDEFINED_GETTER, HintCode.UNDEFINED_HIDDEN_NAME, - HintCode.UNDEFINED_METHOD, HintCode.UNDEFINED_OPERATOR, HintCode.UNDEFINED_SETTER, HintCode.UNDEFINED_SHOWN_NAME, @@ -533,6 +539,7 @@ ScannerErrorCode.UNTERMINATED_MULTI_LINE_COMMENT, ScannerErrorCode.UNTERMINATED_STRING_LITERAL, StaticTypeWarningCode.EXPECTED_ONE_LIST_TYPE_ARGUMENTS, + StaticTypeWarningCode.EXPECTED_ONE_SET_TYPE_ARGUMENTS, StaticTypeWarningCode.EXPECTED_TWO_MAP_TYPE_ARGUMENTS, StaticTypeWarningCode.FOR_IN_OF_INVALID_ELEMENT_TYPE, StaticTypeWarningCode.FOR_IN_OF_INVALID_TYPE, @@ -556,7 +563,6 @@ StaticTypeWarningCode.UNDEFINED_FUNCTION, StaticTypeWarningCode.UNDEFINED_GETTER, StaticTypeWarningCode.UNDEFINED_METHOD, - StaticTypeWarningCode.UNDEFINED_METHOD_WITH_CONSTRUCTOR, StaticTypeWarningCode.UNDEFINED_OPERATOR, StaticTypeWarningCode.UNDEFINED_SETTER, StaticTypeWarningCode.UNDEFINED_SUPER_GETTER, @@ -629,6 +635,7 @@ StaticWarningCode.REDIRECT_TO_MISSING_CONSTRUCTOR, StaticWarningCode.REDIRECT_TO_NON_CLASS, StaticWarningCode.RETURN_WITHOUT_VALUE, + StaticWarningCode.SET_ELEMENT_TYPE_NOT_ASSIGNABLE, StaticWarningCode.STATIC_ACCESS_TO_INSTANCE_MEMBER, StaticWarningCode.SWITCH_EXPRESSION_NOT_ASSIGNABLE, StaticWarningCode.TYPE_ANNOTATION_DEFERRED_CLASS, @@ -665,6 +672,7 @@ StrongModeCode.INVALID_CAST_LITERAL, StrongModeCode.INVALID_CAST_LITERAL_LIST, StrongModeCode.INVALID_CAST_LITERAL_MAP, + StrongModeCode.INVALID_CAST_LITERAL_SET, StrongModeCode.INVALID_CAST_FUNCTION_EXPR, StrongModeCode.INVALID_CAST_NEW_EXPR, StrongModeCode.INVALID_CAST_METHOD,
diff --git a/pkg/analyzer/lib/error/listener.dart b/pkg/analyzer/lib/error/listener.dart index eeef617..a835bc3 100644 --- a/pkg/analyzer/lib/error/listener.dart +++ b/pkg/analyzer/lib/error/listener.dart
@@ -256,58 +256,32 @@ * way that is appropriate for caching those errors within an analysis context. */ class RecordingErrorListener implements AnalysisErrorListener { - /** - * A map of sets containing the errors that were collected, keyed by each - * source. - */ - Map<Source, HashSet<AnalysisError>> _errors = - new HashMap<Source, HashSet<AnalysisError>>(); + Set<AnalysisError> _errors; /** * Return the errors collected by the listener. */ List<AnalysisError> get errors { - int numEntries = _errors.length; - if (numEntries == 0) { - return AnalysisError.NO_ERRORS; + if (_errors == null) { + return const <AnalysisError>[]; } - List<AnalysisError> resultList = new List<AnalysisError>(); - for (HashSet<AnalysisError> errors in _errors.values) { - resultList.addAll(errors); - } - return resultList; - } - - /** - * Add all of the errors recorded by the given [listener] to this listener. - */ - void addAll(RecordingErrorListener listener) { - for (AnalysisError error in listener.errors) { - onError(error); - } + return _errors.toList(); } /** * Return the errors collected by the listener for the given [source]. */ List<AnalysisError> getErrorsForSource(Source source) { - HashSet<AnalysisError> errorsForSource = _errors[source]; - if (errorsForSource == null) { - return AnalysisError.NO_ERRORS; - } else { - return new List.from(errorsForSource); + if (_errors == null) { + return const <AnalysisError>[]; } + return _errors.where((error) => error.source == source).toList(); } @override void onError(AnalysisError error) { - Source source = error.source; - HashSet<AnalysisError> errorsForSource = _errors[source]; - if (_errors[source] == null) { - errorsForSource = new HashSet<AnalysisError>(); - _errors[source] = errorsForSource; - } - errorsForSource.add(error); + _errors ??= new HashSet<AnalysisError>(); + _errors.add(error); } }
diff --git a/pkg/analyzer/lib/src/codegen/html.dart b/pkg/analyzer/lib/src/codegen/html.dart index f6405af..1cbce5f 100644 --- a/pkg/analyzer/lib/src/codegen/html.dart +++ b/pkg/analyzer/lib/src/codegen/html.dart
@@ -75,7 +75,7 @@ /** * Mixin class for generating HTML. */ -class HtmlGenerator { +mixin HtmlGenerator { List<dom.Node> _html; /**
diff --git a/pkg/analyzer/lib/src/command_line/arguments.dart b/pkg/analyzer/lib/src/command_line/arguments.dart index 904684c..c39ec25 100644 --- a/pkg/analyzer/lib/src/command_line/arguments.dart +++ b/pkg/analyzer/lib/src/command_line/arguments.dart
@@ -15,7 +15,6 @@ const String analysisOptionsFileOption = 'options'; const String bazelAnalysisOptionsPath = 'package:dart.analysis_options/default.yaml'; -const String declarationCastsFlag = 'declaration-casts'; const String defineVariableOption = 'D'; const String enableInitializingFormalAccessFlag = 'initializing-formal-access'; @deprecated @@ -47,13 +46,6 @@ options.implicitCasts = args[implicitCastsFlag]; verbose('$implicitCastsFlag = ${options.implicitCasts}'); } - if (args.wasParsed(declarationCastsFlag)) { - options.declarationCasts = args[declarationCastsFlag]; - verbose('$declarationCastsFlag = ${options.declarationCasts}'); - } else if (args.wasParsed(implicitCastsFlag)) { - options.declarationCasts = args[implicitCastsFlag]; - verbose('$declarationCastsFlag = ${options.declarationCasts}'); - } if (args.wasParsed(noImplicitDynamicFlag)) { options.implicitDynamic = !args[noImplicitDynamicFlag]; verbose('$noImplicitDynamicFlag = ${options.implicitDynamic}'); @@ -162,10 +154,10 @@ defaultsTo: true, hide: true, negatable: true); - parser.addFlag(declarationCastsFlag, + parser.addFlag('declaration-casts', negatable: true, help: 'Disable declaration casts in strong mode (https://goo.gl/cTLz40)\n' - 'This option is deprecated and will be removed in a future release.', + 'This option is now ignored and will be removed in a future release.', hide: ddc && hide); parser.addFlag(implicitCastsFlag, negatable: true,
diff --git a/pkg/analyzer/lib/src/context/builder.dart b/pkg/analyzer/lib/src/context/builder.dart index 8c7104e..3e50d4a 100644 --- a/pkg/analyzer/lib/src/context/builder.dart +++ b/pkg/analyzer/lib/src/context/builder.dart
@@ -1,10 +1,12 @@ -// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file +// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. import 'dart:collection'; import 'dart:core'; +import 'package:analyzer/dart/analysis/analysis_context.dart' as api; +import 'package:analyzer/dart/analysis/context_locator.dart' as api; import 'package:analyzer/dart/analysis/declared_variables.dart'; import 'package:analyzer/file_system/file_system.dart'; import 'package:analyzer/src/analysis_options/analysis_options_provider.dart'; @@ -15,27 +17,31 @@ flutterAnalysisOptionsPath; import 'package:analyzer/src/context/context.dart'; import 'package:analyzer/src/context/context_root.dart'; +import 'package:analyzer/src/dart/analysis/byte_store.dart'; +import 'package:analyzer/src/dart/analysis/context_root.dart' as api; import 'package:analyzer/src/dart/analysis/driver.dart' show AnalysisDriver, AnalysisDriverScheduler; +import 'package:analyzer/src/dart/analysis/driver_based_analysis_context.dart' + as api; import 'package:analyzer/src/dart/analysis/file_state.dart'; +import 'package:analyzer/src/dart/analysis/performance_logger.dart'; import 'package:analyzer/src/dart/sdk/sdk.dart'; -import 'package:analyzer/src/file_system/file_system.dart'; -import 'package:analyzer/src/generated/bazel.dart'; import 'package:analyzer/src/generated/engine.dart'; -import 'package:analyzer/src/generated/gn.dart'; -import 'package:analyzer/src/generated/package_build.dart'; import 'package:analyzer/src/generated/sdk.dart'; import 'package:analyzer/src/generated/source.dart'; -import 'package:analyzer/src/generated/workspace.dart'; +import 'package:analyzer/src/hint/sdk_constraint_extractor.dart'; import 'package:analyzer/src/lint/registry.dart'; import 'package:analyzer/src/plugin/resolver_provider.dart'; -import 'package:analyzer/src/source/package_map_resolver.dart'; +import 'package:analyzer/src/summary/package_bundle_reader.dart'; import 'package:analyzer/src/summary/summary_sdk.dart'; import 'package:analyzer/src/task/options.dart'; import 'package:analyzer/src/util/uri.dart'; +import 'package:analyzer/src/workspace/basic.dart'; +import 'package:analyzer/src/workspace/bazel.dart'; +import 'package:analyzer/src/workspace/gn.dart'; +import 'package:analyzer/src/workspace/package_build.dart'; +import 'package:analyzer/src/workspace/workspace.dart'; import 'package:args/args.dart'; -import 'package:analyzer/src/dart/analysis/byte_store.dart'; -import 'package:analyzer/src/dart/analysis/performance_logger.dart'; import 'package:package_config/packages.dart'; import 'package:package_config/packages_file.dart'; import 'package:package_config/src/packages_impl.dart'; @@ -131,9 +137,10 @@ FileContentOverlay fileContentOverlay; /** - * Whether to enable the Dart 2.0 preview. + * Whether any analysis driver created through this interface should support + * indexing and search. */ - bool get previewDart2 => true; + bool enableIndex = false; /** * Initialize a newly created builder to be ready to build a context rooted in @@ -155,7 +162,6 @@ AnalysisOptionsImpl options = getAnalysisOptions(path); context.contentCache = contentCache; context.sourceFactory = createSourceFactory(path, options); - options.previewDart2 = previewDart2; context.analysisOptions = options; context.name = path; //_processAnalysisOptions(context, optionMap); @@ -172,7 +178,11 @@ AnalysisOptions options = getAnalysisOptions(path, contextRoot: contextRoot); //_processAnalysisOptions(context, optionMap); - final sf = createSourceFactory(path, options); + SummaryDataStore summaryData; + if (builderOptions.librarySummaryPaths != null) { + summaryData = SummaryDataStore(builderOptions.librarySummaryPaths); + } + final sf = createSourceFactory(path, options, summaryData: summaryData); AnalysisDriver driver = new AnalysisDriver( analysisDriverScheduler, @@ -182,7 +192,23 @@ fileContentOverlay, contextRoot, sf, - options); + options, + enableIndex: enableIndex, + externalSummaries: summaryData); + + // Set API AnalysisContext for the driver. + var apiContextRoots = api.ContextLocator( + resourceProvider: resourceProvider, + ).locateRoots( + includedPaths: [contextRoot.root], + excludedPaths: contextRoot.exclude, + ); + driver.analysisContext = api.DriverBasedAnalysisContext( + resourceProvider, + apiContextRoots.first, + driver, + ); + // temporary plugin support: if (onCreateAnalysisDriver != null) { onCreateAnalysisDriver(driver, analysisDriverScheduler, performanceLog, @@ -255,10 +281,14 @@ return findPackagesFromFile(rootDirectoryPath); } - SourceFactory createSourceFactory(String rootPath, AnalysisOptions options) { + SourceFactory createSourceFactory(String rootPath, AnalysisOptions options, + {SummaryDataStore summaryData}) { Workspace workspace = createWorkspace(rootPath); DartSdk sdk = findSdk(workspace.packageMap, options); - return workspace.createSourceFactory(sdk); + if (summaryData != null && sdk is SummaryBasedDartSdk) { + summaryData.addBundle(null, sdk.bundle); + } + return workspace.createSourceFactory(sdk, summaryData); } Workspace createWorkspace(String rootPath) { @@ -266,12 +296,12 @@ // Bazel workspaces that include package files are treated like normal // (non-Bazel) directories. But may still use package:build. return PackageBuildWorkspace.find(resourceProvider, rootPath, this) ?? - _BasicWorkspace.find(resourceProvider, rootPath, this); + BasicWorkspace.find(resourceProvider, rootPath, this); } Workspace workspace = BazelWorkspace.find(resourceProvider, rootPath); workspace ??= GnWorkspace.find(resourceProvider, rootPath); workspace ??= PackageBuildWorkspace.find(resourceProvider, rootPath, this); - return workspace ?? _BasicWorkspace.find(resourceProvider, rootPath, this); + return workspace ?? BasicWorkspace.find(resourceProvider, rootPath, this); } /** @@ -414,7 +444,7 @@ // TODO(danrubel) restructure so that we don't create a workspace // both here and in createSourceFactory Workspace workspace = createWorkspace(path); - SourceFactory sourceFactory = workspace.createSourceFactory(null); + SourceFactory sourceFactory = workspace.createSourceFactory(null, null); AnalysisOptionsProvider optionsProvider = new AnalysisOptionsProvider(sourceFactory); @@ -472,6 +502,16 @@ } else { verbose('Using default analysis options'); } + + var pubspecFile = _findPubspecFile(path); + if (pubspecFile != null) { + var extractor = new SdkConstraintExtractor(pubspecFile); + var sdkVersionConstraint = extractor.constraint(); + if (sdkVersionConstraint != null) { + options.sdkVersionConstraint = sdkVersionConstraint; + } + } + return options; } @@ -606,6 +646,24 @@ } /** + * Return the `pubspec.yaml` file that should be used when analyzing code in + * the directory with the given [path], possibly `null`. + */ + File _findPubspecFile(String path) { + var resource = resourceProvider.getResource(path); + while (resource != null) { + if (resource is Folder) { + File pubspecFile = resource.getChildAssumingFile('pubspec.yaml'); + if (pubspecFile.exists) { + return pubspecFile; + } + } + resource = resource.parent; + } + return null; + } + + /** * Return `true` if either the directory at [rootPath] or a parent of that * directory contains a `.packages` file. */ @@ -674,6 +732,12 @@ String defaultPackagesDirectoryPath; /** + * A list of the paths of summary files that are to be used, or `null` if no + * summary information is available. + */ + List<String> librarySummaryPaths; + + /** * Initialize a newly created set of options */ ContextBuilderOptions(); @@ -773,71 +837,3 @@ } } } - -/** - * Information about a default Dart workspace. - */ -class _BasicWorkspace extends Workspace { - /** - * The [ResourceProvider] by which paths are converted into [Resource]s. - */ - final ResourceProvider provider; - - /** - * The absolute workspace root path. - */ - final String root; - - final ContextBuilder _builder; - - Map<String, List<Folder>> _packageMap; - - Packages _packages; - - _BasicWorkspace._(this.provider, this.root, this._builder); - - @override - Map<String, List<Folder>> get packageMap { - _packageMap ??= _builder.convertPackagesToMap(packages); - return _packageMap; - } - - Packages get packages { - _packages ??= _builder.createPackageMap(root); - return _packages; - } - - @override - UriResolver get packageUriResolver => - new PackageMapUriResolver(provider, packageMap); - - @override - SourceFactory createSourceFactory(DartSdk sdk) { - List<UriResolver> resolvers = <UriResolver>[]; - if (sdk != null) { - resolvers.add(new DartUriResolver(sdk)); - } - resolvers.add(packageUriResolver); - resolvers.add(new ResourceUriResolver(provider)); - return new SourceFactory(resolvers, packages, provider); - } - - /** - * Find the basic workspace that contains the given [path]. - */ - static _BasicWorkspace find( - ResourceProvider provider, String path, ContextBuilder builder) { - Context context = provider.pathContext; - - // Ensure that the path is absolute and normalized. - if (!context.isAbsolute(path)) { - throw new ArgumentError('not absolute: $path'); - } - path = context.normalize(path); - Resource resource = provider.getResource(path); - if (resource is File) { - path = resource.parent.path; - } - return new _BasicWorkspace._(provider, path, builder); - } -}
diff --git a/pkg/analyzer/lib/src/context/context.dart b/pkg/analyzer/lib/src/context/context.dart index 2dc5cfd..f26ad7d 100644 --- a/pkg/analyzer/lib/src/context/context.dart +++ b/pkg/analyzer/lib/src/context/context.dart
@@ -283,9 +283,6 @@ ? this._options.strongModeHints != options.strongModeHints : false) || ((options is AnalysisOptionsImpl) - ? this._options.declarationCasts != options.declarationCasts - : false) || - ((options is AnalysisOptionsImpl) ? this._options.implicitCasts != options.implicitCasts : false) || ((options is AnalysisOptionsImpl) @@ -313,10 +310,8 @@ this._options.patchPaths = options.patchPaths; if (options is AnalysisOptionsImpl) { this._options.strongModeHints = options.strongModeHints; - this._options.declarationCasts = options.declarationCasts; this._options.implicitCasts = options.implicitCasts; this._options.implicitDynamic = options.implicitDynamic; - this._options.isMixinSupportEnabled = options.isMixinSupportEnabled; } if (needsRecompute) { for (WorkManager workManager in workManagers) {
diff --git a/pkg/analyzer/lib/src/dart/analysis/analysis_context_collection.dart b/pkg/analyzer/lib/src/dart/analysis/analysis_context_collection.dart index a474878..f844029 100644 --- a/pkg/analyzer/lib/src/dart/analysis/analysis_context_collection.dart +++ b/pkg/analyzer/lib/src/dart/analysis/analysis_context_collection.dart
@@ -4,10 +4,11 @@ import 'package:analyzer/dart/analysis/analysis_context.dart'; import 'package:analyzer/dart/analysis/analysis_context_collection.dart'; -import 'package:analyzer/dart/analysis/context_builder.dart'; import 'package:analyzer/dart/analysis/context_locator.dart'; import 'package:analyzer/file_system/file_system.dart'; import 'package:analyzer/file_system/physical_file_system.dart'; +import 'package:analyzer/src/dart/analysis/context_builder.dart'; +import 'package:analyzer/src/dart/analysis/file_state.dart'; import 'package:meta/meta.dart'; /// An implementation of [AnalysisContextCollection]. @@ -20,7 +21,9 @@ /// Initialize a newly created analysis context manager. AnalysisContextCollectionImpl( - {@required List<String> includedPaths, + {bool enableIndex: false, + @deprecated FileContentOverlay fileContentOverlay, + @required List<String> includedPaths, ResourceProvider resourceProvider, String sdkPath}) : resourceProvider = @@ -35,11 +38,15 @@ ); var roots = contextLocator.locateRoots(includedPaths: includedPaths); for (var root in roots) { - var contextBuilder = new ContextBuilder( + var contextBuilder = new ContextBuilderImpl( resourceProvider: this.resourceProvider, ); - var context = - contextBuilder.createContext(contextRoot: root, sdkPath: sdkPath); + var context = contextBuilder.createContext( + contextRoot: root, + enableIndex: enableIndex, + fileContentOverlay: fileContentOverlay, + sdkPath: sdkPath, + ); contexts.add(context); } }
diff --git a/pkg/analyzer/lib/src/dart/analysis/ast_provider_driver.dart b/pkg/analyzer/lib/src/dart/analysis/ast_provider_driver.dart deleted file mode 100644 index 21c2297..0000000 --- a/pkg/analyzer/lib/src/dart/analysis/ast_provider_driver.dart +++ /dev/null
@@ -1,66 +0,0 @@ -// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file -// for details. All rights reserved. Use of this source code is governed by a -// BSD-style license that can be found in the LICENSE file. - -import 'dart:async'; - -import 'package:analyzer/dart/ast/ast.dart'; -import 'package:analyzer/dart/element/element.dart'; -import 'package:analyzer/src/dart/analysis/driver.dart'; -import 'package:analyzer/src/dart/ast/utilities.dart'; -import 'package:analyzer/src/dart/element/ast_provider.dart'; - -/** - * [AstProvider] implementation for [AnalysisDriver]. - */ -class AstProviderForDriver implements AstProvider { - final AnalysisDriver driver; - - AstProviderForDriver(this.driver); - - @override - Future<SimpleIdentifier> getParsedNameForElement(Element element) async { - // TODO(brianwilkerson) Determine whether this await is necessary. - await null; - CompilationUnit unit = await getParsedUnitForElement(element); - return _getNameNode(unit, element); - } - - @override - Future<CompilationUnit> getParsedUnitForElement(Element element) async { - // TODO(brianwilkerson) Determine whether this await is necessary. - await null; - String path = element.source.fullName; - ParseResult parseResult = await driver.parseFile(path); - return parseResult.unit; - } - - @override - Future<SimpleIdentifier> getResolvedNameForElement(Element element) async { - // TODO(brianwilkerson) Determine whether this await is necessary. - await null; - CompilationUnit unit = await getResolvedUnitForElement(element); - return _getNameNode(unit, element); - } - - @override - Future<CompilationUnit> getResolvedUnitForElement(Element element) async { - // TODO(brianwilkerson) Determine whether this await is necessary. - await null; - String path = element.source.fullName; - AnalysisResult analysisResult = await driver.getResult(path); - return analysisResult?.unit; - } - - SimpleIdentifier _getNameNode(CompilationUnit unit, Element element) { - int nameOffset = element.nameOffset; - if (nameOffset == -1) { - return null; - } - AstNode nameNode = new NodeLocator(nameOffset).searchWithin(unit); - if (nameNode is SimpleIdentifier) { - return nameNode; - } - return null; - } -}
diff --git a/pkg/analyzer/lib/src/dart/analysis/context_builder.dart b/pkg/analyzer/lib/src/dart/analysis/context_builder.dart index f835eb6..074d46d 100644 --- a/pkg/analyzer/lib/src/dart/analysis/context_builder.dart +++ b/pkg/analyzer/lib/src/dart/analysis/context_builder.dart
@@ -11,18 +11,18 @@ import 'package:analyzer/src/context/builder.dart' as old show ContextBuilder, ContextBuilderOptions; import 'package:analyzer/src/context/context_root.dart' as old; +import 'package:analyzer/src/dart/analysis/byte_store.dart' + show ByteStore, MemoryByteStore; import 'package:analyzer/src/dart/analysis/driver.dart' show AnalysisDriver, AnalysisDriverScheduler; import 'package:analyzer/src/dart/analysis/driver_based_analysis_context.dart'; import 'package:analyzer/src/dart/analysis/file_state.dart' show FileContentOverlay; +import 'package:analyzer/src/dart/analysis/performance_logger.dart' + show PerformanceLog; import 'package:analyzer/src/dart/sdk/sdk.dart'; import 'package:analyzer/src/generated/sdk.dart' show DartSdkManager; import 'package:analyzer/src/generated/source.dart' show ContentCache; -import 'package:analyzer/src/dart/analysis/performance_logger.dart' - show PerformanceLog; -import 'package:analyzer/src/dart/analysis/byte_store.dart' - show ByteStore, MemoryByteStore; import 'package:meta/meta.dart'; /** @@ -55,10 +55,15 @@ {@deprecated ByteStore byteStore, @required ContextRoot contextRoot, DeclaredVariables declaredVariables, + bool enableIndex: false, + @deprecated FileContentOverlay fileContentOverlay, + List<String> librarySummaryPaths, @deprecated PerformanceLog performanceLog, @deprecated AnalysisDriverScheduler scheduler, - String sdkPath}) { + String sdkPath, + String sdkSummaryPath}) { byteStore ??= new MemoryByteStore(); + fileContentOverlay ??= new FileContentOverlay(); performanceLog ??= new PerformanceLog(new StringBuffer()); sdkPath ??= _defaultSdkPath; @@ -78,6 +83,12 @@ if (declaredVariables != null) { options.declaredVariables = _toMap(declaredVariables); } + if (sdkSummaryPath != null) { + options.dartSdkSummaryPath = sdkSummaryPath; + } + if (librarySummaryPaths != null) { + options.librarySummaryPaths = librarySummaryPaths; + } options.defaultPackageFilePath = contextRoot.packagesFile?.path; old.ContextBuilder builder = new old.ContextBuilder( @@ -85,7 +96,8 @@ options: options); builder.analysisDriverScheduler = scheduler; builder.byteStore = byteStore; - builder.fileContentOverlay = new FileContentOverlay(); + builder.fileContentOverlay = fileContentOverlay; + builder.enableIndex = enableIndex; builder.performanceLog = performanceLog; old.ContextRoot oldContextRoot = new old.ContextRoot(
diff --git a/pkg/analyzer/lib/src/dart/analysis/context_locator.dart b/pkg/analyzer/lib/src/dart/analysis/context_locator.dart index 4422823..e3fff7c 100644 --- a/pkg/analyzer/lib/src/dart/analysis/context_locator.dart +++ b/pkg/analyzer/lib/src/dart/analysis/context_locator.dart
@@ -13,19 +13,18 @@ import 'package:analyzer/src/context/builder.dart' show ContextBuilder, ContextBuilderOptions; import 'package:analyzer/src/context/context_root.dart' as old; +import 'package:analyzer/src/dart/analysis/byte_store.dart' + show MemoryByteStore; import 'package:analyzer/src/dart/analysis/context_root.dart'; import 'package:analyzer/src/dart/analysis/driver.dart' show AnalysisDriver, AnalysisDriverScheduler; import 'package:analyzer/src/dart/analysis/driver_based_analysis_context.dart'; import 'package:analyzer/src/dart/analysis/file_state.dart' show FileContentOverlay; -import 'package:analyzer/src/dart/sdk/sdk.dart' show FolderBasedDartSdk; -import 'package:analyzer/src/generated/sdk.dart' show DartSdkManager; -import 'package:analyzer/src/generated/source.dart' show ContentCache; import 'package:analyzer/src/dart/analysis/performance_logger.dart' show PerformanceLog; -import 'package:analyzer/src/dart/analysis/byte_store.dart' - show MemoryByteStore; +import 'package:analyzer/src/dart/sdk/sdk.dart' show FolderBasedDartSdk; +import 'package:analyzer/src/generated/sdk.dart' show DartSdkManager; import 'package:meta/meta.dart'; /** @@ -91,7 +90,7 @@ scheduler.start(); ContextBuilderOptions options = new ContextBuilderOptions(); ContextBuilder builder = new ContextBuilder( - resourceProvider, sdkManager, new ContentCache(), + resourceProvider, sdkManager, null, options: options); if (packagesFile != null) { options.defaultPackageFilePath = packagesFile;
diff --git a/pkg/analyzer/lib/src/dart/analysis/dependency/library_builder.dart b/pkg/analyzer/lib/src/dart/analysis/dependency/library_builder.dart new file mode 100644 index 0000000..5acbdc4 --- /dev/null +++ b/pkg/analyzer/lib/src/dart/analysis/dependency/library_builder.dart
@@ -0,0 +1,667 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:analyzer/dart/ast/ast.dart'; +import 'package:analyzer/dart/ast/token.dart'; +import 'package:analyzer/src/dart/analysis/dependency/node.dart'; +import 'package:analyzer/src/dart/ast/token.dart'; +import 'package:analyzer/src/summary/api_signature.dart'; + +/// Build [Library] that describes nodes and dependencies of the library +/// with the given [uri] and [units]. +/// +/// If the [units] are just parsed, then only token signatures and referenced +/// names of nodes can be computed. If the [units] are fully resolved, then +/// also class member references can be recorded. +Library buildLibrary( + Uri uri, + List<CompilationUnit> units, + ReferenceCollector referenceCollector, +) { + return _LibraryBuilder(uri, units, referenceCollector).build(); +} + +/// The `show` or `hide` namespace combinator. +class Combinator { + final bool isShow; + final List<String> names; + + Combinator(this.isShow, this.names); + + @override + String toString() { + if (isShow) { + return 'show ' + names.join(', '); + } else { + return 'hide ' + names.join(', '); + } + } +} + +/// The `export` directive. +class Export { + /// The absolute URI of the exported library. + final Uri uri; + + /// The list of namespace combinators to apply, not `null`. + final List<Combinator> combinators; + + Export(this.uri, this.combinators); + + @override + String toString() { + return 'Export(uri: $uri, combinators: $combinators)'; + } +} + +/// The `import` directive. +class Import { + /// The absolute URI of the imported library. + final Uri uri; + + /// The import prefix, or `null` if not specified. + final String prefix; + + /// The list of namespace combinators to apply, not `null`. + final List<Combinator> combinators; + + Import(this.uri, this.prefix, this.combinators); + + @override + String toString() { + return 'Import(uri: $uri, prefix: $prefix, combinators: $combinators)'; + } +} + +/// The collection of imports, exports, and top-level nodes. +class Library { + /// The absolute URI of the library. + final Uri uri; + + /// The list of imports in this library. + final List<Import> imports; + + /// The list of exports in this library. + final List<Export> exports; + + /// The list of libraries that correspond to the [imports]. + List<Library> importedLibraries; + + /// The list of top-level nodes defined in the library. + /// + /// This list is sorted. + final List<DependencyNode> declaredNodes; + + /// The map of [declaredNodes], used for fast search. + /// TODO(scheglov) consider using binary search instead. + final Map<DependencyName, DependencyNode> declaredNodeMap = {}; + + /// The list of nodes exported from this library, either using `export` + /// directives, or declared in this library. + /// + /// This list is sorted. + List<DependencyNode> exportedNodes; + + /// The map of nodes that are visible in the library, either imported, + /// or declared in this library. + /// + /// TODO(scheglov) support for imports with prefixes + Map<String, DependencyNode> libraryScope; + + Library(this.uri, this.imports, this.exports, this.declaredNodes) { + for (var node in declaredNodes) { + declaredNodeMap[node.name] = node; + } + } + + @override + String toString() => '$uri'; +} + +/// The interface for a class that collects information about external nodes +/// referenced by a node. +/// +/// The workflow for using it is that the library builder creates a new +/// instance, fills it with names of import prefixes using [addImportPrefix]. +/// Then for each node defined in the library, methods `appendXyz` called +/// zero or more times to record references to external names to record API or +/// implementation dependencies. When all dependencies of a node are appended, +/// [finish] is invoked to construct the full [DependencyNodeDependencies]. +/// TODO(scheglov) In following CLs we will provide single implementation. +abstract class ReferenceCollector { + final Uri libraryUri; + + ReferenceCollector(this.libraryUri); + + /// Record that the [name] is a name of an import prefix. + /// + /// So, when we see code like `prefix.foo` we know that `foo` should be + /// resolved in the import scope that corresponds to `prefix` (unless the + /// name `prefix` is shadowed by a local declaration). + void addImportPrefix(String name); + + /// Collect external nodes referenced from the given [node]. + void appendExpression(Expression node); + + /// Collect external nodes referenced from the given [node]. + void appendFormalParameters(FormalParameterList node); + + /// Collect external nodes referenced from the given [node]. + void appendFunctionBody(FunctionBody node); + + /// Collect external nodes referenced from the given [node]. + void appendTypeAnnotation(TypeAnnotation node); + + /// Construct and return a new [DependencyNodeDependencies] with the given + /// [tokenSignature] and all recorded references to external nodes. Clear + /// data structures with recorded references and be ready to start recording + /// references for a new node. + DependencyNodeDependencies finish(List<int> tokenSignature); +} + +class _LibraryBuilder { + /// The URI of the library. + final Uri uri; + + /// The units of the library, parsed or fully resolved. + final List<CompilationUnit> units; + + /// The instance of the referenced names, class members collector. + final ReferenceCollector referenceCollector; + + /// The list of imports in the library. + final List<Import> imports = []; + + /// The list of exports in the library. + final List<Export> exports = []; + + /// The top-level nodes declared in the library. + final List<DependencyNode> declaredNodes = []; + + _LibraryBuilder(this.uri, this.units, this.referenceCollector); + + Library build() { + _addImports(); + _addExports(); + + // TODO(scheglov) import prefixes are shadowed by class members + + for (var unit in units) { + _addUnit(unit); + } + declaredNodes.sort(DependencyNode.compare); + + return Library(uri, imports, exports, declaredNodes); + } + + void _addClassOrMixin(ClassOrMixinDeclaration node) { + var hasConstConstructor = node.members.any( + (m) => m is ConstructorDeclaration && m.constKeyword != null, + ); + + List<DependencyNode> classTypeParameters; + if (node.typeParameters != null) { + classTypeParameters = <DependencyNode>[]; + for (var typeParameter in node.typeParameters.typeParameters) { + classTypeParameters.add(DependencyNode( + DependencyName(uri, typeParameter.name.name), + DependencyNodeKind.TYPE_PARAMETER, + _computeApiDependencies( + _computeNodeTokenSignature(typeParameter), + typeParameter, + ), + DependencyNodeDependencies.none, + )); + } + classTypeParameters.sort(DependencyNode.compare); + } + + var classMembers = <DependencyNode>[]; + var hasConstructor = false; + for (var member in node.members) { + if (member is ConstructorDeclaration) { + hasConstructor = true; + _addConstructor(classMembers, member); + } else if (member is FieldDeclaration) { + _addVariables( + classMembers, + member.metadata, + member.fields, + hasConstConstructor, + ); + } else if (member is MethodDeclaration) { + _addMethod(classMembers, member); + } else { + throw UnimplementedError('(${member.runtimeType}) $member'); + } + } + + if (!hasConstructor && node is ClassDeclaration) { + classMembers.add(DependencyNode( + DependencyName(uri, ''), + DependencyNodeKind.CONSTRUCTOR, + DependencyNodeDependencies.none, + DependencyNodeDependencies.none, + )); + } + + var classTokenSignature = _computeTokenSignature( + node.beginToken, + node.leftBracket, + ); + // TODO(scheglov) add library URI + + var classNode = DependencyNode( + DependencyName(uri, node.name.name), + node is MixinDeclaration + ? DependencyNodeKind.MIXIN + : DependencyNodeKind.CLASS, + _computeApiDependencies(classTokenSignature, node), + DependencyNodeDependencies.none, + classTypeParameters: classTypeParameters, + ); + + classMembers.sort(DependencyNode.compare); + classNode.setClassMembers(classMembers); + + declaredNodes.add(classNode); + } + + void _addClassTypeAlias(ClassTypeAlias node) { + var tokenSignature = _computeNodeTokenSignature(node); + declaredNodes.add(DependencyNode( + DependencyName(uri, node.name.name), + DependencyNodeKind.CLASS_TYPE_ALIAS, + _computeApiDependencies(tokenSignature, node), + DependencyNodeDependencies.none, + )); + } + + void _addConstructor( + List<DependencyNode> classMembers, ConstructorDeclaration node) { + var signature = ApiSignature(); + _appendMetadataTokens(signature, node.metadata); + _appendFormalParametersTokens(signature, node.parameters); + var tokenSignature = signature.toByteList(); + + classMembers.add(DependencyNode( + DependencyName(uri, node.name?.name ?? ''), + DependencyNodeKind.CONSTRUCTOR, + _computeApiDependencies(tokenSignature, node), + DependencyNodeDependencies.none, + )); + } + + void _addEnum(EnumDeclaration node) { + var classMembers = <DependencyNode>[]; + for (var constant in node.constants) { + classMembers.add(DependencyNode( + DependencyName(uri, constant.name.name), + DependencyNodeKind.GETTER, + DependencyNodeDependencies.none, + DependencyNodeDependencies.none, + )); + } + classMembers.add(DependencyNode( + DependencyName(uri, 'index'), + DependencyNodeKind.GETTER, + DependencyNodeDependencies.none, + DependencyNodeDependencies.none, + )); + classMembers.add(DependencyNode( + DependencyName(uri, 'values'), + DependencyNodeKind.GETTER, + DependencyNodeDependencies.none, + DependencyNodeDependencies.none, + )); + classMembers.sort(DependencyNode.compare); + + var enumNode = DependencyNode( + DependencyName(uri, node.name.name), + DependencyNodeKind.ENUM, + DependencyNodeDependencies.none, + DependencyNodeDependencies.none, + ); + enumNode.setClassMembers(classMembers); + + declaredNodes.add(enumNode); + } + + /// Fill [exports] with information about exports. + void _addExports() { + for (var directive in units.first.directives) { + if (directive is ExportDirective) { + var refUri = directive.uri.stringValue; + var importUri = uri.resolve(refUri); + var combinators = _getCombinators(directive); + exports.add(Export(importUri, combinators)); + } + } + } + + void _addFunction(FunctionDeclaration node) { + var functionExpression = node.functionExpression; + + var signature = ApiSignature(); + _appendMetadataTokens(signature, node.metadata); + _appendNodeTokens(signature, node.returnType); + _appendNodeTokens(signature, functionExpression.typeParameters); + _appendFormalParametersTokens(signature, functionExpression.parameters); + var tokenSignature = signature.toByteList(); + + var rawName = node.name.name; + var name = DependencyName(uri, node.isSetter ? '$rawName=' : rawName); + + DependencyNodeKind kind; + if (node.isGetter) { + kind = DependencyNodeKind.GETTER; + } else if (node.isSetter) { + kind = DependencyNodeKind.SETTER; + } else { + kind = DependencyNodeKind.FUNCTION; + } + + referenceCollector.appendTypeAnnotation(node.returnType); + referenceCollector.appendFormalParameters( + node.functionExpression.parameters, + ); + var api = referenceCollector.finish(tokenSignature); + + var bodyNode = node.functionExpression.body; + var implTokenSignature = _computeNodeTokenSignature(bodyNode); + referenceCollector.appendFunctionBody(bodyNode); + var impl = referenceCollector.finish(implTokenSignature); + + declaredNodes.add(DependencyNode(name, kind, api, impl)); + } + + void _addFunctionTypeAlias(FunctionTypeAlias node) { + var signature = ApiSignature(); + _appendMetadataTokens(signature, node.metadata); + _appendNodeTokens(signature, node.typeParameters); + _appendNodeTokens(signature, node.returnType); + _appendFormalParametersTokens(signature, node.parameters); + var tokenSignature = signature.toByteList(); + + declaredNodes.add(DependencyNode( + DependencyName(uri, node.name.name), + DependencyNodeKind.FUNCTION_TYPE_ALIAS, + _computeApiDependencies(tokenSignature, node), + DependencyNodeDependencies.none, + )); + } + + void _addGenericTypeAlias(GenericTypeAlias node) { + var functionType = node.functionType; + + var signature = ApiSignature(); + _appendMetadataTokens(signature, node.metadata); + _appendNodeTokens(signature, node.typeParameters); + _appendNodeTokens(signature, functionType.returnType); + _appendNodeTokens(signature, functionType.typeParameters); + _appendFormalParametersTokens(signature, functionType.parameters); + var tokenSignature = signature.toByteList(); + + declaredNodes.add(DependencyNode( + DependencyName(uri, node.name.name), + DependencyNodeKind.GENERIC_TYPE_ALIAS, + _computeApiDependencies(tokenSignature, node), + DependencyNodeDependencies.none, + )); + } + + /// Fill [imports] with information about imports. + void _addImports() { + var hasDartCoreImport = false; + for (var directive in units.first.directives) { + if (directive is ImportDirective) { + var refUri = directive.uri.stringValue; + var importUri = uri.resolve(refUri); + + if (importUri.toString() == 'dart:core') { + hasDartCoreImport = true; + } + + var combinators = _getCombinators(directive); + + imports.add(Import(importUri, directive.prefix?.name, combinators)); + + if (directive.prefix != null) { + referenceCollector.addImportPrefix(directive.prefix.name); + } + } + } + + if (!hasDartCoreImport) { + imports.add(Import(Uri.parse('dart:core'), null, [])); + } + } + + void _addMethod(List<DependencyNode> classMembers, MethodDeclaration node) { + var signature = ApiSignature(); + _appendMetadataTokens(signature, node.metadata); + _appendNodeTokens(signature, node.returnType); + _appendNodeTokens(signature, node.typeParameters); + _appendFormalParametersTokens(signature, node.parameters); + var tokenSignature = signature.toByteList(); + + DependencyNodeKind kind; + if (node.isGetter) { + kind = DependencyNodeKind.GETTER; + } else if (node.isSetter) { + kind = DependencyNodeKind.SETTER; + } else { + kind = DependencyNodeKind.METHOD; + } + + referenceCollector.appendTypeAnnotation(node.returnType); + referenceCollector.appendFormalParameters(node.parameters); + var api = referenceCollector.finish(tokenSignature); + + var implTokenSignature = _computeNodeTokenSignature(node.body); + referenceCollector.appendFunctionBody(node.body); + var impl = referenceCollector.finish(implTokenSignature); + + classMembers.add( + DependencyNode(DependencyName(uri, node.name.name), kind, api, impl)); + } + + void _addUnit(CompilationUnit unit) { + for (var declaration in unit.declarations) { + if (declaration is ClassOrMixinDeclaration) { + _addClassOrMixin(declaration); + } else if (declaration is ClassTypeAlias) { + _addClassTypeAlias(declaration); + } else if (declaration is EnumDeclaration) { + _addEnum(declaration); + } else if (declaration is FunctionDeclaration) { + _addFunction(declaration); + } else if (declaration is FunctionTypeAlias) { + _addFunctionTypeAlias(declaration); + } else if (declaration is GenericTypeAlias) { + _addGenericTypeAlias(declaration); + } else if (declaration is TopLevelVariableDeclaration) { + _addVariables( + declaredNodes, + declaration.metadata, + declaration.variables, + false, + ); + } else { + throw UnimplementedError('(${declaration.runtimeType}) $declaration'); + } + } + } + + void _addVariables( + List<DependencyNode> variableNodes, + List<Annotation> metadata, + VariableDeclarationList variables, + bool appendInitializerToApi) { + if (variables.isConst || variables.type == null) { + appendInitializerToApi = true; + } + + for (var variable in variables.variables) { + var signature = ApiSignature(); + signature.addInt(variables.isConst ? 1 : 0); // const flag + _appendMetadataTokens(signature, metadata); + + _appendNodeTokens(signature, variables.type); + referenceCollector.appendTypeAnnotation(variables.type); + + if (appendInitializerToApi) { + _appendNodeTokens(signature, variable.initializer); + referenceCollector.appendExpression(variable.initializer); + } + + var tokenSignature = signature.toByteList(); + var api = referenceCollector.finish(tokenSignature); + + var rawName = variable.name.name; + variableNodes.add( + DependencyNode( + DependencyName(uri, rawName), + DependencyNodeKind.GETTER, + api, + DependencyNodeDependencies.none, + ), + ); + if (!variables.isConst && !variables.isFinal) { + variableNodes.add( + DependencyNode( + DependencyName(uri, '$rawName='), + DependencyNodeKind.SETTER, + api, + DependencyNodeDependencies.none, + ), + ); + } + } + } + + /// Append tokens of the given [parameters] to the [signature]. + static void _appendFormalParametersTokens( + ApiSignature signature, FormalParameterList parameters) { + if (parameters == null) return; + + for (var parameter in parameters.parameters) { + if (parameter.isRequired) { + signature.addInt(1); + } else if (parameter.isOptionalPositional) { + signature.addInt(2); + } else { + signature.addInt(3); + } + + // If a simple not named parameter, we don't need its name. + // We should be careful to include also annotations. + if (parameter is SimpleFormalParameter && parameter.type != null) { + _appendTokens( + signature, + parameter.beginToken, + parameter.type.endToken, + ); + continue; + } + + // We don't know anything better than adding the whole parameter. + _appendNodeTokens(signature, parameter); + } + } + + static void _appendMetadataTokens( + ApiSignature signature, List<Annotation> metadata) { + if (metadata != null) { + for (var annotation in metadata) { + _appendNodeTokens(signature, annotation); + } + } + } + + /// Append tokens of the given [node] to the [signature]. + static void _appendNodeTokens(ApiSignature signature, AstNode node) { + if (node != null) { + _appendTokens(signature, node.beginToken, node.endToken); + } + } + + /// Append tokens from [begin] to [end] (both including) to the [signature]. + static void _appendTokens(ApiSignature signature, Token begin, Token end) { + if (begin is CommentToken) { + begin = (begin as CommentToken).parent; + } + + Token token = begin; + while (token != null) { + signature.addString(token.lexeme); + + if (token == end) { + break; + } + + var nextToken = token.next; + if (nextToken == token) { + break; + } + + token = nextToken; + } + } + + /// TODO(scheglov) Replace all uses with [referenceCollector]. + static DependencyNodeDependencies _computeApiDependencies( + List<int> tokenSignature, AstNode node, + [AstNode node2]) { + List<String> importPrefixes = []; + List<String> unprefixedReferencedNames = []; + List<List<String>> importPrefixedReferencedNames = []; + return DependencyNodeDependencies( + tokenSignature, + unprefixedReferencedNames, + importPrefixes, + importPrefixedReferencedNames, + const [], + ); + } + + /// Return the signature for all tokens of the [node]. + static List<int> _computeNodeTokenSignature(AstNode node) { + if (node == null) { + return const <int>[]; + } + return _computeTokenSignature(node.beginToken, node.endToken); + } + + /// Return the signature for tokens from [begin] to [end] (both including). + static List<int> _computeTokenSignature(Token begin, Token end) { + var signature = ApiSignature(); + _appendTokens(signature, begin, end); + return signature.toByteList(); + } + + /// Return [Combinator]s for the given import or export [directive]. + static List<Combinator> _getCombinators(NamespaceDirective directive) { + var combinators = <Combinator>[]; + for (var combinator in directive.combinators) { + if (combinator is ShowCombinator) { + combinators.add( + Combinator( + true, + combinator.shownNames.map((id) => id.name).toList(), + ), + ); + } + if (combinator is HideCombinator) { + combinators.add( + Combinator( + false, + combinator.hiddenNames.map((id) => id.name).toList(), + ), + ); + } + } + return combinators; + } +}
diff --git a/pkg/analyzer/lib/src/dart/analysis/dependency/node.dart b/pkg/analyzer/lib/src/dart/analysis/dependency/node.dart new file mode 100644 index 0000000..e3de954 --- /dev/null +++ b/pkg/analyzer/lib/src/dart/analysis/dependency/node.dart
@@ -0,0 +1,248 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'dart:typed_data'; + +import 'package:analyzer/src/generated/utilities_general.dart'; +import 'package:convert/convert.dart'; + +/// The reference to a class member. +class ClassMemberReference { + /// The target class name. + /// + /// This is different from the class that actually turned out to define + /// the referenced member at the time of recording this reference. So, we + /// will notice added overrides in the target class, or anywhere in between. + final DependencyName target; + + /// Whether the explicit `super` was used as the target. + /// The [target] is the enclosing class. + final bool targetSuper; + + /// The name referenced in the [target]. + final String name; + + @override + final int hashCode; + + ClassMemberReference(this.target, this.targetSuper, this.name) + : hashCode = JenkinsSmiHash.hash2(target.hashCode, name.hashCode); + + @override + bool operator ==(other) { + return other is ClassMemberReference && + other.target == target && + other.targetSuper == targetSuper && + other.name == name; + } + + @override + String toString() { + return '($target, $name, super: $targetSuper)'; + } + + static int compare(ClassMemberReference first, ClassMemberReference second) { + var result = DependencyName.compare(first.target, second.target); + if (result != 0) return result; + + if (first.targetSuper && !second.targetSuper) return -1; + if (!first.targetSuper && second.targetSuper) return 1; + + return first.name.compareTo(second.name); + } +} + +/// A name qualified by a library URI. +class DependencyName { + /// The URI of the defining library. + /// Not `null`. + final Uri libraryUri; + + /// The name of this name object. + /// If the name starts with `_`, then the name is private. + /// Names of setters end with `=`. + final String name; + + /// Whether this name is private, and its [name] starts with `_`. + final bool isPrivate; + + /// The cached, pre-computed hash code. + @override + final int hashCode; + + factory DependencyName(Uri libraryUri, String name) { + var isPrivate = name.startsWith('_'); + var hashCode = JenkinsSmiHash.hash2(libraryUri.hashCode, name.hashCode); + return DependencyName._internal(libraryUri, name, isPrivate, hashCode); + } + + DependencyName._internal( + this.libraryUri, this.name, this.isPrivate, this.hashCode); + + @override + bool operator ==(Object other) { + return other is DependencyName && + other.hashCode == hashCode && + name == other.name && + libraryUri == other.libraryUri; + } + + /// Whether this name us accessible for the library with the given + /// [libraryUri], i.e. when the name is public, or is defined in a library + /// with the same URI. + bool isAccessibleFor(Uri libraryUri) { + return !isPrivate || this.libraryUri == libraryUri; + } + + @override + String toString() => '$libraryUri::$name'; + + /// Compare given names by their raw names. + /// + /// This method should be used only for sorting, it does not follow the + /// complete semantics of [==] and [hashCode]. + static int compare(DependencyName first, DependencyName second) { + return first.name.compareTo(second.name); + } +} + +/// A dependency node - anything that has a name, and can be referenced. +class DependencyNode { + /// The API or implementation signature used in [DependencyNodeDependencies] + /// as a marker that this node is changed, explicitly because its token + /// signature changed, or implicitly - because it references a changed node. + static final changedSignature = Uint8List.fromList([0xDE, 0xAD, 0xBE, 0xEF]); + + final DependencyName name; + final DependencyNodeKind kind; + + /// Dependencies that affect the API of the node, so affect API or + /// implementation dependencies of the nodes that use this node. + final DependencyNodeDependencies api; + + /// Additional (to the [api]) dependencies that affect only the + /// "implementation" of the node, e.g. the body of a method, but are not + /// visible outside of the node, and so don't affect any other nodes. + final DependencyNodeDependencies impl; + + /// If the node is a class member, the node of the enclosing class. + /// Otherwise `null`. + final DependencyNode enclosingClass; + + /// If the node is a class, the nodes of its type parameters. + /// Otherwise `null`. + final List<DependencyNode> classTypeParameters; + + /// If the node is a class, the sorted list of members in this class. + /// Otherwise `null`. + List<DependencyNode> classMembers; + + DependencyNode( + this.name, + this.kind, + this.api, + this.impl, { + this.enclosingClass, + this.classTypeParameters, + }); + + /// Return the node that can be referenced by the given [name] from the + /// library with the given [libraryUri]. + DependencyNode getClassMember(Uri libraryUri, String name) { + // TODO(scheglov) The list is sorted, use this fact to search faster. + // TODO(scheglov) Collect superclass members here or outside. + for (var i = 0; i < classMembers.length; ++i) { + var member = classMembers[i]; + var memberName = member.name; + if (memberName.name == name && memberName.isAccessibleFor(libraryUri)) { + return member; + } + } + return null; + } + + /// Set new class members for this class. + void setClassMembers(List<DependencyNode> newClassMembers) { + classMembers = newClassMembers; + } + + @override + String toString() { + if (enclosingClass != null) { + return '$enclosingClass::${name.name}'; + } + return name.toString(); + } + + /// Compare given nodes by their names. + static int compare(DependencyNode first, DependencyNode second) { + return DependencyName.compare(first.name, second.name); + } +} + +/// The dependencies of the API or implementation portion of a node. +class DependencyNodeDependencies { + static final none = DependencyNodeDependencies([], [], [], [], []); + + /// The token signature of this portion of the node. It depends on all + /// tokens that might affect the node API or implementation resolution. + final List<int> tokenSignature; + + /// The names that appear unprefixed in this portion of the node, and are + /// not defined locally in the node. Locally defined names themselves + /// depend on some non-local nodes, which will also recorded here. + /// + /// This list is sorted. + final List<String> unprefixedReferencedNames; + + /// The names of import prefixes used to reference names in this node. + /// + /// This list is sorted. + final List<String> importPrefixes; + + /// The names referenced by this node with the import prefix at the + /// corresponding index in [importPrefixes]. + /// + /// This list is sorted. + final List<List<String>> importPrefixedReferencedNames; + + /// The class members referenced in this portion of the node. + /// + /// This list is sorted. + final List<ClassMemberReference> classMemberReferences; + + /// All referenced nodes, computed from [unprefixedReferencedNames], + /// [importPrefixedReferencedNames], and [classMemberReferences]. + List<DependencyNode> referencedNodes; + + /// The transitive signature of this portion of the node, computed using + /// the [tokenSignature] of this node, and API signatures of the + /// [referencedNodes]. + List<int> transitiveSignature; + + DependencyNodeDependencies( + this.tokenSignature, + this.unprefixedReferencedNames, + this.importPrefixes, + this.importPrefixedReferencedNames, + this.classMemberReferences); + + String get tokenSignatureHex => hex.encode(tokenSignature); +} + +/// Kinds of nodes. +enum DependencyNodeKind { + CLASS, + CLASS_TYPE_ALIAS, + CONSTRUCTOR, + ENUM, + FUNCTION, + FUNCTION_TYPE_ALIAS, + GENERIC_TYPE_ALIAS, + GETTER, + METHOD, + MIXIN, + SETTER, + TYPE_PARAMETER, +}
diff --git a/pkg/analyzer/lib/src/dart/analysis/driver.dart b/pkg/analyzer/lib/src/dart/analysis/driver.dart index 6f2d3ec..a1cc939 100644 --- a/pkg/analyzer/lib/src/dart/analysis/driver.dart +++ b/pkg/analyzer/lib/src/dart/analysis/driver.dart
@@ -6,13 +6,12 @@ import 'dart:collection'; import 'dart:typed_data'; +import 'package:analyzer/dart/analysis/analysis_context.dart' as api; import 'package:analyzer/dart/analysis/declared_variables.dart'; -import 'package:analyzer/dart/analysis/results.dart' as results; import 'package:analyzer/dart/analysis/results.dart'; import 'package:analyzer/dart/analysis/session.dart'; import 'package:analyzer/dart/ast/ast.dart'; -import 'package:analyzer/dart/element/element.dart' - show CompilationUnitElement, LibraryElement; +import 'package:analyzer/dart/element/element.dart' show LibraryElement; import 'package:analyzer/error/error.dart'; import 'package:analyzer/error/listener.dart'; import 'package:analyzer/exception/exception.dart'; @@ -145,11 +144,6 @@ AnalysisOptionsImpl _analysisOptions; /** - * The optional SDK bundle, used when the client cannot read SDK files. - */ - final PackageBundle _sdkBundle; - - /** * The [SourceFactory] is used to resolve URIs to paths and restore URIs * from file paths. */ @@ -166,16 +160,21 @@ final ContextRoot contextRoot; /** + * The analysis context that created this driver / session. + */ + api.AnalysisContext analysisContext; + + /** * The salt to mix into all hashes used as keys for unlinked data. */ final Uint32List _unlinkedSalt = - new Uint32List(1 + AnalysisOptionsImpl.unlinkedSignatureLength); + new Uint32List(2 + AnalysisOptionsImpl.unlinkedSignatureLength); /** * The salt to mix into all hashes used as keys for linked data. */ final Uint32List _linkedSalt = - new Uint32List(1 + AnalysisOptions.signatureLength); + new Uint32List(2 + AnalysisOptions.signatureLength); /** * The set of priority files, that should be analyzed sooner. @@ -186,7 +185,7 @@ * The mapping from the files for which analysis was requested using * [getResult] to the [Completer]s to report the result. */ - final _requestedFiles = <String, List<Completer<AnalysisResult>>>{}; + final _requestedFiles = <String, List<Completer<ResolvedUnitResult>>>{}; /** * The mapping from the files for which analysis was requested using @@ -257,7 +256,7 @@ * [getResult], and which were found to be parts without known libraries, * to the [Completer]s to report the result. */ - final _requestedParts = <String, List<Completer<AnalysisResult>>>{}; + final _requestedParts = <String, List<Completer<ResolvedUnitResult>>>{}; /** * The set of part files that are currently scheduled for analysis. @@ -267,12 +266,12 @@ /** * The controller for the [results] stream. */ - final _resultController = new StreamController<AnalysisResult>(); + final _resultController = new StreamController<ResolvedUnitResult>(); /** * The stream that will be written to when analysis results are produced. */ - Stream<AnalysisResult> _onResults; + Stream<ResolvedUnitResult> _onResults; /** * Resolution signatures of the most recently produced results for files. @@ -282,7 +281,7 @@ /** * Cached results for [_priorityFiles]. */ - final Map<String, AnalysisResult> _priorityResults = {}; + final Map<String, ResolvedUnitResult> _priorityResults = {}; /** * The controller for the [exceptions] stream. @@ -323,6 +322,11 @@ final bool disableChangesAndCacheAllResults; /** + * Whether resolved units should be indexed. + */ + final bool enableIndex; + + /** * The cache to use with [disableChangesAndCacheAllResults]. */ final Map<String, AnalysisResult> _allCachedResults = {}; @@ -333,6 +337,13 @@ AnalysisSessionImpl _currentSession; /** + * The current library context, consistent with the [_currentSession]. + * + * TODO(scheglov) We probably should tie it into the session. + */ + LibraryContext _libraryContext; + + /** * Create a new instance of [AnalysisDriver]. * * The given [SourceFactory] is cloned to ensure that it does not contain a @@ -347,12 +358,11 @@ this.contextRoot, SourceFactory sourceFactory, this._analysisOptions, - {PackageBundle sdkBundle, - this.disableChangesAndCacheAllResults: false, + {this.disableChangesAndCacheAllResults: false, + this.enableIndex: false, SummaryDataStore externalSummaries}) : _logger = logger, _sourceFactory = sourceFactory.clone(), - _sdkBundle = sdkBundle, _externalSummaries = externalSummaries { _createNewSession(); _onResults = _resultController.stream.asBroadcastStream(); @@ -456,7 +466,7 @@ * Results might be produced even for files that have never been added * using [addFile], for example when [getResult] was called for a file. */ - Stream<AnalysisResult> get results => _onResults; + Stream<ResolvedUnitResult> get results => _onResults; /** * Return the search support for the driver. @@ -528,6 +538,7 @@ _unitElementRequestedParts.isNotEmpty) { return AnalysisDriverPriority.general; } + _libraryContext = null; return AnalysisDriverPriority.nothing; } @@ -539,13 +550,7 @@ } if (AnalysisEngine.isDartFileName(path)) { _fileTracker.addFile(path); - // If the file is known, it has already been read, even if it did not - // exist. Now we are notified that the file exists, so we need to - // re-read it and make sure that we invalidate signature of the files - // that reference it. - if (_fsState.knownFilePaths.contains(path)) { - _changeFile(path); - } + _changeFile(path); } } @@ -613,17 +618,17 @@ } /** - * Return the cached [AnalysisResult] for the Dart file with the given [path]. - * If there is no cached result, return `null`. Usually only results of - * priority files are cached. + * Return the cached [ResolvedUnitResult] for the Dart file with the given + * [path]. If there is no cached result, return `null`. Usually only results + * of priority files are cached. * * The [path] must be absolute and normalized. * * The [path] can be any file - explicitly or implicitly analyzed, or neither. */ - AnalysisResult getCachedResult(String path) { + ResolvedUnitResult getCachedResult(String path) { _throwIfNotAbsolutePath(path); - AnalysisResult result = _priorityResults[path]; + ResolvedUnitResult result = _priorityResults[path]; if (disableChangesAndCacheAllResults) { result ??= _allCachedResults[path]; } @@ -647,13 +652,7 @@ // Ask the analysis result without unit, so return cached errors. // If no cached analysis result, it will be computed. - AnalysisResult analysisResult = await _computeAnalysisResult(path); - - // Check for asynchronous changes during computing the result. - await _runTestAsyncWorkDuringAnalysis(path); - if (_fileTracker.hasChangedFiles) { - analysisResult = null; - } + ResolvedUnitResult analysisResult = _computeAnalysisResult(path); // If not computed yet, because a part file without a known library, // we have to compute the full analysis result, with the unit. @@ -662,7 +661,7 @@ return null; } - return new ErrorsResult(currentSession, path, analysisResult.uri, + return new ErrorsResultImpl(currentSession, path, analysisResult.uri, analysisResult.lineInfo, analysisResult.isPart, analysisResult.errors); } @@ -698,7 +697,7 @@ FileResult getFileSync(String path) { _throwIfNotAbsolutePath(path); FileState file = _fileTracker.verifyApiSignature(path); - return new FileResult( + return new FileResultImpl( _currentSession, path, file.uri, file.lineInfo, file.isPart); } @@ -709,6 +708,9 @@ */ Future<AnalysisDriverUnitIndex> getIndex(String path) { _throwIfNotAbsolutePath(path); + if (!enableIndex) { + throw new ArgumentError('Indexing is not enabled.'); + } if (!_fsState.hasUri(path)) { return new Future.value(); } @@ -724,20 +726,78 @@ * Return a [Future] that completes with the [LibraryElement] for the given * [uri], which is either resynthesized from the provided external summary * store, or built for a file to which the given [uri] is resolved. + * + * Throw [ArgumentError] if the [uri] corresponds to a part. */ Future<LibraryElement> getLibraryByUri(String uri) async { - // TODO(brianwilkerson) Determine whether this await is necessary. - await null; - if (_externalSummaries != null && _externalSummaries.hasUnlinkedUnit(uri)) { - return LibraryContext.resynthesizeLibraryElement(analysisOptions, - declaredVariables, sourceFactory, _externalSummaries, uri); + var uriObj = Uri.parse(uri); + var file = _fsState.getFileForUri(uriObj); + + if (file.isExternalLibrary) { + return _createLibraryContext(file).getLibraryElement(file); } - Source source = sourceFactory.resolveUri(null, uri); - UnitElementResult unitResult = await getUnitElement(source.fullName); + + if (file.isPart) { + throw ArgumentError('$uri is not a library.'); + } + + UnitElementResult unitResult = await getUnitElement(file.path); return unitResult.element.library; } /** + * Return a [ParsedLibraryResult] for the library with the given [path]. + * + * Throw [ArgumentError] if the given [path] is not the defining compilation + * unit for a library (that is, is a part of a library). + * + * The [path] must be absolute and normalized. + */ + ParsedLibraryResult getParsedLibrary(String path) { + FileState file = _fsState.getFileForPath(path); + + if (file.isExternalLibrary) { + return ParsedLibraryResultImpl.external(currentSession, file.uri); + } + + if (file.isPart) { + throw ArgumentError('Is a part: $path'); + } + + var units = <ParsedUnitResult>[]; + for (var unitFile in file.libraryFiles) { + var unitPath = unitFile.path; + if (unitPath != null) { + var unitResult = parseFileSync(unitPath); + units.add(unitResult); + } + } + + return ParsedLibraryResultImpl(currentSession, path, file.uri, units); + } + + /** + * Return a [ParsedLibraryResult] for the library with the given [uri]. + * + * Throw [ArgumentError] if the given [uri] is not the defining compilation + * unit for a library (that is, is a part of a library). + */ + ParsedLibraryResult getParsedLibraryByUri(Uri uri) { + FileState file = _fsState.getFileForUri(uri); + + if (file.isExternalLibrary) { + return ParsedLibraryResultImpl.external(currentSession, file.uri); + } + + if (file.isPart) { + throw ArgumentError('Is a part: $uri'); + } + + // The file is a local file, we can get the result. + return getParsedLibrary(file.path); + } + + /** * Return a [Future] that completes with a [ResolvedLibraryResult] for the * Dart library file with the given [path]. If the file is not a Dart file * or cannot be analyzed, the [Future] completes with `null`. @@ -823,7 +883,7 @@ } /** - * Return a [Future] that completes with a [AnalysisResult] for the Dart + * Return a [Future] that completes with a [ResolvedUnitResult] for the Dart * file with the given [path]. If the file is not a Dart file or cannot * be analyzed, the [Future] completes with `null`. * @@ -841,7 +901,7 @@ * of the files previously reported using [changeFile]), prior to the next * time the analysis state transitions to "idle". */ - Future<AnalysisResult> getResult(String path, + Future<ResolvedUnitResult> getResult(String path, {bool sendCachedToStream: false}) { _throwIfNotAbsolutePath(path); if (!_fsState.hasUri(path)) { @@ -850,7 +910,7 @@ // Return the cached result. { - AnalysisResult result = getCachedResult(path); + ResolvedUnitResult result = getCachedResult(path); if (result != null) { if (sendCachedToStream) { _resultController.add(result); @@ -860,9 +920,9 @@ } // Schedule analysis. - var completer = new Completer<AnalysisResult>(); + var completer = new Completer<ResolvedUnitResult>(); _requestedFiles - .putIfAbsent(path, () => <Completer<AnalysisResult>>[]) + .putIfAbsent(path, () => <Completer<ResolvedUnitResult>>[]) .add(completer); _scheduler.notify(this); return completer.future; @@ -959,17 +1019,11 @@ * not a part, so it must be a library. */ bool isLibraryByUri(Uri uri) { - if (_externalSummaries != null) { - var uriStr = uri.toString(); - if (_externalSummaries.unlinkedMap[uriStr] != null) { - return _externalSummaries.linkedMap.containsKey(uriStr); - } - } return !_fsState.getFileForUri(uri).isPart; } /** - * Return a [Future] that completes with a [ParseResult] for the file + * Return a [Future] that completes with a [ParsedUnitResult] for the file * with the given [path]. * * The [path] must be absolute and normalized. @@ -980,14 +1034,14 @@ * produced through the [results] stream (just because it is not a fully * resolved unit). */ - Future<ParseResult> parseFile(String path) async { + Future<ParsedUnitResult> parseFile(String path) async { // TODO(brianwilkerson) Determine whether this await is necessary. await null; return parseFileSync(path); } /** - * Return a [ParseResult] for the file with the given [path]. + * Return a [ParsedUnitResult] for the file with the given [path]. * * The [path] must be absolute and normalized. * @@ -997,13 +1051,13 @@ * produced through the [results] stream (just because it is not a fully * resolved unit). */ - ParseResult parseFileSync(String path) { + ParsedUnitResult parseFileSync(String path) { _throwIfNotAbsolutePath(path); FileState file = _fileTracker.verifyApiSignature(path); RecordingErrorListener listener = new RecordingErrorListener(); CompilationUnit unit = file.parse(listener); - return new ParseResult(currentSession, file.path, file.uri, file.content, - file.lineInfo, file.isPart, unit, listener.errors); + return new ParsedUnitResultImpl(currentSession, file.path, file.uri, + file.content, file.lineInfo, file.isPart, unit, listener.errors); } @override @@ -1018,13 +1072,7 @@ if (_requestedFiles.isNotEmpty) { String path = _requestedFiles.keys.first; try { - AnalysisResult result = - await _computeAnalysisResult(path, withUnit: true); - // Check for asynchronous changes during computing the result. - await _runTestAsyncWorkDuringAnalysis(path); - if (_fileTracker.hasChangedFiles) { - return; - } + AnalysisResult result = _computeAnalysisResult(path, withUnit: true); // If a part without a library, delay its analysis. if (result == null) { _requestedParts @@ -1067,7 +1115,7 @@ // Process an index request. if (_indexRequestedFiles.isNotEmpty) { String path = _indexRequestedFiles.keys.first; - AnalysisDriverUnitIndex index = await _computeIndex(path); + AnalysisDriverUnitIndex index = _computeIndex(path); _indexRequestedFiles.remove(path).forEach((completer) { completer.complete(index); }); @@ -1094,7 +1142,7 @@ // Process a unit element request. if (_unitElementRequestedFiles.isNotEmpty) { String path = _unitElementRequestedFiles.keys.first; - UnitElementResult result = await _computeUnitElement(path); + UnitElementResult result = _computeUnitElement(path); var completers = _unitElementRequestedFiles.remove(path); if (result != null) { completers.forEach((completer) { @@ -1152,8 +1200,7 @@ if (_fileTracker.isFilePending(path)) { try { AnalysisResult result = - await _computeAnalysisResult(path, withUnit: true); - await _runTestAsyncWorkDuringAnalysis(path); + _computeAnalysisResult(path, withUnit: true); if (result == null) { _partsToAnalyze.add(path); } else { @@ -1173,9 +1220,8 @@ if (_fileTracker.hasPendingFiles) { String path = _fileTracker.anyPendingFile; try { - AnalysisResult result = await _computeAnalysisResult(path, + AnalysisResult result = _computeAnalysisResult(path, withUnit: false, skipIfSameSignature: true); - await _runTestAsyncWorkDuringAnalysis(path); if (result == null) { _partsToAnalyze.add(path); } else if (result == AnalysisResult._UNCHANGED) { @@ -1197,12 +1243,8 @@ if (_requestedParts.isNotEmpty) { String path = _requestedParts.keys.first; try { - AnalysisResult result = await _computeAnalysisResult(path, + AnalysisResult result = _computeAnalysisResult(path, withUnit: true, asIsIfPartWithoutLibrary: true); - // Check for asynchronous changes during computing the result. - if (_fileTracker.hasChangedFiles) { - return; - } // Notify the completers. _requestedParts.remove(path).forEach((completer) { completer.complete(result); @@ -1224,7 +1266,7 @@ String path = _partsToAnalyze.first; _partsToAnalyze.remove(path); try { - AnalysisResult result = await _computeAnalysisResult(path, + AnalysisResult result = _computeAnalysisResult(path, withUnit: _priorityFiles.contains(path), asIsIfPartWithoutLibrary: true); _resultController.add(result); @@ -1237,7 +1279,7 @@ // Process a unit element signature request for a part. if (_unitElementSignatureParts.isNotEmpty) { String path = _unitElementSignatureParts.keys.first; - var signature = + String signature = _computeUnitElementSignature(path, asIsIfPartWithoutLibrary: true); _unitElementSignatureParts.remove(path).forEach((completer) { completer.complete(signature); @@ -1249,7 +1291,7 @@ if (_unitElementRequestedParts.isNotEmpty) { String path = _unitElementRequestedParts.keys.first; UnitElementResult result = - await _computeUnitElement(path, asIsIfPartWithoutLibrary: true); + _computeUnitElement(path, asIsIfPartWithoutLibrary: true); _unitElementRequestedParts.remove(path).forEach((completer) { completer.complete(result); }); @@ -1270,6 +1312,7 @@ _throwIfNotAbsolutePath(path); _throwIfChangesAreNotAllowed(); _fileTracker.removeFile(path); + _libraryContext = null; _priorityResults.clear(); } @@ -1277,8 +1320,15 @@ * Implementation for [changeFile]. */ void _changeFile(String path) { - _fileTracker.changeFile(path); - _priorityResults.clear(); + // If the file is known, it has already been read, even if it din't exist. + // Now we are notified that the file changed (just changed or added), so we + // need to re-read it and make sure that we invalidate signature of the + // files that reference it. + if (_fsState.knownFilePaths.contains(path)) { + _fileTracker.changeFile(path); + _libraryContext = null; + _priorityResults.clear(); + } } /** @@ -1287,6 +1337,7 @@ */ void _changeHook() { _createNewSession(); + _libraryContext = null; _priorityResults.clear(); _scheduler.notify(this); } @@ -1306,12 +1357,10 @@ * the resolved signature of the file in its library is the same as the one * that was the most recently produced to the client. */ - Future<AnalysisResult> _computeAnalysisResult(String path, + AnalysisResult _computeAnalysisResult(String path, {bool withUnit: false, bool asIsIfPartWithoutLibrary: false, - bool skipIfSameSignature: false}) async { - // TODO(brianwilkerson) Determine whether this await is necessary. - await null; + bool skipIfSameSignature: false}) { FileState file = _fsState.getFileForPath(path); // Prepare the library - the file itself, or the known library. @@ -1347,67 +1396,60 @@ } // We need the fully resolved unit, or the result is not cached. - return _logger.runAsync('Compute analysis result for $path', () async { - // TODO(brianwilkerson) Determine whether this await is necessary. - await null; + return _logger.run('Compute analysis result for $path', () { try { - LibraryContext libraryContext; - try { - _testView.numOfAnalyzedLibraries++; + _testView.numOfAnalyzedLibraries++; - if (!_fsState.getFileForUri(Uri.parse('dart:core')).exists) { - return _newMissingDartLibraryResult(file, 'dart:core'); - } - if (!_fsState.getFileForUri(Uri.parse('dart:async')).exists) { - return _newMissingDartLibraryResult(file, 'dart:async'); - } - libraryContext = _createLibraryContext(library); - - LibraryAnalyzer analyzer = new LibraryAnalyzer( - analysisOptions, - declaredVariables, - sourceFactory, - libraryContext.isLibraryUri, - libraryContext.analysisContext, - libraryContext.resynthesizer, - library, - _resourceProvider); - Map<FileState, UnitAnalysisResult> results = analyzer.analyze(); - - List<int> bytes; - CompilationUnit resolvedUnit; - for (FileState unitFile in results.keys) { - UnitAnalysisResult unitResult = results[unitFile]; - List<int> unitBytes = - _serializeResolvedUnit(unitResult.unit, unitResult.errors); - String unitSignature = _getResolvedUnitSignature(library, unitFile); - String unitKey = _getResolvedUnitKey(unitSignature); - _byteStore.put(unitKey, unitBytes); - if (unitFile == file) { - bytes = unitBytes; - resolvedUnit = unitResult.unit; - } - if (disableChangesAndCacheAllResults) { - AnalysisResult result = _getAnalysisResultFromBytes( - unitFile, unitSignature, unitBytes, - content: unitFile.content, resolvedUnit: unitResult.unit); - _allCachedResults[unitFile.path] = result; - } - } - - // Return the result, full or partial. - _logger.writeln('Computed new analysis result.'); - AnalysisResult result = _getAnalysisResultFromBytes( - file, signature, bytes, - content: withUnit ? file.content : null, - resolvedUnit: withUnit ? resolvedUnit : null); - if (withUnit && _priorityFiles.contains(path)) { - _priorityResults[path] = result; - } - return result; - } finally { - libraryContext?.dispose(); + if (!_fsState.getFileForUri(Uri.parse('dart:core')).exists) { + return _newMissingDartLibraryResult(file, 'dart:core'); } + if (!_fsState.getFileForUri(Uri.parse('dart:async')).exists) { + return _newMissingDartLibraryResult(file, 'dart:async'); + } + var libraryContext = _createLibraryContext(library); + + LibraryAnalyzer analyzer = new LibraryAnalyzer( + analysisOptions, + declaredVariables, + sourceFactory, + libraryContext.isLibraryUri, + libraryContext.analysisContext, + libraryContext.resynthesizer, + libraryContext.inheritanceManager, + library); + Map<FileState, UnitAnalysisResult> results = analyzer.analyze(); + + List<int> bytes; + CompilationUnit resolvedUnit; + for (FileState unitFile in results.keys) { + UnitAnalysisResult unitResult = results[unitFile]; + List<int> unitBytes = + _serializeResolvedUnit(unitResult.unit, unitResult.errors); + String unitSignature = _getResolvedUnitSignature(library, unitFile); + String unitKey = _getResolvedUnitKey(unitSignature); + _byteStore.put(unitKey, unitBytes); + if (unitFile == file) { + bytes = unitBytes; + resolvedUnit = unitResult.unit; + } + if (disableChangesAndCacheAllResults) { + AnalysisResult result = _getAnalysisResultFromBytes( + unitFile, unitSignature, unitBytes, + content: unitFile.content, resolvedUnit: unitResult.unit); + _allCachedResults[unitFile.path] = result; + } + } + + // Return the result, full or partial. + _logger.writeln('Computed new analysis result.'); + AnalysisResult result = _getAnalysisResultFromBytes( + file, signature, bytes, + content: withUnit ? file.content : null, + resolvedUnit: withUnit ? resolvedUnit : null); + if (withUnit && _priorityFiles.contains(path)) { + _priorityResults[path] = result; + } + return result; } catch (exception, stackTrace) { String contextKey = _storeExceptionContext(path, library, exception, stackTrace); @@ -1416,10 +1458,8 @@ }); } - Future<AnalysisDriverUnitIndex> _computeIndex(String path) async { - // TODO(brianwilkerson) Determine whether this await is necessary. - await null; - AnalysisResult analysisResult = await _computeAnalysisResult(path, + AnalysisDriverUnitIndex _computeIndex(String path) { + AnalysisResult analysisResult = _computeAnalysisResult(path, withUnit: false, asIsIfPartWithoutLibrary: true); return analysisResult._index; } @@ -1442,8 +1482,8 @@ libraryContext.isLibraryUri, libraryContext.analysisContext, libraryContext.resynthesizer, - library, - _resourceProvider); + libraryContext.inheritanceManager, + library); Map<FileState, UnitAnalysisResult> unitResults = analyzer.analyze(); var resolvedUnits = <ResolvedUnitResult>[]; @@ -1452,7 +1492,7 @@ var unitResult = unitResults[unitFile]; resolvedUnits.add( new AnalysisResult( - this, + currentSession, _sourceFactory, unitFile.path, unitFile.uri, @@ -1474,16 +1514,14 @@ library.path, library.uri, resolvedUnits.first.libraryElement, - libraryContext.analysisContext.typeProvider, + libraryContext.typeProvider, resolvedUnits, ); }); } - Future<UnitElementResult> _computeUnitElement(String path, - {bool asIsIfPartWithoutLibrary: false}) async { - // TODO(brianwilkerson) Determine whether this await is necessary. - await null; + UnitElementResult _computeUnitElement(String path, + {bool asIsIfPartWithoutLibrary: false}) { FileState file = _fsState.getFileForPath(path); // Prepare the library - the file itself, or the known library. @@ -1496,16 +1534,10 @@ } } - LibraryContext libraryContext = _createLibraryContext(library); - try { - CompilationUnitElement element = - libraryContext.computeUnitElement(library.source, file.source); - String signature = library.transitiveSignature; - return new UnitElementResult( - currentSession, path, file.uri, signature, element); - } finally { - libraryContext.dispose(); - } + var libraryContext = _createLibraryContext(library); + var element = libraryContext.computeUnitElement(library, file); + return new UnitElementResultImpl( + currentSession, path, file.uri, library.transitiveSignature, element); } String _computeUnitElementSignature(String path, @@ -1551,17 +1583,28 @@ * Return the context in which the [library] should be analyzed. */ LibraryContext _createLibraryContext(FileState library) { - _testView.numOfCreatedLibraryContexts++; - return new LibraryContext.forSingleLibrary( - library, - _logger, - _sdkBundle, - _byteStore, - _analysisOptions, - declaredVariables, - _sourceFactory, - _externalSummaries, - fsState); + if (_libraryContext != null) { + if (_libraryContext.pack()) { + _libraryContext = null; + } + } + + if (_libraryContext == null) { + _libraryContext = new LibraryContext( + session: currentSession, + logger: _logger, + fsState: fsState, + byteStore: _byteStore, + analysisOptions: _analysisOptions, + declaredVariables: declaredVariables, + sourceFactory: _sourceFactory, + externalSummaries: _externalSummaries, + targetLibrary: library, + ); + } else { + _libraryContext.load(library); + } + return _libraryContext; } /** @@ -1584,10 +1627,12 @@ */ void _fillSalt() { _unlinkedSalt[0] = DATA_VERSION; - _unlinkedSalt.setAll(1, _analysisOptions.unlinkedSignature); + _unlinkedSalt[1] = enableIndex ? 1 : 0; + _unlinkedSalt.setAll(2, _analysisOptions.unlinkedSignature); _linkedSalt[0] = DATA_VERSION; - _linkedSalt.setAll(1, _analysisOptions.signature); + _linkedSalt[1] = enableIndex ? 1 : 0; + _linkedSalt.setAll(2, _analysisOptions.signature); } /** @@ -1601,7 +1646,7 @@ List<AnalysisError> errors = _getErrorsFromSerialized(file, unit.errors); _updateHasErrorOrWarningFlag(file, errors); return new AnalysisResult( - this, + currentSession, _sourceFactory, file.path, file.uri, @@ -1691,7 +1736,7 @@ FileState file, String missingUri) { // TODO(scheglov) Find a better way to report this. return new AnalysisResult( - this, + currentSession, _sourceFactory, file.path, file.uri, @@ -1721,26 +1766,13 @@ } /** - * Runs any asynchronous work that was injected as part of a test using - * [AnalysisDriverTestView.workToWaitAfterComputingResult]. - * - * If the test view indicates that there is work to do, performs the work - * and returns a [Future] that will be signaled when the work completes. - * - * This gives tests a reliable way to simulate file changes during analysis. - */ - Future _runTestAsyncWorkDuringAnalysis(String path) { - var work = _testView.workToWaitAfterComputingResult; - _testView.workToWaitAfterComputingResult = null; - return work != null ? work(path) : new Future.value(); - } - - /** * Serialize the given [resolvedUnit] errors and index into bytes. */ List<int> _serializeResolvedUnit( CompilationUnit resolvedUnit, List<AnalysisError> errors) { - AnalysisDriverUnitIndexBuilder index = indexUnit(resolvedUnit); + AnalysisDriverUnitIndexBuilder index = enableIndex + ? indexUnit(resolvedUnit) + : new AnalysisDriverUnitIndexBuilder(); return new AnalysisDriverResolvedUnitBuilder( errors: errors .map((error) => new AnalysisDriverUnitErrorBuilder( @@ -1763,7 +1795,7 @@ } try { List<AnalysisDriverExceptionFileBuilder> contextFiles = libraryFile - .transitiveFiles + .libraryFiles .map((file) => new AnalysisDriverExceptionFileBuilder( path: file.path, content: file.content)) .toList(); @@ -2092,34 +2124,20 @@ class AnalysisDriverTestView { final AnalysisDriver driver; - int numOfCreatedLibraryContexts = 0; - int numOfAnalyzedLibraries = 0; - /** - * If non-null, a function that should be executed asynchronously after - * the next result is computed. - * - * This can be used by a test to simulate file changes during analysis. - */ - WorkToWaitAfterComputingResult workToWaitAfterComputingResult; - AnalysisDriverTestView(this.driver); FileTracker get fileTracker => driver._fileTracker; - Map<String, AnalysisResult> get priorityResults => driver._priorityResults; + Map<String, ResolvedUnitResult> get priorityResults { + return driver._priorityResults; + } - Future<SummaryDataStore> getSummaryStore(String libraryPath) async { + SummaryDataStore getSummaryStore(String libraryPath) { FileState library = driver.fsState.getFileForPath(libraryPath); - // TODO(brianwilkerson) Determine whether this await is necessary. - await null; LibraryContext libraryContext = driver._createLibraryContext(library); - try { - return libraryContext.store; - } finally { - libraryContext.dispose(); - } + return libraryContext.store; } } @@ -2134,88 +2152,52 @@ * Every result is independent, and is not guaranteed to be consistent with * any previously returned result, even inside of the same library. */ -class AnalysisResult extends FileResult implements results.ResolvedUnitResult { +class AnalysisResult extends ResolvedUnitResultImpl { static final _UNCHANGED = new AnalysisResult( null, null, null, null, null, null, null, null, null, null, null, null); - - /** - * The [AnalysisDriver] that produced this result. - */ - final AnalysisDriver driver; - /** * The [SourceFactory] with which the file was analyzed. */ final SourceFactory sourceFactory; /** - * Return `true` if the file exists. - */ - final bool exists; - - @override - final String content; - - /** * The signature of the result based on the content of the file, and the * transitive closure of files imported and exported by the library of * the requested file. */ final String _signature; - @override - final CompilationUnit unit; - - @override - final List<AnalysisError> errors; - /** * The index of the unit. */ final AnalysisDriverUnitIndex _index; AnalysisResult( - this.driver, + AnalysisSession session, this.sourceFactory, String path, Uri uri, - this.exists, - this.content, + bool exists, + String content, LineInfo lineInfo, bool isPart, this._signature, - this.unit, - this.errors, + CompilationUnit unit, + List<AnalysisError> errors, this._index) - : super(driver?.currentSession, path, uri, lineInfo, isPart); + : super(session, path, uri, exists, content, lineInfo, isPart, unit, + errors); @override LibraryElement get libraryElement => unit.declaredElement.library; @override - results.ResultState get state => - exists ? results.ResultState.VALID : results.ResultState.NOT_A_FILE; - - @override TypeProvider get typeProvider => unit.declaredElement.context.typeProvider; @override TypeSystem get typeSystem => unit.declaredElement.context.typeSystem; } -abstract class BaseAnalysisResult implements results.AnalysisResult { - @override - final AnalysisSession session; - - @override - final String path; - - @override - final Uri uri; - - BaseAnalysisResult(this.session, this.path, this.uri); -} - class DriverPerformance { static final PerformanceTag driver = PerformanceStatistics.analyzer.createChild('driver'); @@ -2242,25 +2224,6 @@ } /** - * The errors in a single file. - * - * These results are self-consistent, i.e. [errors] and [lineInfo] correspond - * to each other. But none of the results is guaranteed to be consistent with - * the state of the files. - */ -class ErrorsResult extends FileResult implements results.ErrorsResult { - @override - final List<AnalysisError> errors; - - ErrorsResult(AnalysisSession session, String path, Uri uri, LineInfo lineInfo, - bool isPart, this.errors) - : super(session, path, uri, lineInfo, isPart); - - @override - results.ResultState get state => results.ResultState.VALID; -} - -/** * Exception that happened during analysis. */ class ExceptionResult { @@ -2288,83 +2251,6 @@ } /** - * The result of computing some cheap information for a single file, when full - * parsed file is not required, so [ParseResult] is not necessary. - */ -class FileResult extends BaseAnalysisResult implements results.FileResult { - @override - final LineInfo lineInfo; - - @override - final bool isPart; - - FileResult( - AnalysisSession session, String path, Uri uri, this.lineInfo, this.isPart) - : super(session, path, uri); - - @override - results.ResultState get state => results.ResultState.VALID; -} - -/** - * The result of parsing of a single file. - * - * These results are self-consistent, i.e. [content], [lineInfo], the - * parsed [unit] correspond to each other. But none of the results is - * guaranteed to be consistent with the state of the files. - */ -class ParseResult extends FileResult implements results.ParseResult { - @override - final String content; - - @override - final CompilationUnit unit; - - @override - final List<AnalysisError> errors; - - ParseResult(AnalysisSession session, String path, Uri uri, this.content, - LineInfo lineInfo, bool isPart, this.unit, this.errors) - : super(session, path, uri, lineInfo, isPart); - - @override - results.ResultState get state => results.ResultState.VALID; -} - -/** - * The result with the [CompilationUnitElement] of a single file. - * - * These results are self-consistent, i.e. all elements and types accessible - * through [element], including defined in other files, correspond to each - * other. But none of the results is guaranteed to be consistent with the state - * of the files. - * - * Every result is independent, and is not guaranteed to be consistent with - * any previously returned result, even inside of the same library. - */ -class UnitElementResult extends BaseAnalysisResult - implements results.UnitElementResult { - /** - * The signature of the [element] is based the APIs of the files of the - * library (including the file itself) of the requested file and the - * transitive closure of files imported and exported by the library. - */ - final String signature; - - /** - * The element of the file. - */ - final CompilationUnitElement element; - - UnitElementResult(AnalysisSession session, String path, Uri uri, - this.signature, this.element) - : super(session, path, uri); - - @override - results.ResultState get state => results.ResultState.VALID; -} - -/** * Task that discovers all files that are available to the driver, and makes * them known. */
diff --git a/pkg/analyzer/lib/src/dart/analysis/driver_based_analysis_context.dart b/pkg/analyzer/lib/src/dart/analysis/driver_based_analysis_context.dart index f96d909..6d35e0e 100644 --- a/pkg/analyzer/lib/src/dart/analysis/driver_based_analysis_context.dart +++ b/pkg/analyzer/lib/src/dart/analysis/driver_based_analysis_context.dart
@@ -6,7 +6,7 @@ import 'package:analyzer/dart/analysis/context_root.dart'; import 'package:analyzer/dart/analysis/session.dart'; import 'package:analyzer/file_system/file_system.dart'; -import 'package:analyzer/src/dart/analysis/driver.dart' hide AnalysisResult; +import 'package:analyzer/src/dart/analysis/driver.dart' show AnalysisDriver; import 'package:analyzer/src/generated/engine.dart' show AnalysisOptions; /** @@ -31,7 +31,9 @@ * to access the file system and that is based on the given analysis [driver]. */ DriverBasedAnalysisContext( - this.resourceProvider, this.contextRoot, this.driver); + this.resourceProvider, this.contextRoot, this.driver) { + driver.analysisContext = this; + } @override AnalysisOptions get analysisOptions => driver.analysisOptions;
diff --git a/pkg/analyzer/lib/src/dart/analysis/experiments.dart b/pkg/analyzer/lib/src/dart/analysis/experiments.dart new file mode 100644 index 0000000..d0993c6 --- /dev/null +++ b/pkg/analyzer/lib/src/dart/analysis/experiments.dart
@@ -0,0 +1,36 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:analyzer/src/generated/engine.dart'; + +/// A representation of the set of experiments that are active and whether they +/// are enabled. +class Experiments { + /// The name of the experiment to extend which expressions are constant + /// expressions. + static const String constantUpdate2018Name = 'constant-update-2018'; + + /// The name of the experiment to support set literals. + static const String setLiteralName = 'set-literal'; + + /// A list containing the names of active experiments. + static const List<String> activeExperimentNames = <String>[ + constantUpdate2018Name, + setLiteralName, + ]; + + /// A list containing the names of the experiments that have been enabled. + final List<String> _enabled; + + /// Initialize a newly created set of experiments from the given set of + /// analysis [options]. + Experiments(AnalysisOptions options) : _enabled = options.enabledExperiments; + + /// Return `true` if the experiment named 'constant-update-2018' has been + /// enabled. + bool get constantUpdate2018 => _enabled.contains(constantUpdate2018Name); + + /// Return `true` if the experiment named 'set-literal' has been enabled. + bool get setLiteral => _enabled.contains(setLiteralName); +}
diff --git a/pkg/analyzer/lib/src/dart/analysis/file_state.dart b/pkg/analyzer/lib/src/dart/analysis/file_state.dart index e627abb..2ea7c4c 100644 --- a/pkg/analyzer/lib/src/dart/analysis/file_state.dart +++ b/pkg/analyzer/lib/src/dart/analysis/file_state.dart
@@ -12,6 +12,8 @@ import 'package:analyzer/file_system/file_system.dart'; import 'package:analyzer/src/dart/analysis/byte_store.dart'; import 'package:analyzer/src/dart/analysis/defined_names.dart'; +import 'package:analyzer/src/dart/analysis/experiments.dart'; +import 'package:analyzer/src/dart/analysis/library_graph.dart'; import 'package:analyzer/src/dart/analysis/performance_logger.dart'; import 'package:analyzer/src/dart/analysis/referenced_names.dart'; import 'package:analyzer/src/dart/analysis/top_level_declaration.dart'; @@ -125,8 +127,11 @@ List<NameFilter> _exportFilters; Set<FileState> _directReferencedFiles; - Set<FileState> _transitiveFiles; + Set<FileState> _directReferencedLibraries; + + LibraryCycle _libraryCycle; String _transitiveSignature; + String _transitiveSignatureLinked; Map<String, TopLevelDeclaration> _topLevelDeclarations; Map<String, TopLevelDeclaration> _exportedTopLevelDeclarations; @@ -147,6 +152,7 @@ source = null, _exists = true { _apiSignature = new Uint8List(16); + _libraryCycle = new LibraryCycle.external(); } /** @@ -187,6 +193,11 @@ Set<FileState> get directReferencedFiles => _directReferencedFiles; /** + * Return the set of all directly referenced libraries - imported or exported. + */ + Set<FileState> get directReferencedLibraries => _directReferencedLibraries; + + /** * Return `true` if the file exists. */ bool get exists => _exists; @@ -213,6 +224,8 @@ */ List<FileState> get importedFiles => _importedFiles; + LibraryCycle get internal_libraryCycle => _libraryCycle; + /** * Return `true` if the file is a stub created for a library in the provided * external summary store. @@ -254,6 +267,23 @@ } } + /// Return the [LibraryCycle] this file belongs to, even if it consists of + /// just this file. If the library cycle is not known yet, compute it. + LibraryCycle get libraryCycle { + if (isPart) { + var library = this.library; + if (library != null) { + return library.libraryCycle; + } + } + + if (_libraryCycle == null) { + computeLibraryCycle(_fsState._linkedSalt, this); + } + + return _libraryCycle; + } + /** * The list of files files that this library consists of, i.e. this library * file itself and its [partedFiles]. @@ -331,39 +361,26 @@ } /** - * Return the set of transitive files - the file itself and all of the - * directly or indirectly referenced files. + * Return the signature of the file, based on API signatures of the + * transitive closure of imported / exported files. */ - Set<FileState> get transitiveFiles { - if (_transitiveFiles == null) { - _transitiveFiles = new Set<FileState>(); - - void appendReferenced(FileState file) { - if (_transitiveFiles.add(file)) { - file._directReferencedFiles?.forEach(appendReferenced); - } + String get transitiveSignature { + if (isPart) { + var library = this.library; + if (library != null) { + return library.transitiveSignature; } - - appendReferenced(this); } - return _transitiveFiles; + + this.libraryCycle; // sets _transitiveSignature + return _transitiveSignature; } /** - * Return the signature of the file, based on the [transitiveFiles]. + * The value `transitiveSignature.linked` is used often, so we cache it. */ - String get transitiveSignature { - if (_transitiveSignature == null) { - ApiSignature signature = new ApiSignature(); - signature.addUint32List(_fsState._linkedSalt); - signature.addInt(transitiveFiles.length); - transitiveFiles - .map((file) => file.apiSignature) - .forEach(signature.addBytes); - signature.addString(uri.toString()); - _transitiveSignature = signature.toHex(); - } - return _transitiveSignature; + String get transitiveSignatureLinked { + return _transitiveSignatureLinked ??= '$transitiveSignature.linked'; } /** @@ -381,6 +398,17 @@ return other is FileState && other.uri == uri; } + void internal_setLibraryCycle(LibraryCycle cycle, String signature) { + if (cycle == null) { + _libraryCycle = null; + _transitiveSignature = null; + _transitiveSignatureLinked = null; + } else { + _libraryCycle = cycle; + _transitiveSignature = signature; + } + } + /** * Return a new parsed unresolved [CompilationUnit]. * @@ -461,14 +489,11 @@ _apiSignature = newApiSignature; // The API signature changed. - // Flush transitive signatures of affected files. + // Flush affected library cycles. // Flush exported top-level declarations of all files. if (apiSignatureChanged) { + _libraryCycle?.invalidate(); for (FileState file in _fsState._uriToFile.values) { - if (file._transitiveFiles != null && - file._transitiveFiles.contains(this)) { - file._transitiveSignature = null; - } file._exportedTopLevelDeclarations = null; } } @@ -508,26 +533,13 @@ _libraryFiles = [this]..addAll(_partedFiles); // Compute referenced files. - Set<FileState> oldDirectReferencedFiles = _directReferencedFiles; _directReferencedFiles = new Set<FileState>() ..addAll(_importedFiles) ..addAll(_exportedFiles) ..addAll(_partedFiles); - - // If the set of directly referenced files of this file is changed, - // then the transitive sets of files that include this file are also - // changed. Reset these transitive sets. - if (oldDirectReferencedFiles != null) { - if (_directReferencedFiles.length != oldDirectReferencedFiles.length || - !_directReferencedFiles.containsAll(oldDirectReferencedFiles)) { - for (FileState file in _fsState._uriToFile.values) { - if (file._transitiveFiles != null && - file._transitiveFiles.contains(this)) { - file._transitiveFiles = null; - } - } - } - } + _directReferencedLibraries = Set<FileState>() + ..addAll(_importedFiles) + ..addAll(_exportedFiles); // Update mapping from subtyped names to files. for (var name in _driverUnlinkedUnit.subtypedNames) { @@ -659,8 +671,10 @@ } AnalysisOptions analysisOptions = _fsState._analysisOptions; + Experiments experiments = new Experiments(analysisOptions); CharSequenceReader reader = new CharSequenceReader(content); Scanner scanner = new Scanner(source, reader, errorListener); + scanner.enableGtGtGt = experiments.constantUpdate2018; Token token = PerformanceStatistics.scan.makeCurrentWhile(() { return scanner.tokenize(); }); @@ -669,6 +683,7 @@ bool useFasta = analysisOptions.useFastaParser; Parser parser = new Parser(source, errorListener, useFasta: useFasta); parser.enableOptionalNewAndConst = true; + parser.enableSetLiterals = experiments.setLiteral; CompilationUnit unit = parser.parseCompilationUnit(token); unit.lineInfo = lineInfo; @@ -714,7 +729,7 @@ */ class FileSystemState { final PerformanceLog _logger; - final ResourceProvider resourceProvider; + final ResourceProvider _resourceProvider; final ByteStore _byteStore; final FileContentOverlay _contentOverlay; final SourceFactory _sourceFactory; @@ -795,7 +810,7 @@ this._logger, this._byteStore, this._contentOverlay, - this.resourceProvider, + this._resourceProvider, this._sourceFactory, this._analysisOptions, this._unlinkedSalt, @@ -803,7 +818,7 @@ this.externalSummaries, }) { _fileContentCache = _FileContentCache.getInstance( - resourceProvider, + _resourceProvider, _contentOverlay, ); _testView = new FileSystemStateTestView(this); @@ -833,7 +848,7 @@ FileState getFileForPath(String path) { FileState file = _pathToCanonicalFile[path]; if (file == null) { - File resource = resourceProvider.getFile(path); + File resource = _resourceProvider.getFile(path); Source fileSource = resource.createSource(); Uri uri = _sourceFactory.restoreUri(fileSource); // Try to get the existing instance. @@ -884,7 +899,7 @@ } String path = uriSource.fullName; - File resource = resourceProvider.getFile(path); + File resource = _resourceProvider.getFile(path); FileSource source = new FileSource(resource, uri); file = new FileState._(this, path, uri, source); _uriToFile[uri] = file; @@ -927,7 +942,7 @@ bool hasUri(String path) { bool flag = _hasUriForPath[path]; if (flag == null) { - File resource = resourceProvider.getFile(path); + File resource = _resourceProvider.getFile(path); Source fileSource = resource.createSource(); Uri uri = _sourceFactory.restoreUri(fileSource); Source uriSource = _sourceFactory.forUri2(uri); @@ -978,15 +993,9 @@ FileSystemStateTestView(this.state); - Set<FileState> get filesWithoutTransitiveFiles { + Set<FileState> get filesWithoutLibraryCycle { return state._uriToFile.values - .where((f) => f._transitiveFiles == null) - .toSet(); - } - - Set<FileState> get filesWithoutTransitiveSignature { - return state._uriToFile.values - .where((f) => f._transitiveSignature == null) + .where((f) => f._libraryCycle == null) .toSet(); }
diff --git a/pkg/analyzer/lib/src/dart/analysis/library_analyzer.dart b/pkg/analyzer/lib/src/dart/analysis/library_analyzer.dart index ed45474..c11275c 100644 --- a/pkg/analyzer/lib/src/dart/analysis/library_analyzer.dart +++ b/pkg/analyzer/lib/src/dart/analysis/library_analyzer.dart
@@ -8,8 +8,6 @@ import 'package:analyzer/dart/element/element.dart'; import 'package:analyzer/error/error.dart'; import 'package:analyzer/error/listener.dart'; -import 'package:analyzer/file_system/file_system.dart'; -import 'package:analyzer/src/context/context.dart'; import 'package:analyzer/src/dart/analysis/file_state.dart'; import 'package:analyzer/src/dart/ast/ast.dart'; import 'package:analyzer/src/dart/ast/utilities.dart'; @@ -27,7 +25,6 @@ import 'package:analyzer/src/generated/error_verifier.dart'; import 'package:analyzer/src/generated/resolver.dart'; import 'package:analyzer/src/generated/source.dart'; -import 'package:analyzer/src/hint/sdk_constraint_extractor.dart'; import 'package:analyzer/src/hint/sdk_constraint_verifier.dart'; import 'package:analyzer/src/lint/linter.dart'; import 'package:analyzer/src/lint/linter_visitor.dart'; @@ -44,37 +41,31 @@ /// [_versionConstraintFromPubspec] when the previous initialization attempt /// failed. static final VersionRange noSpecifiedRange = new VersionRange(); - final AnalysisOptionsImpl _analysisOptions; final DeclaredVariables _declaredVariables; final SourceFactory _sourceFactory; final FileState _library; - final ResourceProvider resourceProvider; - final InheritanceManager2 _inheritance; + final InheritanceManager2 _inheritance; final bool Function(Uri) _isLibraryUri; - final AnalysisContextImpl _context; + final AnalysisContext _context; final ElementResynthesizer _resynthesizer; final TypeProvider _typeProvider; + final TypeSystem _typeSystem; - LibraryElement _libraryElement; + LibraryScope _libraryScope; - final Map<FileState, LineInfo> _fileToLineInfo = {}; - final Map<FileState, IgnoreInfo> _fileToIgnoreInfo = {}; + final Map<FileState, IgnoreInfo> _fileToIgnoreInfo = {}; final Map<FileState, RecordingErrorListener> _errorListeners = {}; final Map<FileState, ErrorReporter> _errorReporters = {}; final List<UsedImportedElements> _usedImportedElementsList = []; final List<UsedLocalElements> _usedLocalElementsList = []; final Map<FileState, List<PendingError>> _fileToPendingErrors = {}; - final Set<ConstantEvaluationTarget> _constants = new Set(); - /// The cached version range for the SDK specified in `pubspec.yaml`, or - /// [noSpecifiedRange] if there is no `pubspec.yaml` or if it does not contain - /// an SDK range. Use [versionConstraintFromPubspec] to access this field. - VersionConstraint _versionConstraintFromPubspec; + final Set<ConstantEvaluationTarget> _constants = new Set(); LibraryAnalyzer( this._analysisOptions, @@ -83,10 +74,9 @@ this._isLibraryUri, this._context, this._resynthesizer, - this._library, - this.resourceProvider) - : _inheritance = new InheritanceManager2(_context.typeSystem), - _typeProvider = _context.typeProvider, + this._inheritance, + this._library) + : _typeProvider = _context.typeProvider, _typeSystem = _context.typeSystem; /** @@ -114,60 +104,56 @@ _resolveUriBasedDirectives(file, unit); }); - try { - _libraryElement = _resynthesizer - .getElement(new ElementLocationImpl.con3([_library.uriStr])); - _libraryScope = new LibraryScope(_libraryElement); + _libraryElement = _resynthesizer + .getElement(new ElementLocationImpl.con3([_library.uriStr])); + _libraryScope = new LibraryScope(_libraryElement); - _resolveDirectives(units); + _resolveDirectives(units); + units.forEach((file, unit) { + _resolveFile(file, unit); + _computePendingMissingRequiredParameters(file, unit); + }); + + units.values.forEach(_findConstants); + _computeConstants(); + + PerformanceStatistics.errors.makeCurrentWhile(() { units.forEach((file, unit) { - _resolveFile(file, unit); - _computePendingMissingRequiredParameters(file, unit); + _computeVerifyErrors(file, unit); }); + }); - units.values.forEach(_findConstants); - _computeConstants(); - - PerformanceStatistics.errors.makeCurrentWhile(() { + if (_analysisOptions.hint) { + PerformanceStatistics.hints.makeCurrentWhile(() { units.forEach((file, unit) { - _computeVerifyErrors(file, unit); - }); - }); - - if (_analysisOptions.hint) { - PerformanceStatistics.hints.makeCurrentWhile(() { - units.forEach((file, unit) { - { - var visitor = new GatherUsedLocalElementsVisitor(_libraryElement); - unit.accept(visitor); - _usedLocalElementsList.add(visitor.usedElements); - } - { - var visitor = - new GatherUsedImportedElementsVisitor(_libraryElement); - unit.accept(visitor); - _usedImportedElementsList.add(visitor.usedElements); - } - }); - units.forEach((file, unit) { - _computeHints(file, unit); - }); - }); - } - - if (_analysisOptions.lint) { - PerformanceStatistics.lints.makeCurrentWhile(() { - var allUnits = _library.libraryFiles - .map((file) => LinterContextUnit(file.content, units[file])) - .toList(); - for (int i = 0; i < allUnits.length; i++) { - _computeLints(_library.libraryFiles[i], allUnits[i], allUnits); + { + var visitor = new GatherUsedLocalElementsVisitor(_libraryElement); + unit.accept(visitor); + _usedLocalElementsList.add(visitor.usedElements); + } + { + var visitor = + new GatherUsedImportedElementsVisitor(_libraryElement); + unit.accept(visitor); + _usedImportedElementsList.add(visitor.usedElements); } }); - } - } finally { - _context.dispose(); + units.forEach((file, unit) { + _computeHints(file, unit); + }); + }); + } + + if (_analysisOptions.lint) { + PerformanceStatistics.lints.makeCurrentWhile(() { + var allUnits = _library.libraryFiles + .map((file) => LinterContextUnit(file.content, units[file])) + .toList(); + for (int i = 0; i < allUnits.length; i++) { + _computeLints(_library.libraryFiles[i], allUnits[i], allUnits); + } + }); } // Return full results. @@ -180,20 +166,6 @@ return results; } - VersionConstraint versionConstraintFromPubspec() { - if (_versionConstraintFromPubspec == null) { - _versionConstraintFromPubspec = noSpecifiedRange; - File pubspecFile = _findPubspecFile(_library); - if (pubspecFile != null) { - SdkConstraintExtractor extractor = - new SdkConstraintExtractor(pubspecFile); - _versionConstraintFromPubspec = - extractor.constraint() ?? noSpecifiedRange; - } - } - return _versionConstraintFromPubspec; - } - void _computeConstantErrors( ErrorReporter errorReporter, CompilationUnit unit) { ConstantVerifier constantVerifier = new ConstantVerifier( @@ -268,14 +240,15 @@ new UnusedLocalElementsVerifier(errorListener, usedElements); unit.accept(visitor); } + // - // Find code that uses features from an SDK that is newer than the minimum - // version allowed in the pubspec.yaml file. + // Find code that uses features from an SDK version that does not satisfy + // the SDK constraints specified in analysis options. // - VersionRange versionRange = versionConstraintFromPubspec(); - if (versionRange != noSpecifiedRange) { + var sdkVersionConstraint = _analysisOptions.sdkVersionConstraint; + if (sdkVersionConstraint != null) { SdkConstraintVerifier verifier = new SdkConstraintVerifier( - errorReporter, _libraryElement, _typeProvider, versionRange); + errorReporter, _libraryElement, _typeProvider, sdkVersionConstraint); unit.accept(verifier); } } @@ -295,11 +268,8 @@ allUnits, currentUnit, _declaredVariables, _typeProvider, _typeSystem); for (Linter linter in _analysisOptions.lintRules) { linter.reporter = errorReporter; - if (linter is NodeLintRuleWithContext) { - (linter as NodeLintRuleWithContext) - .registerNodeProcessors(nodeRegistry, context); - } else if (linter is NodeLintRule) { - (linter as NodeLintRule).registerNodeProcessors(nodeRegistry); + if (linter is NodeLintRule) { + (linter as NodeLintRule).registerNodeProcessors(nodeRegistry, context); } else { AstVisitor visitor = linter.getVisitor(); if (visitor != null) { @@ -412,18 +382,6 @@ _constants.addAll(dependenciesFinder.dependencies); } - File _findPubspecFile(FileState file) { - Folder folder = resourceProvider?.getFile(file.path)?.parent; - while (folder != null) { - File pubspecFile = folder.getChildAssumingFile('pubspec.yaml'); - if (pubspecFile.exists) { - return pubspecFile; - } - folder = folder.parent; - } - return null; - } - RecordingErrorListener _getErrorListener(FileState file) => _errorListeners.putIfAbsent(file, () => new RecordingErrorListener()); @@ -459,6 +417,15 @@ return null; } + bool _isExistingSource(Source source) { + for (var file in _library.directReferencedFiles) { + if (file.uri == source.uri) { + return file.exists; + } + } + return false; + } + /** * Return `true` if the given [source] is a library. */ @@ -554,7 +521,7 @@ // Validate that the part contains a part-of directive with the same // name or uri as the library. // - if (_context.exists(partSource)) { + if (_isExistingSource(partSource)) { _NameOrSource nameOrSource = _getPartLibraryNameOrUri( partSource, partUnit, directivesToResolve); if (nameOrSource == null) { @@ -702,7 +669,7 @@ FileState file, UriBasedDirectiveImpl directive) { Source source = directive.uriSource; if (source != null) { - if (_context.exists(source)) { + if (_isExistingSource(source)) { return; } } else {
diff --git a/pkg/analyzer/lib/src/dart/analysis/library_context.dart b/pkg/analyzer/lib/src/dart/analysis/library_context.dart index 3a36e2b..44f61a4 100644 --- a/pkg/analyzer/lib/src/dart/analysis/library_context.dart +++ b/pkg/analyzer/lib/src/dart/analysis/library_context.dart
@@ -3,6 +3,7 @@ // BSD-style license that can be found in the LICENSE file. import 'package:analyzer/dart/analysis/declared_variables.dart'; +import 'package:analyzer/dart/analysis/session.dart'; import 'package:analyzer/dart/element/element.dart' show CompilationUnitElement, LibraryElement; import 'package:analyzer/src/context/context.dart'; @@ -10,161 +11,94 @@ import 'package:analyzer/src/dart/analysis/driver.dart'; import 'package:analyzer/src/dart/analysis/file_state.dart'; import 'package:analyzer/src/dart/analysis/performance_logger.dart'; +import 'package:analyzer/src/dart/analysis/restricted_analysis_context.dart'; import 'package:analyzer/src/dart/element/element.dart'; -import 'package:analyzer/src/dart/element/handle.dart'; +import 'package:analyzer/src/dart/element/inheritance_manager2.dart'; import 'package:analyzer/src/generated/engine.dart' - show AnalysisContext, AnalysisEngine, AnalysisOptions; + show AnalysisContext, AnalysisOptions; +import 'package:analyzer/src/generated/resolver.dart' show TypeProvider; import 'package:analyzer/src/generated/source.dart'; import 'package:analyzer/src/summary/format.dart'; import 'package:analyzer/src/summary/idl.dart'; import 'package:analyzer/src/summary/link.dart'; import 'package:analyzer/src/summary/package_bundle_reader.dart'; +import 'package:analyzer/src/summary/resynthesize.dart'; +import 'package:meta/meta.dart'; /** * Context information necessary to analyze one or more libraries within an * [AnalysisDriver]. * * Currently this is implemented as a wrapper around [AnalysisContext]. - * TODO(paulberry): make a front end API that this can make use of instead. */ class LibraryContext { - final SummaryDataStore store; + static const _maxLinkedDataInBytes = 64 * 1024 * 1024; - /** - * The [AnalysisContext] which is used to do the analysis. - */ - final AnalysisContext analysisContext; + final PerformanceLog logger; + final ByteStore byteStore; + final SummaryDataStore store = new SummaryDataStore([]); - /** - * The resynthesizer that resynthesizes elements in [analysisContext]. - */ - final ElementResynthesizer resynthesizer; + /// The size of the linked data that is loaded by this context. + /// When it reaches [_maxLinkedDataInBytes] the whole context is thrown away. + /// We use it as an approximation for the heap size of elements. + int _linkedDataInBytes = 0; - /** - * Create a [LibraryContext] which is prepared to analyze [targetLibrary]. - */ - factory LibraryContext.forSingleLibrary( - FileState targetLibrary, - PerformanceLog logger, - PackageBundle sdkBundle, - ByteStore byteStore, - AnalysisOptions options, - DeclaredVariables declaredVariables, - SourceFactory sourceFactory, - SummaryDataStore externalSummaries, - FileSystemState fsState) { - return logger.run('Create library context', () { - Map<String, FileState> libraries = <String, FileState>{}; - SummaryDataStore store = new SummaryDataStore(const <String>[]); + AnalysisContextImpl analysisContext; + SummaryResynthesizer resynthesizer; + InheritanceManager2 inheritanceManager; - if (externalSummaries != null) { - store.addStore(externalSummaries); - } + LibraryContext({ + @required AnalysisSession session, + @required PerformanceLog logger, + @required ByteStore byteStore, + @required FileSystemState fsState, + @required AnalysisOptions analysisOptions, + @required DeclaredVariables declaredVariables, + @required SourceFactory sourceFactory, + @required SummaryDataStore externalSummaries, + @required FileState targetLibrary, + }) : this.logger = logger, + this.byteStore = byteStore { + if (externalSummaries != null) { + store.addStore(externalSummaries); + } - if (sdkBundle != null) { - store.addBundle(null, sdkBundle); - } + // Fill the store with summaries required for the initial library. + load(targetLibrary); - void appendLibraryFiles(FileState library) { - if (!libraries.containsKey(library.uriStr)) { - // Serve 'dart:' URIs from the SDK bundle. - if (sdkBundle != null && library.uri.scheme == 'dart') { - return; - } + analysisContext = new RestrictedAnalysisContext( + analysisOptions, + declaredVariables, + sourceFactory, + ); - if (library.isInExternalSummaries) { - return; - } + var provider = new InputPackagesResultProvider(analysisContext, store, + session: session); + resynthesizer = provider.resynthesizer; - libraries[library.uriStr] = library; - - // Append library units. - for (FileState part in library.libraryFiles) { - store.addUnlinkedUnit(part.uriStr, part.unlinked); - } - - // Append referenced libraries. - library.importedFiles.forEach(appendLibraryFiles); - library.exportedFiles.forEach(appendLibraryFiles); - } - } - - logger.run('Append library files', () { - appendLibraryFiles(targetLibrary); - }); - - var libraryUrisToLink = new Set<String>(); - var libraryFilesToLink = new Set<FileState>(); - logger.run('Load linked bundles', () { - for (FileState library in libraries.values) { - if (library.exists || library == targetLibrary) { - String key = '${library.transitiveSignature}.linked'; - List<int> bytes = byteStore.get(key); - if (bytes != null) { - LinkedLibrary linked = new LinkedLibrary.fromBuffer(bytes); - store.addLinkedLibrary(library.uriStr, linked); - } else { - libraryUrisToLink.add(library.uriStr); - libraryFilesToLink.add(library); - } - } - } - int numOfLoaded = libraries.length - libraryUrisToLink.length; - logger.writeln('Loaded $numOfLoaded linked bundles.'); - }); - - Map<String, LinkedLibraryBuilder> linkedLibraries = {}; - logger.run('Link libraries', () { - linkedLibraries = link(libraryUrisToLink, (String uri) { - LinkedLibrary linkedLibrary = store.linkedMap[uri]; - return linkedLibrary; - }, (String uri) { - UnlinkedUnit unlinkedUnit = store.unlinkedMap[uri]; - return unlinkedUnit; - }, (_) => null); - logger.writeln('Linked ${linkedLibraries.length} libraries.'); - }); - - for (String uri in linkedLibraries.keys) { - LinkedLibraryBuilder linkedBuilder = linkedLibraries[uri]; - FileState library = libraries[uri]; - String key = '${library.transitiveSignature}.linked'; - List<int> bytes = linkedBuilder.toBuffer(); - LinkedLibrary linked = new LinkedLibrary.fromBuffer(bytes); - store.addLinkedLibrary(uri, linked); - byteStore.put(key, bytes); - } - - var resynthesizingContext = _createResynthesizingContext( - options, declaredVariables, sourceFactory, store); - resynthesizingContext.context.contentCache = - new _ContentCacheWrapper(fsState); - - return new LibraryContext._(store, resynthesizingContext.context, - resynthesizingContext.resynthesizer); - }); + inheritanceManager = new InheritanceManager2(analysisContext.typeSystem); } - LibraryContext._(this.store, this.analysisContext, this.resynthesizer); + /** + * The type provider used in this context. + */ + TypeProvider get typeProvider => analysisContext.typeProvider; /** * Computes a [CompilationUnitElement] for the given library/unit pair. */ - CompilationUnitElement computeUnitElement( - Source librarySource, Source unitSource) { - String libraryUri = librarySource.uri.toString(); - String unitUri = unitSource.uri.toString(); - return resynthesizer.getElement( - new ElementLocationImpl.con3(<String>[libraryUri, unitUri])); + CompilationUnitElement computeUnitElement(FileState library, FileState unit) { + return resynthesizer.getElement(new ElementLocationImpl.con3(<String>[ + library.uriStr, + unit.uriStr, + ])); } /** - * Cleans up any persistent resources used by this [LibraryContext]. - * - * Should be called once the [LibraryContext] is no longer needed. + * Get the [LibraryElement] for the given library. */ - void dispose() { - analysisContext.dispose(); + LibraryElement getLibraryElement(FileState library) { + return resynthesizer.getLibraryElement(library.uriStr); } /** @@ -175,99 +109,96 @@ return store.unlinkedMap[uriStr]?.isPartOf == false; } - /** - * Resynthesize the [LibraryElement] from the given [store]. - */ - static LibraryElement resynthesizeLibraryElement( - AnalysisOptions analysisOptions, - DeclaredVariables declaredVariables, - SourceFactory sourceFactory, - SummaryDataStore store, - String uri) { - var resynthesizingContext = _createResynthesizingContext( - analysisOptions, declaredVariables, sourceFactory, store); - try { - return resynthesizingContext.resynthesizer - .getElement(new ElementLocationImpl.con3([uri])); - } finally { - resynthesizingContext.context.dispose(); + /// Load data required to access elements of the given [targetLibrary]. + void load(FileState targetLibrary) { + // The library is already a part of the context, nothing to do. + if (store.linkedMap.containsKey(targetLibrary.uriStr)) { + return; + } + + var libraries = <String, FileState>{}; + void appendLibraryFiles(FileState library) { + // Stop if this library is already a part of the context. + // Libraries from external summaries are also covered by this. + if (store.linkedMap.containsKey(library.uriStr)) { + return; + } + + // Stop if we have already scheduled loading of this library. + if (libraries.containsKey(library.uriStr)) { + return; + } + + // Schedule the library for loading or linking. + libraries[library.uriStr] = library; + + // Append library units. + for (FileState part in library.libraryFiles) { + store.addUnlinkedUnit(part.uriStr, part.unlinked); + } + + // Append referenced libraries. + library.importedFiles.forEach(appendLibraryFiles); + library.exportedFiles.forEach(appendLibraryFiles); + } + + logger.run('Append library files', () { + appendLibraryFiles(targetLibrary); + }); + + var libraryUrisToLink = new Set<String>(); + logger.run('Load linked bundles', () { + for (FileState library in libraries.values) { + if (library.exists || library == targetLibrary) { + String key = library.transitiveSignatureLinked; + List<int> bytes = byteStore.get(key); + if (bytes != null) { + LinkedLibrary linked = new LinkedLibrary.fromBuffer(bytes); + store.addLinkedLibrary(library.uriStr, linked); + _linkedDataInBytes += bytes.length; + } else { + libraryUrisToLink.add(library.uriStr); + } + } + } + int numOfLoaded = libraries.length - libraryUrisToLink.length; + logger.writeln('Loaded $numOfLoaded linked bundles.'); + }); + + var linkedLibraries = <String, LinkedLibraryBuilder>{}; + logger.run('Link libraries', () { + linkedLibraries = link(libraryUrisToLink, (String uri) { + LinkedLibrary linkedLibrary = store.linkedMap[uri]; + return linkedLibrary; + }, (String uri) { + UnlinkedUnit unlinkedUnit = store.unlinkedMap[uri]; + return unlinkedUnit; + }, (_) => null); + logger.writeln('Linked ${linkedLibraries.length} libraries.'); + }); + + // Store freshly linked libraries into the byte store. + // Append them to the context. + for (String uri in linkedLibraries.keys) { + FileState library = libraries[uri]; + String key = library.transitiveSignatureLinked; + + LinkedLibraryBuilder linkedBuilder = linkedLibraries[uri]; + List<int> bytes = linkedBuilder.toBuffer(); + byteStore.put(key, bytes); + + LinkedLibrary linked = new LinkedLibrary.fromBuffer(bytes); + store.addLinkedLibrary(uri, linked); + _linkedDataInBytes += bytes.length; } } - static _ResynthesizingAnalysisContext _createResynthesizingContext( - AnalysisOptions analysisOptions, - DeclaredVariables declaredVariables, - SourceFactory sourceFactory, - SummaryDataStore store) { - AnalysisContextImpl analysisContext = - AnalysisEngine.instance.createAnalysisContext(); - analysisContext.useSdkCachePartition = false; - analysisContext.analysisOptions = analysisOptions; - analysisContext.declaredVariables = declaredVariables; - analysisContext.sourceFactory = sourceFactory.clone(); - var provider = new InputPackagesResultProvider(analysisContext, store); - analysisContext.resultProvider = provider; - return new _ResynthesizingAnalysisContext( - analysisContext, provider.resynthesizer); + /// Return `true` if this context grew too large, and should be recreated. + /// + /// It might have been used to analyze libraries that we don't need anymore, + /// and because loading libraries is not very expensive (but not free), the + /// simplest way to get rid of the garbage is to throw away everything. + bool pack() { + return _linkedDataInBytes > _maxLinkedDataInBytes; } } - -/** - * [ContentCache] wrapper around [FileContentOverlay]. - */ -class _ContentCacheWrapper implements ContentCache { - final FileSystemState fsState; - - _ContentCacheWrapper(this.fsState); - - @override - void accept(ContentCacheVisitor visitor) { - throw new UnimplementedError(); - } - - @override - String getContents(Source source) { - return _getFileForSource(source).content; - } - - @override - bool getExists(Source source) { - if (source.isInSystemLibrary) { - return true; - } - String uriStr = source.uri.toString(); - if (fsState.externalSummaries != null && - fsState.externalSummaries.hasUnlinkedUnit(uriStr)) { - return true; - } - return _getFileForSource(source).exists; - } - - @override - int getModificationStamp(Source source) { - if (source.isInSystemLibrary) { - return 0; - } - return _getFileForSource(source).exists ? 0 : -1; - } - - @override - String setContents(Source source, String contents) { - throw new UnimplementedError(); - } - - FileState _getFileForSource(Source source) { - String path = source.fullName; - return fsState.getFileForPath(path); - } -} - -/** - * Container with analysis context and the corresponding resynthesizer. - */ -class _ResynthesizingAnalysisContext { - final AnalysisContextImpl context; - final ElementResynthesizer resynthesizer; - - _ResynthesizingAnalysisContext(this.context, this.resynthesizer); -}
diff --git a/pkg/analyzer/lib/src/dart/analysis/library_graph.dart b/pkg/analyzer/lib/src/dart/analysis/library_graph.dart new file mode 100644 index 0000000..74cb08c --- /dev/null +++ b/pkg/analyzer/lib/src/dart/analysis/library_graph.dart
@@ -0,0 +1,173 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'dart:typed_data'; + +import 'package:analyzer/src/dart/analysis/file_state.dart'; +import 'package:analyzer/src/summary/api_signature.dart'; +import 'package:analyzer/src/summary/link.dart' as graph + show DependencyWalker, Node; +import 'package:meta/meta.dart'; + +/// Ensure that the [FileState.libraryCycle] for the [file] and anything it +/// depends on is computed. +void computeLibraryCycle(Uint32List linkedSalt, FileState file) { + var libraryWalker = new _LibraryWalker(linkedSalt); + libraryWalker.walk(libraryWalker.getNode(file)); +} + +/// Information about libraries that reference each other, so form a cycle. +class LibraryCycle { + /// The libraries that belong to this cycle. + final List<FileState> libraries = []; + + /// The library cycles that this cycle references directly. + @visibleForTesting + final Set<LibraryCycle> directDependencies = new Set<LibraryCycle>(); + + /// The cycles that use this cycle, used to [invalidate] transitively. + final List<LibraryCycle> _directUsers = []; + + /// The transitive signature of this cycle. + /// + /// It is based on the API signatures of all files of the [libraries], and + /// transitive signatures of the cycles that the [libraries] reference + /// directly. So, indirectly it is based on the transitive closure of all + /// files that [libraries] reference (but we don't compute these files). + String _transitiveSignature; + + /// The map from a library in [libraries] to its transitive signature. + /// + /// It is almost the same as [_transitiveSignature], but is also based on + /// the URI of this specific library. Currently we store each linked library + /// with its own key, so we need unique keys. However practically we never + /// can use just *one* library of a cycle, we always use the whole cycle. + /// + /// TODO(scheglov) Switch to loading the whole cycle maybe? + final Map<FileState, String> transitiveSignatures = {}; + + LibraryCycle(); + + LibraryCycle.external() : _transitiveSignature = '<external>'; + + /// Invalidate this cycle and any cycles that directly or indirectly use it. + /// + /// Practically invalidation means that we clear the library cycle in all the + /// [libraries] that share this [LibraryCycle] instance. + void invalidate() { + for (var library in libraries) { + library.internal_setLibraryCycle(null, null); + } + for (var user in _directUsers) { + user.invalidate(); + } + _directUsers.clear(); + } + + @override + String toString() { + return '[' + libraries.join(', ') + ']'; + } +} + +/// Node in [_LibraryWalker]. +class _LibraryNode extends graph.Node<_LibraryNode> { + final _LibraryWalker walker; + final FileState file; + + _LibraryNode(this.walker, this.file); + + @override + bool get isEvaluated => file.internal_libraryCycle != null; + + @override + List<_LibraryNode> computeDependencies() { + return file.directReferencedLibraries.map(walker.getNode).toList(); + } +} + +/// Helper that organizes dependencies of a library into topologically +/// sorted [LibraryCycle]s. +class _LibraryWalker extends graph.DependencyWalker<_LibraryNode> { + final Uint32List _linkedSalt; + final Map<FileState, _LibraryNode> nodesOfFiles = {}; + + _LibraryWalker(this._linkedSalt); + + @override + void evaluate(_LibraryNode v) { + evaluateScc([v]); + } + + @override + void evaluateScc(List<_LibraryNode> scc) { + var cycle = new LibraryCycle(); + + var signature = new ApiSignature(); + signature.addUint32List(_linkedSalt); + + // Sort libraries to produce stable signatures. + scc.sort((first, second) { + var firstPath = first.file.path; + var secondPath = second.file.path; + return firstPath.compareTo(secondPath); + }); + + // Append direct referenced cycles. + for (var node in scc) { + var file = node.file; + _appendDirectlyReferenced(cycle, signature, file.importedFiles); + _appendDirectlyReferenced(cycle, signature, file.exportedFiles); + } + + // Fill the cycle with libraries. + for (var node in scc) { + cycle.libraries.add(node.file); + + signature.addInt(node.file.libraryFiles.length); + for (var file in node.file.libraryFiles) { + signature.addBytes(file.apiSignature); + } + } + + // Compute the general library cycle signature. + cycle._transitiveSignature = signature.toHex(); + + // Compute library specific signatures. + for (var node in scc) { + var librarySignatureBuilder = new ApiSignature() + ..addString(node.file.uriStr) + ..addString(cycle._transitiveSignature); + var librarySignature = librarySignatureBuilder.toHex(); + + node.file.internal_setLibraryCycle( + cycle, + librarySignature, + ); + } + } + + _LibraryNode getNode(FileState file) { + return nodesOfFiles.putIfAbsent(file, () => new _LibraryNode(this, file)); + } + + void _appendDirectlyReferenced( + LibraryCycle cycle, + ApiSignature signature, + List<FileState> directlyReferenced, + ) { + signature.addInt(directlyReferenced.length); + for (var referencedLibrary in directlyReferenced) { + var referencedCycle = referencedLibrary.internal_libraryCycle; + + // We get null when the library is a part of the cycle being build. + if (referencedCycle == null) continue; + + if (cycle.directDependencies.add(referencedCycle)) { + referencedCycle._directUsers.add(cycle); + signature.addString(referencedCycle._transitiveSignature); + } + } + } +}
diff --git a/pkg/analyzer/lib/src/dart/analysis/restricted_analysis_context.dart b/pkg/analyzer/lib/src/dart/analysis/restricted_analysis_context.dart new file mode 100644 index 0000000..179ac05 --- /dev/null +++ b/pkg/analyzer/lib/src/dart/analysis/restricted_analysis_context.dart
@@ -0,0 +1,55 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:analyzer/dart/analysis/declared_variables.dart'; +import 'package:analyzer/src/context/context.dart'; +import 'package:analyzer/src/generated/engine.dart'; +import 'package:analyzer/src/generated/resolver.dart'; +import 'package:analyzer/src/generated/source.dart'; +import 'package:analyzer/src/generated/type_system.dart'; + +/// This class is a temporary step toward migrating Analyzer clients to the +/// new API. It guards against attempts to use any [AnalysisContext] +/// functionality (which is task based), except what we intend to expose +/// through the new API. +class RestrictedAnalysisContext implements AnalysisContextImpl { + @override + final AnalysisOptionsImpl analysisOptions; + + @override + final DeclaredVariables declaredVariables; + + @override + final SourceFactory sourceFactory; + + TypeProvider _typeProvider; + + TypeSystem _typeSystem; + + RestrictedAnalysisContext( + this.analysisOptions, this.declaredVariables, this.sourceFactory); + + @override + TypeProvider get typeProvider => _typeProvider; + + @override + set typeProvider(TypeProvider typeProvider) { + if (_typeProvider != null) { + throw StateError('TypeProvider can be set only once.'); + } + _typeProvider = typeProvider; + } + + @override + TypeSystem get typeSystem { + return _typeSystem ??= StrongTypeSystemImpl( + typeProvider, + implicitCasts: analysisOptions.implicitCasts, + ); + } + + noSuchMethod(Invocation invocation) { + return super.noSuchMethod(invocation); + } +}
diff --git a/pkg/analyzer/lib/src/dart/analysis/results.dart b/pkg/analyzer/lib/src/dart/analysis/results.dart index 2b9ac07..fd50c1c 100644 --- a/pkg/analyzer/lib/src/dart/analysis/results.dart +++ b/pkg/analyzer/lib/src/dart/analysis/results.dart
@@ -68,39 +68,62 @@ class ParsedLibraryResultImpl extends AnalysisResultImpl implements ParsedLibraryResult { @override - final ResultState state = ResultState.VALID; - - @override final List<ParsedUnitResult> units; ParsedLibraryResultImpl( AnalysisSession session, String path, Uri uri, this.units) : super(session, path, uri); + ParsedLibraryResultImpl.external(AnalysisSession session, Uri uri) + : this(session, null, uri, null); + @Deprecated('This factory exists temporary until AnalysisSession migration.') factory ParsedLibraryResultImpl.tmp(LibraryElement library) { - var libraryPath = library.source.fullName; - var analysisContext = library.context; - var units = <ParsedUnitResult>[]; - for (var unitElement in library.units) { - var unitSource = unitElement.source; + var session = library.session; + if (session != null) { + return session.getParsedLibraryByElement(library); + } else { + var analysisContext = library.context; + var units = <ParsedUnitResult>[]; + for (var unitElement in library.units) { + var unitSource = unitElement.source; - if (!analysisContext.exists(unitSource)) { - continue; + if (!analysisContext.exists(unitSource)) { + continue; + } + + var content = analysisContext.getContents(unitSource).data; + var lineInfo = analysisContext.getLineInfo(unitSource); + var unit = analysisContext.parseCompilationUnit(unitSource); + units.add(ParsedUnitResultImpl( + null, + unitSource.fullName, + unitSource.uri, + content, + lineInfo, + unitSource != library.source, + unit, const [])); } - - var content = analysisContext.getContents(unitSource).data; - var lineInfo = analysisContext.getLineInfo(unitSource); - var unit = analysisContext.parseCompilationUnit(unitSource); - units.add(ParsedUnitResultImpl(null, unitSource.fullName, unitSource.uri, - content, lineInfo, unitSource != library.source, unit, const [])); + var libraryPath = library.source.fullName; + return ParsedLibraryResultImpl( + null, libraryPath, library.source.uri, units); } - return ParsedLibraryResultImpl( - null, libraryPath, library.source.uri, units); + } + + @override + ResultState get state { + if (path == null) { + return ResultState.NOT_A_FILE; + } + return ResultState.VALID; } @override ElementDeclarationResult getElementDeclaration(Element element) { + if (state != ResultState.VALID) { + throw StateError('The result is not valid: $state'); + } + var elementPath = element.source.fullName; var unitResult = units.firstWhere( (r) => r.path == elementPath, @@ -190,25 +213,30 @@ @Deprecated('This method exists temporary until AnalysisSession migration.') static Future<ResolvedLibraryResult> tmp(LibraryElement library) async { - var libraryPath = library.source.fullName; - var units = <ResolvedUnitResult>[]; - var analysisContext = library.context; - for (var unitElement in library.units) { - var unitSource = unitElement.source; + var session = library.session; + if (session != null) { + return session.getResolvedLibraryByElement(library); + } else { + var units = <ResolvedUnitResult>[]; + var analysisContext = library.context; + for (var unitElement in library.units) { + var unitSource = unitElement.source; - if (!analysisContext.exists(unitSource)) { - continue; + if (!analysisContext.exists(unitSource)) { + continue; + } + + var path = unitSource.fullName; + var content = analysisContext.getContents(unitSource).data; + var lineInfo = analysisContext.getLineInfo(unitSource); + var unit = analysisContext.resolveCompilationUnit(unitSource, library); + units.add(ResolvedUnitResultImpl(null, path, unitSource.uri, true, + content, lineInfo, unitSource != library.source, unit, const [])); } - - var path = unitSource.fullName; - var content = analysisContext.getContents(unitSource).data; - var lineInfo = analysisContext.getLineInfo(unitSource); - var unit = analysisContext.resolveCompilationUnit(unitSource, library); - units.add(ResolvedUnitResultImpl(null, path, unitSource.uri, true, - content, lineInfo, unitSource != library.source, unit, const [])); + var libraryPath = library.source.fullName; + return ResolvedLibraryResultImpl(null, libraryPath, library.source.uri, + library, library.context.typeProvider, units); } - return ResolvedLibraryResultImpl(null, libraryPath, library.source.uri, - library, library.context.typeProvider, units); } }
diff --git a/pkg/analyzer/lib/src/dart/analysis/search.dart b/pkg/analyzer/lib/src/dart/analysis/search.dart index 9d1ff41..38f006e 100644 --- a/pkg/analyzer/lib/src/dart/analysis/search.dart +++ b/pkg/analyzer/lib/src/dart/analysis/search.dart
@@ -1,10 +1,11 @@ -// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file +// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. import 'dart:async'; import 'dart:collection'; +import 'package:analyzer/dart/analysis/results.dart'; import 'package:analyzer/dart/ast/ast.dart'; import 'package:analyzer/dart/ast/visitor.dart'; import 'package:analyzer/dart/element/element.dart'; @@ -654,10 +655,10 @@ LibraryElement libraryElement = element.library; for (CompilationUnitElement unitElement in libraryElement.units) { String unitPath = unitElement.source.fullName; - AnalysisResult unitAnalysisResult = await _driver.getResult(unitPath); + ResolvedUnitResult unitResult = await _driver.getResult(unitPath); _ImportElementReferencesVisitor visitor = new _ImportElementReferencesVisitor(element, unitElement); - unitAnalysisResult.unit.accept(visitor); + unitResult.unit.accept(visitor); results.addAll(visitor.results); } return results; @@ -675,8 +676,8 @@ List<SearchResult> results = <SearchResult>[]; for (CompilationUnitElement unitElement in element.units) { String unitPath = unitElement.source.fullName; - AnalysisResult unitAnalysisResult = await _driver.getResult(unitPath); - CompilationUnit unit = unitAnalysisResult.unit; + ResolvedUnitResult unitResult = await _driver.getResult(unitPath); + CompilationUnit unit = unitResult.unit; for (Directive directive in unit.directives) { if (directive is PartOfDirective && directive.element == element) { results.add(new SearchResult._( @@ -702,8 +703,8 @@ } // Prepare the unit. - AnalysisResult analysisResult = await _driver.getResult(path); - CompilationUnit unit = analysisResult.unit; + ResolvedUnitResult unitResult = await _driver.getResult(path); + CompilationUnit unit = unitResult.unit; if (unit == null) { return const <SearchResult>[]; } @@ -715,7 +716,7 @@ } // Prepare the enclosing node. - AstNode enclosingNode = node.getAncestor(isRootNode); + AstNode enclosingNode = node.thisOrAncestorMatching(isRootNode); if (enclosingNode == null) { return const <SearchResult>[]; } @@ -759,10 +760,10 @@ LibraryElement libraryElement = element.library; for (CompilationUnitElement unitElement in libraryElement.units) { String unitPath = unitElement.source.fullName; - AnalysisResult unitAnalysisResult = await _driver.getResult(unitPath); + ResolvedUnitResult unitResult = await _driver.getResult(unitPath); _LocalReferencesVisitor visitor = new _LocalReferencesVisitor(element, unitElement); - unitAnalysisResult.unit.accept(visitor); + unitResult.unit.accept(visitor); results.addAll(visitor.results); } return results;
diff --git a/pkg/analyzer/lib/src/dart/analysis/session.dart b/pkg/analyzer/lib/src/dart/analysis/session.dart index b44d556..7f1a46e 100644 --- a/pkg/analyzer/lib/src/dart/analysis/session.dart +++ b/pkg/analyzer/lib/src/dart/analysis/session.dart
@@ -4,6 +4,7 @@ import 'dart:async'; +import 'package:analyzer/dart/analysis/analysis_context.dart'; import 'package:analyzer/dart/analysis/declared_variables.dart'; import 'package:analyzer/dart/analysis/results.dart'; import 'package:analyzer/dart/analysis/session.dart'; @@ -51,6 +52,9 @@ AnalysisSessionImpl(this._driver); @override + AnalysisContext get analysisContext => _driver.analysisContext; + + @override DeclaredVariables get declaredVariables => _driver.declaredVariables; @override @@ -110,24 +114,36 @@ return libraryElement; } + @deprecated @override - Future<ParseResult> getParsedAst(String path) async { - // TODO(brianwilkerson) Determine whether this await is necessary. - await null; - return getParsedAstSync(path); + Future<ParseResult> getParsedAst(String path) async => getParsedUnit(path); + + @deprecated + @override + ParseResult getParsedAstSync(String path) => getParsedUnit(path); + + @override + ParsedLibraryResult getParsedLibrary(String path) { + _checkConsistency(); + return _driver.getParsedLibrary(path); } @override - ParseResult getParsedAstSync(String path) { + ParsedLibraryResult getParsedLibraryByElement(LibraryElement element) { + _checkConsistency(); + _checkElementOfThisSession(element); + return _driver.getParsedLibraryByUri(element.source.uri); + } + + @override + ParsedUnitResult getParsedUnit(String path) { _checkConsistency(); return _driver.parseFileSync(path); } + @deprecated @override - Future<ResolveResult> getResolvedAst(String path) { - _checkConsistency(); - return _driver.getResult(path); - } + Future<ResolveResult> getResolvedAst(String path) => getResolvedUnit(path); @override Future<ResolvedLibraryResult> getResolvedLibrary(String path) { @@ -144,6 +160,12 @@ } @override + Future<ResolvedUnitResult> getResolvedUnit(String path) { + _checkConsistency(); + return _driver.getResult(path); + } + + @override Future<SourceKind> getSourceKind(String path) { _checkConsistency(); return _driver.getSourceKind(path); @@ -179,11 +201,10 @@ } void _checkElementOfThisSession(Element element) { - // TODO(scheglov) Requires 2.2 implementation -// if (element.session != this) { -// throw new ArgumentError( -// '(${element.runtimeType}) $element was not produced by ' -// 'this session.'); -// } + if (element.session != this) { + throw new ArgumentError( + '(${element.runtimeType}) $element was not produced by ' + 'this session.'); + } } }
diff --git a/pkg/analyzer/lib/src/dart/analysis/session_helper.dart b/pkg/analyzer/lib/src/dart/analysis/session_helper.dart index e35ec6a..9692a26 100644 --- a/pkg/analyzer/lib/src/dart/analysis/session_helper.dart +++ b/pkg/analyzer/lib/src/dart/analysis/session_helper.dart
@@ -4,6 +4,7 @@ import 'dart:async'; +import 'package:analyzer/dart/analysis/results.dart'; import 'package:analyzer/dart/analysis/session.dart'; import 'package:analyzer/dart/element/element.dart'; @@ -15,14 +16,14 @@ class AnalysisSessionHelper { final AnalysisSession session; + final Map<String, ResolvedLibraryResult> _resolvedLibraries = {}; + AnalysisSessionHelper(this.session); /// Return the [ClassElement] with the given [className] that is exported /// from the library with the given [libraryUri], or `null` if the library /// does not export a class with such name. Future<ClassElement> getClass(String libraryUri, String className) async { - // TODO(brianwilkerson) Determine whether this await is necessary. - await null; var libraryElement = await session.getLibraryByUri(libraryUri); var element = libraryElement.exportNamespace.get(className); if (element is ClassElement) { @@ -32,13 +33,31 @@ } } + /// Return the declaration of the [element], or `null` is the [element] + /// is synthetic. + Future<ElementDeclarationResult> getElementDeclaration( + Element element) async { + var libraryPath = element.library.source.fullName; + var resolvedLibrary = await _getResolvedLibrary(libraryPath); + return resolvedLibrary.getElementDeclaration(element); + } + + /// Return the resolved unit that declares the given [element]. + Future<ResolvedUnitResult> getResolvedUnitByElement(Element element) async { + var libraryPath = element.library.source.fullName; + var resolvedLibrary = await _getResolvedLibrary(libraryPath); + + var unitPath = element.source.fullName; + return resolvedLibrary.units.singleWhere((resolvedUnit) { + return resolvedUnit.path == unitPath; + }); + } + /// Return the [PropertyAccessorElement] with the given [name] that is /// exported from the library with the given [uri], or `null` if the /// library does not export a top-level accessor with such name. Future<PropertyAccessorElement> getTopLevelPropertyAccessor( String uri, String name) async { - // TODO(brianwilkerson) Determine whether this await is necessary. - await null; var libraryElement = await session.getLibraryByUri(uri); var element = libraryElement.exportNamespace.get(name); if (element is PropertyAccessorElement) { @@ -47,4 +66,14 @@ return null; } } + + /// Return a newly resolved, or cached library with the given [path]. + Future<ResolvedLibraryResult> _getResolvedLibrary(String path) async { + var result = _resolvedLibraries[path]; + if (result == null) { + result = await session.getResolvedLibrary(path); + _resolvedLibraries[path] = result; + } + return result; + } }
diff --git a/pkg/analyzer/lib/src/dart/analysis/uri_converter.dart b/pkg/analyzer/lib/src/dart/analysis/uri_converter.dart index df11c02..da33b5a 100644 --- a/pkg/analyzer/lib/src/dart/analysis/uri_converter.dart +++ b/pkg/analyzer/lib/src/dart/analysis/uri_converter.dart
@@ -18,8 +18,8 @@ final AnalysisDriver driver; /** - * Initialize a newly created URI converter to use the given [context] and - * [driver] to perform the conversions. + * Initialize a newly created URI converter to use the given [driver] to = + * perform the conversions. */ DriverBasedUriConverter(this.driver);
diff --git a/pkg/analyzer/lib/src/dart/ast/ast.dart b/pkg/analyzer/lib/src/dart/ast/ast.dart index 3db5ed9..b328a9a 100644 --- a/pkg/analyzer/lib/src/dart/ast/ast.dart +++ b/pkg/analyzer/lib/src/dart/ast/ast.dart
@@ -1,4 +1,4 @@ -// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file +// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. @@ -939,6 +939,15 @@ } @override + T thisOrAncestorOfType<T extends AstNode>() { + AstNode node = this; + while (node != null && node is! T) { + node = node.parent; + } + return node as T; + } + + @override String toSource() { StringBuffer buffer = new StringBuffer(); accept(new ToSourceVisitor2(buffer)); @@ -1596,7 +1605,7 @@ /** * Helper class to allow iteration of child entities of an AST node. */ -class ChildEntities extends Object +class ChildEntities with IterableMixin<SyntacticEntity> implements Iterable<SyntacticEntity> { /** @@ -2687,17 +2696,21 @@ if (errorCode is CompileTimeErrorCode) { switch (errorCode) { case CompileTimeErrorCode.CONST_EVAL_TYPE_BOOL: + case CompileTimeErrorCode.CONST_EVAL_TYPE_BOOL_INT: case CompileTimeErrorCode.CONST_EVAL_TYPE_BOOL_NUM_STRING: case CompileTimeErrorCode.CONST_EVAL_TYPE_INT: case CompileTimeErrorCode.CONST_EVAL_TYPE_NUM: case CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION: case CompileTimeErrorCode.CONST_EVAL_THROWS_IDBZE: + case CompileTimeErrorCode.CONST_WITH_NON_CONST: case CompileTimeErrorCode.CONST_WITH_NON_CONSTANT_ARGUMENT: case CompileTimeErrorCode.NON_CONSTANT_VALUE_IN_INITIALIZER: case CompileTimeErrorCode .CONST_CONSTRUCTOR_WITH_FIELD_INITIALIZED_BY_NON_CONST: case CompileTimeErrorCode.INVALID_CONSTANT: case CompileTimeErrorCode.MISSING_CONST_IN_LIST_LITERAL: + case CompileTimeErrorCode.MISSING_CONST_IN_MAP_LITERAL: + case CompileTimeErrorCode.MISSING_CONST_IN_SET_LITERAL: hasConstError = true; } } @@ -6394,8 +6407,6 @@ * * newExpression ::= * ('new' | 'const')? [TypeName] ('.' [SimpleIdentifier])? [ArgumentList] - * - * 'new' | 'const' are only optional if the previewDart2 option is enabled. */ class InstanceCreationExpressionImpl extends ExpressionImpl implements InstanceCreationExpression { @@ -6487,8 +6498,6 @@ /** * Return `true` if this is an implicit constructor invocations. - * - * This can only be `true` when the previewDart2 option is enabled. */ bool get isImplicit => keyword == null; @@ -6531,7 +6540,10 @@ * * Also note that this method can cause constant evaluation to occur, which * can be computationally expensive. + * + * Deprecated: Use `LinterContext.canBeConst` instead. */ + @deprecated bool canBeConst() { // // Verify that the invoked constructor is a const constructor. @@ -8252,9 +8264,7 @@ /** * A list of AST nodes that have a common parent. */ -class NodeListImpl<E extends AstNode> extends Object - with ListMixin<E> - implements NodeList<E> { +class NodeListImpl<E extends AstNode> with ListMixin<E> implements NodeList<E> { /** * The node that is the parent of each of the elements in the list. */ @@ -9460,6 +9470,78 @@ } /** + * A literal set. + * + * setLiteral ::= + * 'const'? ('<' [TypeAnnotation] '>')? + * '{' [Expression] (',' [Expression])* ','? '}' + * | 'const'? ('<' [TypeAnnotation] '>')? '{' '}' + */ +class SetLiteralImpl extends TypedLiteralImpl implements SetLiteral { + /** + * The left curly bracket. + */ + @override + Token leftBracket; + + /** + * The elements in the set. + */ + NodeList<Expression> _elements; + + /** + * The right curly bracket. + */ + @override + Token rightBracket; + + /** + * Initialize a newly created set literal. The [constKeyword] can be `null` if + * the literal is not a constant. The [typeArguments] can be `null` if no type + * arguments were declared. The [elements] can be `null` if the set is empty. + */ + SetLiteralImpl(Token constKeyword, TypeArgumentListImpl typeArguments, + this.leftBracket, List<Expression> elements, this.rightBracket) + : super(constKeyword, typeArguments) { + _elements = new NodeListImpl<Expression>(this, elements); + } + + @override + Token get beginToken { + if (constKeyword != null) { + return constKeyword; + } + TypeArgumentList typeArguments = this.typeArguments; + if (typeArguments != null) { + return typeArguments.beginToken; + } + return leftBracket; + } + + @override + // TODO(paulberry): add commas. + Iterable<SyntacticEntity> get childEntities => super._childEntities + ..add(leftBracket) + ..addAll(elements) + ..add(rightBracket); + + @override + NodeList<Expression> get elements => _elements; + + @override + Token get endToken => rightBracket; + + @override + E accept<E>(AstVisitor<E> visitor) => visitor.visitSetLiteral(this); + + @override + void visitChildren(AstVisitor visitor) { + super.visitChildren(visitor); + _elements.accept(visitor); + } +} + +/** * A combinator that restricts the names being imported to those in a given list. * * showCombinator ::=
diff --git a/pkg/analyzer/lib/src/dart/ast/ast_factory.dart b/pkg/analyzer/lib/src/dart/ast/ast_factory.dart index 6a3c3b5..d12b7a6 100644 --- a/pkg/analyzer/lib/src/dart/ast/ast_factory.dart +++ b/pkg/analyzer/lib/src/dart/ast/ast_factory.dart
@@ -832,6 +832,12 @@ ScriptTag scriptTag(Token scriptTag) => new ScriptTagImpl(scriptTag); @override + SetLiteral setLiteral(Token constKeyword, TypeArgumentList typeArguments, + Token leftBracket, List<Expression> elements, Token rightBracket) => + new SetLiteralImpl( + constKeyword, typeArguments, leftBracket, elements, rightBracket); + + @override ShowCombinator showCombinator( Token keyword, List<SimpleIdentifier> shownNames) => new ShowCombinatorImpl(keyword, shownNames);
diff --git a/pkg/analyzer/lib/src/dart/ast/utilities.dart b/pkg/analyzer/lib/src/dart/ast/utilities.dart index f7e6832..2370ed0 100644 --- a/pkg/analyzer/lib/src/dart/ast/utilities.dart +++ b/pkg/analyzer/lib/src/dart/ast/utilities.dart
@@ -1,4 +1,4 @@ -// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file +// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. @@ -845,6 +845,14 @@ astFactory.scriptTag(cloneToken(node.scriptTag)); @override + SetLiteral visitSetLiteral(SetLiteral node) => astFactory.setLiteral( + cloneToken(node.constKeyword), + cloneNode(node.typeArguments), + cloneToken(node.leftBracket), + cloneNodeList(node.elements), + cloneToken(node.rightBracket)); + + @override ShowCombinator visitShowCombinator(ShowCombinator node) => astFactory .showCombinator(cloneToken(node.keyword), cloneNodeList(node.shownNames)); @@ -1988,6 +1996,16 @@ } @override + bool visitSetLiteral(SetLiteral node) { + SetLiteral other = _other as SetLiteral; + return isEqualTokens(node.constKeyword, other.constKeyword) && + isEqualNodes(node.typeArguments, other.typeArguments) && + isEqualTokens(node.leftBracket, other.leftBracket) && + _isEqualNodeLists(node.elements, other.elements) && + isEqualTokens(node.rightBracket, other.rightBracket); + } + + @override bool visitShowCombinator(ShowCombinator node) { ShowCombinator other = _other as ShowCombinator; return isEqualTokens(node.keyword, other.keyword) && @@ -2633,7 +2651,7 @@ * * See [PrefixedIdentifier.isDeferred]. */ -class DeferredLibraryReferenceDetector extends RecursiveAstVisitor<Object> { +class DeferredLibraryReferenceDetector extends RecursiveAstVisitor<void> { /** * A flag indicating whether an identifier from a deferred library has been * found. @@ -2647,13 +2665,12 @@ bool get result => _result; @override - Object visitPrefixedIdentifier(PrefixedIdentifier node) { + void visitPrefixedIdentifier(PrefixedIdentifier node) { if (!_result) { if (node.isDeferred) { _result = true; } } - return null; } } @@ -3713,6 +3730,18 @@ astFactory.scriptTag(_mapToken(node.scriptTag)); @override + SetLiteral visitSetLiteral(SetLiteral node) { + SetLiteral copy = astFactory.setLiteral( + _mapToken(node.constKeyword), + _cloneNode(node.typeArguments), + _mapToken(node.leftBracket), + _cloneNodeList(node.elements), + _mapToken(node.rightBracket)); + copy.staticType = node.staticType; + return copy; + } + + @override ShowCombinator visitShowCombinator(ShowCombinator node) => astFactory .showCombinator(_mapToken(node.keyword), _cloneNodeList(node.shownNames)); @@ -3959,7 +3988,7 @@ * the [AstNode] with the shortest length whose source range completely * encompasses the specified range. */ -class NodeLocator extends UnifyingAstVisitor<Object> { +class NodeLocator extends UnifyingAstVisitor<void> { /** * The start offset of the range used to identify the node. */ @@ -4012,10 +4041,10 @@ } @override - Object visitNode(AstNode node) { + void visitNode(AstNode node) { // Don't visit a new tree if the result has been already found. if (_foundNode != null) { - return null; + return; } // Check whether the current node covers the selection. Token beginToken = node.beginToken; @@ -4032,11 +4061,8 @@ } int end = endToken.end; int start = node.offset; - if (end < _startOffset) { - return null; - } - if (start > _endOffset) { - return null; + if (end < _startOffset || start > _endOffset) { + return; } // Check children. try { @@ -4050,13 +4076,12 @@ } // Found a child. if (_foundNode != null) { - return null; + return; } // Check this node. if (start <= _startOffset && _endOffset <= end) { _foundNode = node; } - return null; } } @@ -4065,7 +4090,7 @@ * More specifically, they will return the deepest [AstNode] which completely * encompasses the specified range. */ -class NodeLocator2 extends UnifyingAstVisitor<Object> { +class NodeLocator2 extends UnifyingAstVisitor<void> { /** * The inclusive start offset of the range used to identify the node. */ @@ -4112,10 +4137,10 @@ } @override - Object visitNode(AstNode node) { + void visitNode(AstNode node) { // Don't visit a new tree if the result has been already found. if (_foundNode != null) { - return null; + return; } // Check whether the current node covers the selection. Token beginToken = node.beginToken; @@ -4132,11 +4157,8 @@ } int end = endToken.end; int start = node.offset; - if (end <= _startOffset) { - return null; - } - if (start > _endOffset) { - return null; + if (end <= _startOffset || start > _endOffset) { + return; } // Check children. try { @@ -4150,13 +4172,12 @@ } // Found a child. if (_foundNode != null) { - return null; + return; } // Check this node. if (start <= _startOffset && _endOffset < end) { _foundNode = node; } - return null; } } @@ -5164,6 +5185,14 @@ bool visitScriptTag(ScriptTag scriptTag) => visitNode(scriptTag); @override + bool visitSetLiteral(SetLiteral node) { + if (_replaceInList(node.elements)) { + return true; + } + return visitTypedLiteral(node); + } + + @override bool visitShowCombinator(ShowCombinator node) { if (_replaceInList(node.shownNames)) { return true; @@ -6494,6 +6523,21 @@ } @override + bool visitSetLiteral(SetLiteral node) { + SetLiteral toNode = this._toNode as SetLiteral; + if (_and( + _isEqualTokens(node.constKeyword, toNode.constKeyword), + _isEqualNodes(node.typeArguments, toNode.typeArguments), + _isEqualTokens(node.leftBracket, toNode.leftBracket), + _isEqualNodeLists(node.elements, toNode.elements), + _isEqualTokens(node.rightBracket, toNode.rightBracket))) { + toNode.staticType = node.staticType; + return true; + } + return false; + } + + @override bool visitShowCombinator(ShowCombinator node) { ShowCombinator toNode = this._toNode as ShowCombinator; return _and(_isEqualTokens(node.keyword, toNode.keyword), @@ -6893,7 +6937,7 @@ * Completion test code coverage is 95%. The two basic blocks that are not * executed cannot be executed. They are included for future reference. */ -class ScopedNameFinder extends GeneralizingAstVisitor<Object> { +class ScopedNameFinder extends GeneralizingAstVisitor<void> { Declaration _declarationNode; AstNode _immediateChild; @@ -6912,112 +6956,104 @@ Map<String, SimpleIdentifier> get locals => _locals; @override - Object visitBlock(Block node) { + void visitBlock(Block node) { _checkStatements(node.statements); - return super.visitBlock(node); + super.visitBlock(node); } @override - Object visitCatchClause(CatchClause node) { + void visitCatchClause(CatchClause node) { _addToScope(node.exceptionParameter); _addToScope(node.stackTraceParameter); - return super.visitCatchClause(node); + super.visitCatchClause(node); } @override - Object visitConstructorDeclaration(ConstructorDeclaration node) { + void visitConstructorDeclaration(ConstructorDeclaration node) { if (!identical(_immediateChild, node.parameters)) { _addParameters(node.parameters.parameters); } _declarationNode = node; - return null; } @override - Object visitFieldDeclaration(FieldDeclaration node) { + void visitFieldDeclaration(FieldDeclaration node) { _declarationNode = node; - return null; } @override - Object visitForEachStatement(ForEachStatement node) { + void visitForEachStatement(ForEachStatement node) { DeclaredIdentifier loopVariable = node.loopVariable; if (loopVariable != null) { _addToScope(loopVariable.identifier); } - return super.visitForEachStatement(node); + super.visitForEachStatement(node); } @override - Object visitForStatement(ForStatement node) { + void visitForStatement(ForStatement node) { if (!identical(_immediateChild, node.variables) && node.variables != null) { _addVariables(node.variables.variables); } - return super.visitForStatement(node); + super.visitForStatement(node); } @override - Object visitFunctionDeclaration(FunctionDeclaration node) { + void visitFunctionDeclaration(FunctionDeclaration node) { if (node.parent is! FunctionDeclarationStatement) { _declarationNode = node; - return null; + } else { + super.visitFunctionDeclaration(node); } - return super.visitFunctionDeclaration(node); } @override - Object visitFunctionDeclarationStatement(FunctionDeclarationStatement node) { + void visitFunctionDeclarationStatement(FunctionDeclarationStatement node) { _referenceIsWithinLocalFunction = true; - return super.visitFunctionDeclarationStatement(node); + super.visitFunctionDeclarationStatement(node); } @override - Object visitFunctionExpression(FunctionExpression node) { + void visitFunctionExpression(FunctionExpression node) { if (node.parameters != null && !identical(_immediateChild, node.parameters)) { _addParameters(node.parameters.parameters); } - return super.visitFunctionExpression(node); + super.visitFunctionExpression(node); } @override - Object visitMethodDeclaration(MethodDeclaration node) { + void visitMethodDeclaration(MethodDeclaration node) { _declarationNode = node; - if (node.parameters == null) { - return null; - } - if (!identical(_immediateChild, node.parameters)) { + if (node.parameters != null && + !identical(_immediateChild, node.parameters)) { _addParameters(node.parameters.parameters); } - return null; } @override - Object visitNode(AstNode node) { + void visitNode(AstNode node) { _immediateChild = node; AstNode parent = node.parent; if (parent != null) { parent.accept(this); } - return null; } @override - Object visitSwitchMember(SwitchMember node) { + void visitSwitchMember(SwitchMember node) { _checkStatements(node.statements); - return super.visitSwitchMember(node); + super.visitSwitchMember(node); } @override - Object visitTopLevelVariableDeclaration(TopLevelVariableDeclaration node) { + void visitTopLevelVariableDeclaration(TopLevelVariableDeclaration node) { _declarationNode = node; - return null; } @override - Object visitTypeAlias(TypeAlias node) { + void visitTypeAlias(TypeAlias node) { _declarationNode = node; - return null; } void _addParameters(NodeList<FormalParameter> vars) { @@ -7076,7 +7112,7 @@ * This class has been deprecated. Use the class ToSourceVisitor2 instead. */ @deprecated -class ToSourceVisitor implements AstVisitor<Object> { +class ToSourceVisitor implements AstVisitor<void> { /** * The writer to which the source is to be written. */ @@ -7089,38 +7125,34 @@ ToSourceVisitor(this._writer); @override - Object visitAdjacentStrings(AdjacentStrings node) { + void visitAdjacentStrings(AdjacentStrings node) { _visitNodeListWithSeparator(node.strings, " "); - return null; } @override - Object visitAnnotation(Annotation node) { + void visitAnnotation(Annotation node) { _writer.print('@'); _visitNode(node.name); _visitNodeWithPrefix(".", node.constructorName); _visitNode(node.arguments); - return null; } @override - Object visitArgumentList(ArgumentList node) { + void visitArgumentList(ArgumentList node) { _writer.print('('); _visitNodeListWithSeparator(node.arguments, ", "); _writer.print(')'); - return null; } @override - Object visitAsExpression(AsExpression node) { + void visitAsExpression(AsExpression node) { _visitNode(node.expression); _writer.print(" as "); _visitNode(node.type); - return null; } @override - bool visitAssertInitializer(AssertInitializer node) { + void visitAssertInitializer(AssertInitializer node) { _writer.print("assert ("); _visitNode(node.condition); if (node.message != null) { @@ -7128,11 +7160,10 @@ _visitNode(node.message); } _writer.print(")"); - return null; } @override - Object visitAssertStatement(AssertStatement node) { + void visitAssertStatement(AssertStatement node) { _writer.print("assert ("); _visitNode(node.condition); if (node.message != null) { @@ -7140,46 +7171,41 @@ _visitNode(node.message); } _writer.print(");"); - return null; } @override - Object visitAssignmentExpression(AssignmentExpression node) { + void visitAssignmentExpression(AssignmentExpression node) { _visitNode(node.leftHandSide); _writer.print(' '); _writer.print(node.operator.lexeme); _writer.print(' '); _visitNode(node.rightHandSide); - return null; } @override - Object visitAwaitExpression(AwaitExpression node) { + void visitAwaitExpression(AwaitExpression node) { _writer.print("await "); _visitNode(node.expression); - return null; } @override - Object visitBinaryExpression(BinaryExpression node) { + void visitBinaryExpression(BinaryExpression node) { _visitNode(node.leftOperand); _writer.print(' '); _writer.print(node.operator.lexeme); _writer.print(' '); _visitNode(node.rightOperand); - return null; } @override - Object visitBlock(Block node) { + void visitBlock(Block node) { _writer.print('{'); _visitNodeListWithSeparator(node.statements, " "); _writer.print('}'); - return null; } @override - Object visitBlockFunctionBody(BlockFunctionBody node) { + void visitBlockFunctionBody(BlockFunctionBody node) { Token keyword = node.keyword; if (keyword != null) { _writer.print(keyword.lexeme); @@ -7189,32 +7215,28 @@ _writer.print(' '); } _visitNode(node.block); - return null; } @override - Object visitBooleanLiteral(BooleanLiteral node) { + void visitBooleanLiteral(BooleanLiteral node) { _writer.print(node.literal.lexeme); - return null; } @override - Object visitBreakStatement(BreakStatement node) { + void visitBreakStatement(BreakStatement node) { _writer.print("break"); _visitNodeWithPrefix(" ", node.label); _writer.print(";"); - return null; } @override - Object visitCascadeExpression(CascadeExpression node) { + void visitCascadeExpression(CascadeExpression node) { _visitNode(node.target); _visitNodeList(node.cascadeSections); - return null; } @override - Object visitCatchClause(CatchClause node) { + void visitCatchClause(CatchClause node) { _visitNodeWithPrefix("on ", node.exceptionType); if (node.catchKeyword != null) { if (node.exceptionType != null) { @@ -7228,11 +7250,10 @@ _writer.print(" "); } _visitNode(node.body); - return null; } @override - Object visitClassDeclaration(ClassDeclaration node) { + void visitClassDeclaration(ClassDeclaration node) { _visitNodeListWithSeparatorAndSuffix(node.metadata, " ", " "); _visitTokenWithSuffix(node.abstractKeyword, " "); _writer.print("class "); @@ -7244,11 +7265,10 @@ _writer.print(" {"); _visitNodeListWithSeparator(node.members, " "); _writer.print("}"); - return null; } @override - Object visitClassTypeAlias(ClassTypeAlias node) { + void visitClassTypeAlias(ClassTypeAlias node) { _visitNodeListWithSeparatorAndSuffix(node.metadata, " ", " "); if (node.abstractKeyword != null) { _writer.print("abstract "); @@ -7261,17 +7281,16 @@ _visitNodeWithPrefix(" ", node.withClause); _visitNodeWithPrefix(" ", node.implementsClause); _writer.print(";"); - return null; } @override - Object visitComment(Comment node) => null; + void visitComment(Comment node) {} @override - Object visitCommentReference(CommentReference node) => null; + void visitCommentReference(CommentReference node) {} @override - Object visitCompilationUnit(CompilationUnit node) { + void visitCompilationUnit(CompilationUnit node) { ScriptTag scriptTag = node.scriptTag; NodeList<Directive> directives = node.directives; _visitNode(scriptTag); @@ -7279,31 +7298,28 @@ _visitNodeListWithSeparatorAndPrefix(prefix, directives, " "); prefix = scriptTag == null && directives.isEmpty ? "" : " "; _visitNodeListWithSeparatorAndPrefix(prefix, node.declarations, " "); - return null; } @override - Object visitConditionalExpression(ConditionalExpression node) { + void visitConditionalExpression(ConditionalExpression node) { _visitNode(node.condition); _writer.print(" ? "); _visitNode(node.thenExpression); _writer.print(" : "); _visitNode(node.elseExpression); - return null; } @override - Object visitConfiguration(Configuration node) { + void visitConfiguration(Configuration node) { _writer.print('if ('); _visitNode(node.name); _visitNodeWithPrefix(" == ", node.value); _writer.print(') '); _visitNode(node.uri); - return null; } @override - Object visitConstructorDeclaration(ConstructorDeclaration node) { + void visitConstructorDeclaration(ConstructorDeclaration node) { _visitNodeListWithSeparatorAndSuffix(node.metadata, " ", " "); _visitTokenWithSuffix(node.externalKeyword, " "); _visitTokenWithSuffix(node.constKeyword, " "); @@ -7314,44 +7330,39 @@ _visitNodeListWithSeparatorAndPrefix(" : ", node.initializers, ", "); _visitNodeWithPrefix(" = ", node.redirectedConstructor); _visitFunctionWithPrefix(" ", node.body); - return null; } @override - Object visitConstructorFieldInitializer(ConstructorFieldInitializer node) { + void visitConstructorFieldInitializer(ConstructorFieldInitializer node) { _visitTokenWithSuffix(node.thisKeyword, "."); _visitNode(node.fieldName); _writer.print(" = "); _visitNode(node.expression); - return null; } @override - Object visitConstructorName(ConstructorName node) { + void visitConstructorName(ConstructorName node) { _visitNode(node.type); _visitNodeWithPrefix(".", node.name); - return null; } @override - Object visitContinueStatement(ContinueStatement node) { + void visitContinueStatement(ContinueStatement node) { _writer.print("continue"); _visitNodeWithPrefix(" ", node.label); _writer.print(";"); - return null; } @override - Object visitDeclaredIdentifier(DeclaredIdentifier node) { + void visitDeclaredIdentifier(DeclaredIdentifier node) { _visitNodeListWithSeparatorAndSuffix(node.metadata, " ", " "); _visitTokenWithSuffix(node.keyword, " "); _visitNodeWithSuffix(node.type, " "); _visitNode(node.identifier); - return null; } @override - Object visitDefaultFormalParameter(DefaultFormalParameter node) { + void visitDefaultFormalParameter(DefaultFormalParameter node) { _visitNode(node.parameter); if (node.separator != null) { if (node.separator.lexeme != ":") { @@ -7360,73 +7371,64 @@ _writer.print(node.separator.lexeme); _visitNodeWithPrefix(" ", node.defaultValue); } - return null; } @override - Object visitDoStatement(DoStatement node) { + void visitDoStatement(DoStatement node) { _writer.print("do "); _visitNode(node.body); _writer.print(" while ("); _visitNode(node.condition); _writer.print(");"); - return null; } @override - Object visitDottedName(DottedName node) { + void visitDottedName(DottedName node) { _visitNodeListWithSeparator(node.components, "."); - return null; } @override - Object visitDoubleLiteral(DoubleLiteral node) { + void visitDoubleLiteral(DoubleLiteral node) { _writer.print(node.literal.lexeme); - return null; } @override - Object visitEmptyFunctionBody(EmptyFunctionBody node) { + void visitEmptyFunctionBody(EmptyFunctionBody node) { _writer.print(';'); - return null; } @override - Object visitEmptyStatement(EmptyStatement node) { + void visitEmptyStatement(EmptyStatement node) { _writer.print(';'); - return null; } @override - Object visitEnumConstantDeclaration(EnumConstantDeclaration node) { + void visitEnumConstantDeclaration(EnumConstantDeclaration node) { _visitNodeListWithSeparatorAndSuffix(node.metadata, " ", " "); _visitNode(node.name); - return null; } @override - Object visitEnumDeclaration(EnumDeclaration node) { + void visitEnumDeclaration(EnumDeclaration node) { _visitNodeListWithSeparatorAndSuffix(node.metadata, " ", " "); _writer.print("enum "); _visitNode(node.name); _writer.print(" {"); _visitNodeListWithSeparator(node.constants, ", "); _writer.print("}"); - return null; } @override - Object visitExportDirective(ExportDirective node) { + void visitExportDirective(ExportDirective node) { _visitNodeListWithSeparatorAndSuffix(node.metadata, " ", " "); _writer.print("export "); _visitNode(node.uri); _visitNodeListWithSeparatorAndPrefix(" ", node.combinators, " "); _writer.print(';'); - return null; } @override - Object visitExpressionFunctionBody(ExpressionFunctionBody node) { + void visitExpressionFunctionBody(ExpressionFunctionBody node) { Token keyword = node.keyword; if (keyword != null) { _writer.print(keyword.lexeme); @@ -7437,34 +7439,30 @@ if (node.semicolon != null) { _writer.print(';'); } - return null; } @override - Object visitExpressionStatement(ExpressionStatement node) { + void visitExpressionStatement(ExpressionStatement node) { _visitNode(node.expression); _writer.print(';'); - return null; } @override - Object visitExtendsClause(ExtendsClause node) { + void visitExtendsClause(ExtendsClause node) { _writer.print("extends "); _visitNode(node.superclass); - return null; } @override - Object visitFieldDeclaration(FieldDeclaration node) { + void visitFieldDeclaration(FieldDeclaration node) { _visitNodeListWithSeparatorAndSuffix(node.metadata, " ", " "); _visitTokenWithSuffix(node.staticKeyword, " "); _visitNode(node.fields); _writer.print(";"); - return null; } @override - Object visitFieldFormalParameter(FieldFormalParameter node) { + void visitFieldFormalParameter(FieldFormalParameter node) { _visitNodeListWithSeparatorAndSuffix(node.metadata, ' ', ' '); _visitTokenWithSuffix(node.covariantKeyword, ' '); _visitTokenWithSuffix(node.keyword, " "); @@ -7473,11 +7471,10 @@ _visitNode(node.identifier); _visitNode(node.typeParameters); _visitNode(node.parameters); - return null; } @override - Object visitForEachStatement(ForEachStatement node) { + void visitForEachStatement(ForEachStatement node) { DeclaredIdentifier loopVariable = node.loopVariable; if (node.awaitKeyword != null) { _writer.print("await "); @@ -7492,11 +7489,10 @@ _visitNode(node.iterable); _writer.print(") "); _visitNode(node.body); - return null; } @override - Object visitFormalParameterList(FormalParameterList node) { + void visitFormalParameterList(FormalParameterList node) { String groupEnd = null; _writer.print('('); NodeList<FormalParameter> parameters = node.parameters; @@ -7521,11 +7517,10 @@ _writer.print(groupEnd); } _writer.print(')'); - return null; } @override - Object visitForStatement(ForStatement node) { + void visitForStatement(ForStatement node) { Expression initialization = node.initialization; _writer.print("for ("); if (initialization != null) { @@ -7539,47 +7534,42 @@ _visitNodeListWithSeparatorAndPrefix(" ", node.updaters, ", "); _writer.print(") "); _visitNode(node.body); - return null; } @override - Object visitFunctionDeclaration(FunctionDeclaration node) { + void visitFunctionDeclaration(FunctionDeclaration node) { _visitNodeListWithSeparatorAndSuffix(node.metadata, " ", " "); _visitTokenWithSuffix(node.externalKeyword, " "); _visitNodeWithSuffix(node.returnType, " "); _visitTokenWithSuffix(node.propertyKeyword, " "); _visitNode(node.name); _visitNode(node.functionExpression); - return null; } @override - Object visitFunctionDeclarationStatement(FunctionDeclarationStatement node) { + void visitFunctionDeclarationStatement(FunctionDeclarationStatement node) { _visitNode(node.functionDeclaration); - return null; } @override - Object visitFunctionExpression(FunctionExpression node) { + void visitFunctionExpression(FunctionExpression node) { _visitNode(node.typeParameters); _visitNode(node.parameters); if (node.body is! EmptyFunctionBody) { _writer.print(' '); } _visitNode(node.body); - return null; } @override - Object visitFunctionExpressionInvocation(FunctionExpressionInvocation node) { + void visitFunctionExpressionInvocation(FunctionExpressionInvocation node) { _visitNode(node.function); _visitNode(node.typeArguments); _visitNode(node.argumentList); - return null; } @override - Object visitFunctionTypeAlias(FunctionTypeAlias node) { + void visitFunctionTypeAlias(FunctionTypeAlias node) { _visitNodeListWithSeparatorAndSuffix(node.metadata, " ", " "); _writer.print("typedef "); _visitNodeWithSuffix(node.returnType, " "); @@ -7587,66 +7577,59 @@ _visitNode(node.typeParameters); _visitNode(node.parameters); _writer.print(";"); - return null; } @override - Object visitFunctionTypedFormalParameter(FunctionTypedFormalParameter node) { + void visitFunctionTypedFormalParameter(FunctionTypedFormalParameter node) { _visitNodeListWithSeparatorAndSuffix(node.metadata, ' ', ' '); _visitTokenWithSuffix(node.covariantKeyword, ' '); _visitNodeWithSuffix(node.returnType, " "); _visitNode(node.identifier); _visitNode(node.typeParameters); _visitNode(node.parameters); - return null; } @override - Object visitGenericFunctionType(GenericFunctionType node) { + void visitGenericFunctionType(GenericFunctionType node) { _visitNode(node.returnType); _writer.print(' Function'); _visitNode(node.typeParameters); _visitNode(node.parameters); - return null; } @override - Object visitGenericTypeAlias(GenericTypeAlias node) { + void visitGenericTypeAlias(GenericTypeAlias node) { _visitNodeListWithSeparatorAndSuffix(node.metadata, " ", " "); _writer.print("typedef "); _visitNode(node.name); _visitNode(node.typeParameters); _writer.print(" = "); _visitNode(node.functionType); - return null; } @override - Object visitHideCombinator(HideCombinator node) { + void visitHideCombinator(HideCombinator node) { _writer.print("hide "); _visitNodeListWithSeparator(node.hiddenNames, ", "); - return null; } @override - Object visitIfStatement(IfStatement node) { + void visitIfStatement(IfStatement node) { _writer.print("if ("); _visitNode(node.condition); _writer.print(") "); _visitNode(node.thenStatement); _visitNodeWithPrefix(" else ", node.elseStatement); - return null; } @override - Object visitImplementsClause(ImplementsClause node) { + void visitImplementsClause(ImplementsClause node) { _writer.print("implements "); _visitNodeListWithSeparator(node.interfaces, ", "); - return null; } @override - Object visitImportDirective(ImportDirective node) { + void visitImportDirective(ImportDirective node) { _visitNodeListWithSeparatorAndSuffix(node.metadata, " ", " "); _writer.print("import "); _visitNode(node.uri); @@ -7656,11 +7639,10 @@ _visitNodeWithPrefix(" as ", node.prefix); _visitNodeListWithSeparatorAndPrefix(" ", node.combinators, " "); _writer.print(';'); - return null; } @override - Object visitIndexExpression(IndexExpression node) { + void visitIndexExpression(IndexExpression node) { if (node.isCascaded) { _writer.print(".."); } else { @@ -7669,25 +7651,22 @@ _writer.print('['); _visitNode(node.index); _writer.print(']'); - return null; } @override - Object visitInstanceCreationExpression(InstanceCreationExpression node) { + void visitInstanceCreationExpression(InstanceCreationExpression node) { _visitTokenWithSuffix(node.keyword, " "); _visitNode(node.constructorName); _visitNode(node.argumentList); - return null; } @override - Object visitIntegerLiteral(IntegerLiteral node) { + void visitIntegerLiteral(IntegerLiteral node) { _writer.print(node.literal.lexeme); - return null; } @override - Object visitInterpolationExpression(InterpolationExpression node) { + void visitInterpolationExpression(InterpolationExpression node) { if (node.rightBracket != null) { _writer.print("\${"); _visitNode(node.expression); @@ -7696,17 +7675,15 @@ _writer.print("\$"); _visitNode(node.expression); } - return null; } @override - Object visitInterpolationString(InterpolationString node) { + void visitInterpolationString(InterpolationString node) { _writer.print(node.contents.lexeme); - return null; } @override - Object visitIsExpression(IsExpression node) { + void visitIsExpression(IsExpression node) { _visitNode(node.expression); if (node.notOperator == null) { _writer.print(" is "); @@ -7714,40 +7691,35 @@ _writer.print(" is! "); } _visitNode(node.type); - return null; } @override - Object visitLabel(Label node) { + void visitLabel(Label node) { _visitNode(node.label); _writer.print(":"); - return null; } @override - Object visitLabeledStatement(LabeledStatement node) { + void visitLabeledStatement(LabeledStatement node) { _visitNodeListWithSeparatorAndSuffix(node.labels, " ", " "); _visitNode(node.statement); - return null; } @override - Object visitLibraryDirective(LibraryDirective node) { + void visitLibraryDirective(LibraryDirective node) { _visitNodeListWithSeparatorAndSuffix(node.metadata, " ", " "); _writer.print("library "); _visitNode(node.name); _writer.print(';'); - return null; } @override - Object visitLibraryIdentifier(LibraryIdentifier node) { + void visitLibraryIdentifier(LibraryIdentifier node) { _writer.print(node.name); - return null; } @override - Object visitListLiteral(ListLiteral node) { + void visitListLiteral(ListLiteral node) { if (node.constKeyword != null) { _writer.print(node.constKeyword.lexeme); _writer.print(' '); @@ -7756,11 +7728,10 @@ _writer.print("["); _visitNodeListWithSeparator(node.elements, ", "); _writer.print("]"); - return null; } @override - Object visitMapLiteral(MapLiteral node) { + void visitMapLiteral(MapLiteral node) { if (node.constKeyword != null) { _writer.print(node.constKeyword.lexeme); _writer.print(' '); @@ -7769,19 +7740,17 @@ _writer.print("{"); _visitNodeListWithSeparator(node.entries, ", "); _writer.print("}"); - return null; } @override - Object visitMapLiteralEntry(MapLiteralEntry node) { + void visitMapLiteralEntry(MapLiteralEntry node) { _visitNode(node.key); _writer.print(" : "); _visitNode(node.value); - return null; } @override - Object visitMethodDeclaration(MethodDeclaration node) { + void visitMethodDeclaration(MethodDeclaration node) { _visitNodeListWithSeparatorAndSuffix(node.metadata, " ", " "); _visitTokenWithSuffix(node.externalKeyword, " "); _visitTokenWithSuffix(node.modifierKeyword, " "); @@ -7794,11 +7763,10 @@ _visitNode(node.parameters); } _visitFunctionWithPrefix(" ", node.body); - return null; } @override - Object visitMethodInvocation(MethodInvocation node) { + void visitMethodInvocation(MethodInvocation node) { if (node.isCascaded) { _writer.print(".."); } else { @@ -7810,11 +7778,10 @@ _visitNode(node.methodName); _visitNode(node.typeArguments); _visitNode(node.argumentList); - return null; } @override - bool visitMixinDeclaration(MixinDeclaration node) { + void visitMixinDeclaration(MixinDeclaration node) { _visitNodeListWithSeparatorAndSuffix(node.metadata, " ", " "); _writer.print("mixin "); _visitNode(node.name); @@ -7824,94 +7791,82 @@ _writer.print(" {"); _visitNodeListWithSeparator(node.members, " "); _writer.print("}"); - return null; } @override - Object visitNamedExpression(NamedExpression node) { + void visitNamedExpression(NamedExpression node) { _visitNode(node.name); _visitNodeWithPrefix(" ", node.expression); - return null; } @override - Object visitNativeClause(NativeClause node) { + void visitNativeClause(NativeClause node) { _writer.print("native "); _visitNode(node.name); - return null; } @override - Object visitNativeFunctionBody(NativeFunctionBody node) { + void visitNativeFunctionBody(NativeFunctionBody node) { _writer.print("native "); _visitNode(node.stringLiteral); _writer.print(';'); - return null; } @override - Object visitNullLiteral(NullLiteral node) { + void visitNullLiteral(NullLiteral node) { _writer.print("null"); - return null; } @override - bool visitOnClause(OnClause node) { + void visitOnClause(OnClause node) { _writer.print('on '); _visitNodeListWithSeparator(node.superclassConstraints, ", "); - return null; } @override - Object visitParenthesizedExpression(ParenthesizedExpression node) { + void visitParenthesizedExpression(ParenthesizedExpression node) { _writer.print('('); _visitNode(node.expression); _writer.print(')'); - return null; } @override - Object visitPartDirective(PartDirective node) { + void visitPartDirective(PartDirective node) { _visitNodeListWithSeparatorAndSuffix(node.metadata, " ", " "); _writer.print("part "); _visitNode(node.uri); _writer.print(';'); - return null; } @override - Object visitPartOfDirective(PartOfDirective node) { + void visitPartOfDirective(PartOfDirective node) { _visitNodeListWithSeparatorAndSuffix(node.metadata, " ", " "); _writer.print("part of "); _visitNode(node.libraryName); _writer.print(';'); - return null; } @override - Object visitPostfixExpression(PostfixExpression node) { + void visitPostfixExpression(PostfixExpression node) { _visitNode(node.operand); _writer.print(node.operator.lexeme); - return null; } @override - Object visitPrefixedIdentifier(PrefixedIdentifier node) { + void visitPrefixedIdentifier(PrefixedIdentifier node) { _visitNode(node.prefix); _writer.print('.'); _visitNode(node.identifier); - return null; } @override - Object visitPrefixExpression(PrefixExpression node) { + void visitPrefixExpression(PrefixExpression node) { _writer.print(node.operator.lexeme); _visitNode(node.operand); - return null; } @override - Object visitPropertyAccess(PropertyAccess node) { + void visitPropertyAccess(PropertyAccess node) { if (node.isCascaded) { _writer.print(".."); } else { @@ -7919,26 +7874,23 @@ _writer.print(node.operator.lexeme); } _visitNode(node.propertyName); - return null; } @override - Object visitRedirectingConstructorInvocation( + void visitRedirectingConstructorInvocation( RedirectingConstructorInvocation node) { _writer.print("this"); _visitNodeWithPrefix(".", node.constructorName); _visitNode(node.argumentList); - return null; } @override - Object visitRethrowExpression(RethrowExpression node) { + void visitRethrowExpression(RethrowExpression node) { _writer.print("rethrow"); - return null; } @override - Object visitReturnStatement(ReturnStatement node) { + void visitReturnStatement(ReturnStatement node) { Expression expression = node.expression; if (expression == null) { _writer.print("return;"); @@ -7947,24 +7899,33 @@ expression.accept(this); _writer.print(";"); } - return null; } @override - Object visitScriptTag(ScriptTag node) { + void visitScriptTag(ScriptTag node) { _writer.print(node.scriptTag.lexeme); - return null; } @override - Object visitShowCombinator(ShowCombinator node) { + void visitSetLiteral(SetLiteral node) { + if (node.constKeyword != null) { + _writer.print(node.constKeyword.lexeme); + _writer.print(' '); + } + _visitNodeWithSuffix(node.typeArguments, " "); + _writer.print("{"); + _visitNodeListWithSeparator(node.elements, ", "); + _writer.print("}"); + } + + @override + void visitShowCombinator(ShowCombinator node) { _writer.print("show "); _visitNodeListWithSeparator(node.shownNames, ", "); - return null; } @override - Object visitSimpleFormalParameter(SimpleFormalParameter node) { + void visitSimpleFormalParameter(SimpleFormalParameter node) { _visitNodeListWithSeparatorAndSuffix(node.metadata, ' ', ' '); _visitTokenWithSuffix(node.covariantKeyword, ' '); _visitTokenWithSuffix(node.keyword, " "); @@ -7973,71 +7934,62 @@ _writer.print(' '); } _visitNode(node.identifier); - return null; } @override - Object visitSimpleIdentifier(SimpleIdentifier node) { + void visitSimpleIdentifier(SimpleIdentifier node) { _writer.print(node.token.lexeme); - return null; } @override - Object visitSimpleStringLiteral(SimpleStringLiteral node) { + void visitSimpleStringLiteral(SimpleStringLiteral node) { _writer.print(node.literal.lexeme); - return null; } @override - Object visitStringInterpolation(StringInterpolation node) { + void visitStringInterpolation(StringInterpolation node) { _visitNodeList(node.elements); - return null; } @override - Object visitSuperConstructorInvocation(SuperConstructorInvocation node) { + void visitSuperConstructorInvocation(SuperConstructorInvocation node) { _writer.print("super"); _visitNodeWithPrefix(".", node.constructorName); _visitNode(node.argumentList); - return null; } @override - Object visitSuperExpression(SuperExpression node) { + void visitSuperExpression(SuperExpression node) { _writer.print("super"); - return null; } @override - Object visitSwitchCase(SwitchCase node) { + void visitSwitchCase(SwitchCase node) { _visitNodeListWithSeparatorAndSuffix(node.labels, " ", " "); _writer.print("case "); _visitNode(node.expression); _writer.print(": "); _visitNodeListWithSeparator(node.statements, " "); - return null; } @override - Object visitSwitchDefault(SwitchDefault node) { + void visitSwitchDefault(SwitchDefault node) { _visitNodeListWithSeparatorAndSuffix(node.labels, " ", " "); _writer.print("default: "); _visitNodeListWithSeparator(node.statements, " "); - return null; } @override - Object visitSwitchStatement(SwitchStatement node) { + void visitSwitchStatement(SwitchStatement node) { _writer.print("switch ("); _visitNode(node.expression); _writer.print(") {"); _visitNodeListWithSeparator(node.members, " "); _writer.print("}"); - return null; } @override - Object visitSymbolLiteral(SymbolLiteral node) { + void visitSymbolLiteral(SymbolLiteral node) { _writer.print("#"); List<Token> components = node.components; for (int i = 0; i < components.length; i++) { @@ -8046,110 +7998,96 @@ } _writer.print(components[i].lexeme); } - return null; } @override - Object visitThisExpression(ThisExpression node) { + void visitThisExpression(ThisExpression node) { _writer.print("this"); - return null; } @override - Object visitThrowExpression(ThrowExpression node) { + void visitThrowExpression(ThrowExpression node) { _writer.print("throw "); _visitNode(node.expression); - return null; } @override - Object visitTopLevelVariableDeclaration(TopLevelVariableDeclaration node) { + void visitTopLevelVariableDeclaration(TopLevelVariableDeclaration node) { _visitNodeWithSuffix(node.variables, ";"); - return null; } @override - Object visitTryStatement(TryStatement node) { + void visitTryStatement(TryStatement node) { _writer.print("try "); _visitNode(node.body); _visitNodeListWithSeparatorAndPrefix(" ", node.catchClauses, " "); _visitNodeWithPrefix(" finally ", node.finallyBlock); - return null; } @override - Object visitTypeArgumentList(TypeArgumentList node) { + void visitTypeArgumentList(TypeArgumentList node) { _writer.print('<'); _visitNodeListWithSeparator(node.arguments, ", "); _writer.print('>'); - return null; } @override - Object visitTypeName(TypeName node) { + void visitTypeName(TypeName node) { _visitNode(node.name); _visitNode(node.typeArguments); - return null; } @override - Object visitTypeParameter(TypeParameter node) { + void visitTypeParameter(TypeParameter node) { _visitNodeListWithSeparatorAndSuffix(node.metadata, " ", " "); _visitNode(node.name); _visitNodeWithPrefix(" extends ", node.bound); - return null; } @override - Object visitTypeParameterList(TypeParameterList node) { + void visitTypeParameterList(TypeParameterList node) { _writer.print('<'); _visitNodeListWithSeparator(node.typeParameters, ", "); _writer.print('>'); - return null; } @override - Object visitVariableDeclaration(VariableDeclaration node) { + void visitVariableDeclaration(VariableDeclaration node) { _visitNodeListWithSeparatorAndSuffix(node.metadata, " ", " "); _visitNode(node.name); _visitNodeWithPrefix(" = ", node.initializer); - return null; } @override - Object visitVariableDeclarationList(VariableDeclarationList node) { + void visitVariableDeclarationList(VariableDeclarationList node) { _visitNodeListWithSeparatorAndSuffix(node.metadata, " ", " "); _visitTokenWithSuffix(node.keyword, " "); _visitNodeWithSuffix(node.type, " "); _visitNodeListWithSeparator(node.variables, ", "); - return null; } @override - Object visitVariableDeclarationStatement(VariableDeclarationStatement node) { + void visitVariableDeclarationStatement(VariableDeclarationStatement node) { _visitNode(node.variables); _writer.print(";"); - return null; } @override - Object visitWhileStatement(WhileStatement node) { + void visitWhileStatement(WhileStatement node) { _writer.print("while ("); _visitNode(node.condition); _writer.print(") "); _visitNode(node.body); - return null; } @override - Object visitWithClause(WithClause node) { + void visitWithClause(WithClause node) { _writer.print("with "); _visitNodeListWithSeparator(node.mixinTypes, ", "); - return null; } @override - Object visitYieldStatement(YieldStatement node) { + void visitYieldStatement(YieldStatement node) { if (node.star != null) { _writer.print("yield* "); } else { @@ -8157,7 +8095,6 @@ } _visitNode(node.expression); _writer.print(";"); - return null; } /** @@ -8280,7 +8217,7 @@ * A visitor used to write a source representation of a visited AST node (and * all of it's children) to a sink. */ -class ToSourceVisitor2 implements AstVisitor<Object> { +class ToSourceVisitor2 implements AstVisitor<void> { /** * The sink to which the source is to be written. */ @@ -8419,38 +8356,34 @@ } @override - Object visitAdjacentStrings(AdjacentStrings node) { + void visitAdjacentStrings(AdjacentStrings node) { safelyVisitNodeListWithSeparator(node.strings, " "); - return null; } @override - Object visitAnnotation(Annotation node) { + void visitAnnotation(Annotation node) { sink.write('@'); safelyVisitNode(node.name); safelyVisitNodeWithPrefix(".", node.constructorName); safelyVisitNode(node.arguments); - return null; } @override - Object visitArgumentList(ArgumentList node) { + void visitArgumentList(ArgumentList node) { sink.write('('); safelyVisitNodeListWithSeparator(node.arguments, ", "); sink.write(')'); - return null; } @override - Object visitAsExpression(AsExpression node) { + void visitAsExpression(AsExpression node) { safelyVisitNode(node.expression); sink.write(" as "); safelyVisitNode(node.type); - return null; } @override - bool visitAssertInitializer(AssertInitializer node) { + void visitAssertInitializer(AssertInitializer node) { sink.write("assert ("); safelyVisitNode(node.condition); if (node.message != null) { @@ -8458,11 +8391,10 @@ safelyVisitNode(node.message); } sink.write(");"); - return null; } @override - Object visitAssertStatement(AssertStatement node) { + void visitAssertStatement(AssertStatement node) { sink.write("assert ("); safelyVisitNode(node.condition); if (node.message != null) { @@ -8470,46 +8402,41 @@ safelyVisitNode(node.message); } sink.write(");"); - return null; } @override - Object visitAssignmentExpression(AssignmentExpression node) { + void visitAssignmentExpression(AssignmentExpression node) { safelyVisitNode(node.leftHandSide); sink.write(' '); sink.write(node.operator.lexeme); sink.write(' '); safelyVisitNode(node.rightHandSide); - return null; } @override - Object visitAwaitExpression(AwaitExpression node) { + void visitAwaitExpression(AwaitExpression node) { sink.write("await "); safelyVisitNode(node.expression); - return null; } @override - Object visitBinaryExpression(BinaryExpression node) { + void visitBinaryExpression(BinaryExpression node) { _writeOperand(node, node.leftOperand); sink.write(' '); sink.write(node.operator.lexeme); sink.write(' '); _writeOperand(node, node.rightOperand); - return null; } @override - Object visitBlock(Block node) { + void visitBlock(Block node) { sink.write('{'); safelyVisitNodeListWithSeparator(node.statements, " "); sink.write('}'); - return null; } @override - Object visitBlockFunctionBody(BlockFunctionBody node) { + void visitBlockFunctionBody(BlockFunctionBody node) { Token keyword = node.keyword; if (keyword != null) { sink.write(keyword.lexeme); @@ -8519,32 +8446,28 @@ sink.write(' '); } safelyVisitNode(node.block); - return null; } @override - Object visitBooleanLiteral(BooleanLiteral node) { + void visitBooleanLiteral(BooleanLiteral node) { sink.write(node.literal.lexeme); - return null; } @override - Object visitBreakStatement(BreakStatement node) { + void visitBreakStatement(BreakStatement node) { sink.write("break"); safelyVisitNodeWithPrefix(" ", node.label); sink.write(";"); - return null; } @override - Object visitCascadeExpression(CascadeExpression node) { + void visitCascadeExpression(CascadeExpression node) { safelyVisitNode(node.target); safelyVisitNodeList(node.cascadeSections); - return null; } @override - Object visitCatchClause(CatchClause node) { + void visitCatchClause(CatchClause node) { safelyVisitNodeWithPrefix("on ", node.exceptionType); if (node.catchKeyword != null) { if (node.exceptionType != null) { @@ -8558,11 +8481,10 @@ sink.write(" "); } safelyVisitNode(node.body); - return null; } @override - Object visitClassDeclaration(ClassDeclaration node) { + void visitClassDeclaration(ClassDeclaration node) { safelyVisitNodeListWithSeparatorAndSuffix(node.metadata, " ", " "); safelyVisitTokenWithSuffix(node.abstractKeyword, " "); sink.write("class "); @@ -8574,11 +8496,10 @@ sink.write(" {"); safelyVisitNodeListWithSeparator(node.members, " "); sink.write("}"); - return null; } @override - Object visitClassTypeAlias(ClassTypeAlias node) { + void visitClassTypeAlias(ClassTypeAlias node) { safelyVisitNodeListWithSeparatorAndSuffix(node.metadata, " ", " "); if (node.abstractKeyword != null) { sink.write("abstract "); @@ -8591,17 +8512,16 @@ safelyVisitNodeWithPrefix(" ", node.withClause); safelyVisitNodeWithPrefix(" ", node.implementsClause); sink.write(";"); - return null; } @override - Object visitComment(Comment node) => null; + void visitComment(Comment node) {} @override - Object visitCommentReference(CommentReference node) => null; + void visitCommentReference(CommentReference node) {} @override - Object visitCompilationUnit(CompilationUnit node) { + void visitCompilationUnit(CompilationUnit node) { ScriptTag scriptTag = node.scriptTag; NodeList<Directive> directives = node.directives; safelyVisitNode(scriptTag); @@ -8609,31 +8529,28 @@ safelyVisitNodeListWithSeparatorAndPrefix(prefix, directives, " "); prefix = scriptTag == null && directives.isEmpty ? "" : " "; safelyVisitNodeListWithSeparatorAndPrefix(prefix, node.declarations, " "); - return null; } @override - Object visitConditionalExpression(ConditionalExpression node) { + void visitConditionalExpression(ConditionalExpression node) { safelyVisitNode(node.condition); sink.write(" ? "); safelyVisitNode(node.thenExpression); sink.write(" : "); safelyVisitNode(node.elseExpression); - return null; } @override - Object visitConfiguration(Configuration node) { + void visitConfiguration(Configuration node) { sink.write('if ('); safelyVisitNode(node.name); safelyVisitNodeWithPrefix(" == ", node.value); sink.write(') '); safelyVisitNode(node.uri); - return null; } @override - Object visitConstructorDeclaration(ConstructorDeclaration node) { + void visitConstructorDeclaration(ConstructorDeclaration node) { safelyVisitNodeListWithSeparatorAndSuffix(node.metadata, " ", " "); safelyVisitTokenWithSuffix(node.externalKeyword, " "); safelyVisitTokenWithSuffix(node.constKeyword, " "); @@ -8644,44 +8561,39 @@ safelyVisitNodeListWithSeparatorAndPrefix(" : ", node.initializers, ", "); safelyVisitNodeWithPrefix(" = ", node.redirectedConstructor); safelyVisitFunctionWithPrefix(" ", node.body); - return null; } @override - Object visitConstructorFieldInitializer(ConstructorFieldInitializer node) { + void visitConstructorFieldInitializer(ConstructorFieldInitializer node) { safelyVisitTokenWithSuffix(node.thisKeyword, "."); safelyVisitNode(node.fieldName); sink.write(" = "); safelyVisitNode(node.expression); - return null; } @override - Object visitConstructorName(ConstructorName node) { + void visitConstructorName(ConstructorName node) { safelyVisitNode(node.type); safelyVisitNodeWithPrefix(".", node.name); - return null; } @override - Object visitContinueStatement(ContinueStatement node) { + void visitContinueStatement(ContinueStatement node) { sink.write("continue"); safelyVisitNodeWithPrefix(" ", node.label); sink.write(";"); - return null; } @override - Object visitDeclaredIdentifier(DeclaredIdentifier node) { + void visitDeclaredIdentifier(DeclaredIdentifier node) { safelyVisitNodeListWithSeparatorAndSuffix(node.metadata, " ", " "); safelyVisitTokenWithSuffix(node.keyword, " "); safelyVisitNodeWithSuffix(node.type, " "); safelyVisitNode(node.identifier); - return null; } @override - Object visitDefaultFormalParameter(DefaultFormalParameter node) { + void visitDefaultFormalParameter(DefaultFormalParameter node) { safelyVisitNode(node.parameter); if (node.separator != null) { if (node.separator.lexeme != ":") { @@ -8690,73 +8602,64 @@ sink.write(node.separator.lexeme); safelyVisitNodeWithPrefix(" ", node.defaultValue); } - return null; } @override - Object visitDoStatement(DoStatement node) { + void visitDoStatement(DoStatement node) { sink.write("do "); safelyVisitNode(node.body); sink.write(" while ("); safelyVisitNode(node.condition); sink.write(");"); - return null; } @override - Object visitDottedName(DottedName node) { + void visitDottedName(DottedName node) { safelyVisitNodeListWithSeparator(node.components, "."); - return null; } @override - Object visitDoubleLiteral(DoubleLiteral node) { + void visitDoubleLiteral(DoubleLiteral node) { sink.write(node.literal.lexeme); - return null; } @override - Object visitEmptyFunctionBody(EmptyFunctionBody node) { + void visitEmptyFunctionBody(EmptyFunctionBody node) { sink.write(';'); - return null; } @override - Object visitEmptyStatement(EmptyStatement node) { + void visitEmptyStatement(EmptyStatement node) { sink.write(';'); - return null; } @override - Object visitEnumConstantDeclaration(EnumConstantDeclaration node) { + void visitEnumConstantDeclaration(EnumConstantDeclaration node) { safelyVisitNodeListWithSeparatorAndSuffix(node.metadata, " ", " "); safelyVisitNode(node.name); - return null; } @override - Object visitEnumDeclaration(EnumDeclaration node) { + void visitEnumDeclaration(EnumDeclaration node) { safelyVisitNodeListWithSeparatorAndSuffix(node.metadata, " ", " "); sink.write("enum "); safelyVisitNode(node.name); sink.write(" {"); safelyVisitNodeListWithSeparator(node.constants, ", "); sink.write("}"); - return null; } @override - Object visitExportDirective(ExportDirective node) { + void visitExportDirective(ExportDirective node) { safelyVisitNodeListWithSeparatorAndSuffix(node.metadata, " ", " "); sink.write("export "); safelyVisitNode(node.uri); safelyVisitNodeListWithSeparatorAndPrefix(" ", node.combinators, " "); sink.write(';'); - return null; } @override - Object visitExpressionFunctionBody(ExpressionFunctionBody node) { + void visitExpressionFunctionBody(ExpressionFunctionBody node) { Token keyword = node.keyword; if (keyword != null) { sink.write(keyword.lexeme); @@ -8767,34 +8670,30 @@ if (node.semicolon != null) { sink.write(';'); } - return null; } @override - Object visitExpressionStatement(ExpressionStatement node) { + void visitExpressionStatement(ExpressionStatement node) { safelyVisitNode(node.expression); sink.write(';'); - return null; } @override - Object visitExtendsClause(ExtendsClause node) { + void visitExtendsClause(ExtendsClause node) { sink.write("extends "); safelyVisitNode(node.superclass); - return null; } @override - Object visitFieldDeclaration(FieldDeclaration node) { + void visitFieldDeclaration(FieldDeclaration node) { safelyVisitNodeListWithSeparatorAndSuffix(node.metadata, " ", " "); safelyVisitTokenWithSuffix(node.staticKeyword, " "); safelyVisitNode(node.fields); sink.write(";"); - return null; } @override - Object visitFieldFormalParameter(FieldFormalParameter node) { + void visitFieldFormalParameter(FieldFormalParameter node) { safelyVisitNodeListWithSeparatorAndSuffix(node.metadata, ' ', ' '); safelyVisitTokenWithSuffix(node.covariantKeyword, ' '); safelyVisitTokenWithSuffix(node.keyword, " "); @@ -8803,11 +8702,10 @@ safelyVisitNode(node.identifier); safelyVisitNode(node.typeParameters); safelyVisitNode(node.parameters); - return null; } @override - Object visitForEachStatement(ForEachStatement node) { + void visitForEachStatement(ForEachStatement node) { DeclaredIdentifier loopVariable = node.loopVariable; if (node.awaitKeyword != null) { sink.write("await "); @@ -8822,11 +8720,10 @@ safelyVisitNode(node.iterable); sink.write(") "); safelyVisitNode(node.body); - return null; } @override - Object visitFormalParameterList(FormalParameterList node) { + void visitFormalParameterList(FormalParameterList node) { String groupEnd = null; sink.write('('); NodeList<FormalParameter> parameters = node.parameters; @@ -8851,11 +8748,10 @@ sink.write(groupEnd); } sink.write(')'); - return null; } @override - Object visitForStatement(ForStatement node) { + void visitForStatement(ForStatement node) { Expression initialization = node.initialization; sink.write("for ("); if (initialization != null) { @@ -8869,47 +8765,42 @@ safelyVisitNodeListWithSeparatorAndPrefix(" ", node.updaters, ", "); sink.write(") "); safelyVisitNode(node.body); - return null; } @override - Object visitFunctionDeclaration(FunctionDeclaration node) { + void visitFunctionDeclaration(FunctionDeclaration node) { safelyVisitNodeListWithSeparatorAndSuffix(node.metadata, " ", " "); safelyVisitTokenWithSuffix(node.externalKeyword, " "); safelyVisitNodeWithSuffix(node.returnType, " "); safelyVisitTokenWithSuffix(node.propertyKeyword, " "); safelyVisitNode(node.name); safelyVisitNode(node.functionExpression); - return null; } @override - Object visitFunctionDeclarationStatement(FunctionDeclarationStatement node) { + void visitFunctionDeclarationStatement(FunctionDeclarationStatement node) { safelyVisitNode(node.functionDeclaration); - return null; } @override - Object visitFunctionExpression(FunctionExpression node) { + void visitFunctionExpression(FunctionExpression node) { safelyVisitNode(node.typeParameters); safelyVisitNode(node.parameters); if (node.body is! EmptyFunctionBody) { sink.write(' '); } safelyVisitNode(node.body); - return null; } @override - Object visitFunctionExpressionInvocation(FunctionExpressionInvocation node) { + void visitFunctionExpressionInvocation(FunctionExpressionInvocation node) { safelyVisitNode(node.function); safelyVisitNode(node.typeArguments); safelyVisitNode(node.argumentList); - return null; } @override - Object visitFunctionTypeAlias(FunctionTypeAlias node) { + void visitFunctionTypeAlias(FunctionTypeAlias node) { safelyVisitNodeListWithSeparatorAndSuffix(node.metadata, " ", " "); sink.write("typedef "); safelyVisitNodeWithSuffix(node.returnType, " "); @@ -8917,66 +8808,59 @@ safelyVisitNode(node.typeParameters); safelyVisitNode(node.parameters); sink.write(";"); - return null; } @override - Object visitFunctionTypedFormalParameter(FunctionTypedFormalParameter node) { + void visitFunctionTypedFormalParameter(FunctionTypedFormalParameter node) { safelyVisitNodeListWithSeparatorAndSuffix(node.metadata, ' ', ' '); safelyVisitTokenWithSuffix(node.covariantKeyword, ' '); safelyVisitNodeWithSuffix(node.returnType, " "); safelyVisitNode(node.identifier); safelyVisitNode(node.typeParameters); safelyVisitNode(node.parameters); - return null; } @override - Object visitGenericFunctionType(GenericFunctionType node) { + void visitGenericFunctionType(GenericFunctionType node) { safelyVisitNode(node.returnType); sink.write(' Function'); safelyVisitNode(node.typeParameters); safelyVisitNode(node.parameters); - return null; } @override - Object visitGenericTypeAlias(GenericTypeAlias node) { + void visitGenericTypeAlias(GenericTypeAlias node) { safelyVisitNodeListWithSeparatorAndSuffix(node.metadata, " ", " "); sink.write("typedef "); safelyVisitNode(node.name); safelyVisitNode(node.typeParameters); sink.write(" = "); safelyVisitNode(node.functionType); - return null; } @override - Object visitHideCombinator(HideCombinator node) { + void visitHideCombinator(HideCombinator node) { sink.write("hide "); safelyVisitNodeListWithSeparator(node.hiddenNames, ", "); - return null; } @override - Object visitIfStatement(IfStatement node) { + void visitIfStatement(IfStatement node) { sink.write("if ("); safelyVisitNode(node.condition); sink.write(") "); safelyVisitNode(node.thenStatement); safelyVisitNodeWithPrefix(" else ", node.elseStatement); - return null; } @override - Object visitImplementsClause(ImplementsClause node) { + void visitImplementsClause(ImplementsClause node) { sink.write("implements "); safelyVisitNodeListWithSeparator(node.interfaces, ", "); - return null; } @override - Object visitImportDirective(ImportDirective node) { + void visitImportDirective(ImportDirective node) { safelyVisitNodeListWithSeparatorAndSuffix(node.metadata, " ", " "); sink.write("import "); safelyVisitNode(node.uri); @@ -8986,11 +8870,10 @@ safelyVisitNodeWithPrefix(" as ", node.prefix); safelyVisitNodeListWithSeparatorAndPrefix(" ", node.combinators, " "); sink.write(';'); - return null; } @override - Object visitIndexExpression(IndexExpression node) { + void visitIndexExpression(IndexExpression node) { if (node.isCascaded) { sink.write(".."); } else { @@ -8999,25 +8882,22 @@ sink.write('['); safelyVisitNode(node.index); sink.write(']'); - return null; } @override - Object visitInstanceCreationExpression(InstanceCreationExpression node) { + void visitInstanceCreationExpression(InstanceCreationExpression node) { safelyVisitTokenWithSuffix(node.keyword, " "); safelyVisitNode(node.constructorName); safelyVisitNode(node.argumentList); - return null; } @override - Object visitIntegerLiteral(IntegerLiteral node) { + void visitIntegerLiteral(IntegerLiteral node) { sink.write(node.literal.lexeme); - return null; } @override - Object visitInterpolationExpression(InterpolationExpression node) { + void visitInterpolationExpression(InterpolationExpression node) { if (node.rightBracket != null) { sink.write("\${"); safelyVisitNode(node.expression); @@ -9026,17 +8906,15 @@ sink.write("\$"); safelyVisitNode(node.expression); } - return null; } @override - Object visitInterpolationString(InterpolationString node) { + void visitInterpolationString(InterpolationString node) { sink.write(node.contents.lexeme); - return null; } @override - Object visitIsExpression(IsExpression node) { + void visitIsExpression(IsExpression node) { safelyVisitNode(node.expression); if (node.notOperator == null) { sink.write(" is "); @@ -9044,40 +8922,35 @@ sink.write(" is! "); } safelyVisitNode(node.type); - return null; } @override - Object visitLabel(Label node) { + void visitLabel(Label node) { safelyVisitNode(node.label); sink.write(":"); - return null; } @override - Object visitLabeledStatement(LabeledStatement node) { + void visitLabeledStatement(LabeledStatement node) { safelyVisitNodeListWithSeparatorAndSuffix(node.labels, " ", " "); safelyVisitNode(node.statement); - return null; } @override - Object visitLibraryDirective(LibraryDirective node) { + void visitLibraryDirective(LibraryDirective node) { safelyVisitNodeListWithSeparatorAndSuffix(node.metadata, " ", " "); sink.write("library "); safelyVisitNode(node.name); sink.write(';'); - return null; } @override - Object visitLibraryIdentifier(LibraryIdentifier node) { + void visitLibraryIdentifier(LibraryIdentifier node) { sink.write(node.name); - return null; } @override - Object visitListLiteral(ListLiteral node) { + void visitListLiteral(ListLiteral node) { if (node.constKeyword != null) { sink.write(node.constKeyword.lexeme); sink.write(' '); @@ -9086,11 +8959,10 @@ sink.write("["); safelyVisitNodeListWithSeparator(node.elements, ", "); sink.write("]"); - return null; } @override - Object visitMapLiteral(MapLiteral node) { + void visitMapLiteral(MapLiteral node) { if (node.constKeyword != null) { sink.write(node.constKeyword.lexeme); sink.write(' '); @@ -9099,19 +8971,17 @@ sink.write("{"); safelyVisitNodeListWithSeparator(node.entries, ", "); sink.write("}"); - return null; } @override - Object visitMapLiteralEntry(MapLiteralEntry node) { + void visitMapLiteralEntry(MapLiteralEntry node) { safelyVisitNode(node.key); sink.write(" : "); safelyVisitNode(node.value); - return null; } @override - Object visitMethodDeclaration(MethodDeclaration node) { + void visitMethodDeclaration(MethodDeclaration node) { safelyVisitNodeListWithSeparatorAndSuffix(node.metadata, " ", " "); safelyVisitTokenWithSuffix(node.externalKeyword, " "); safelyVisitTokenWithSuffix(node.modifierKeyword, " "); @@ -9124,11 +8994,10 @@ safelyVisitNode(node.parameters); } safelyVisitFunctionWithPrefix(" ", node.body); - return null; } @override - Object visitMethodInvocation(MethodInvocation node) { + void visitMethodInvocation(MethodInvocation node) { if (node.isCascaded) { sink.write(".."); } else { @@ -9140,11 +9009,10 @@ safelyVisitNode(node.methodName); safelyVisitNode(node.typeArguments); safelyVisitNode(node.argumentList); - return null; } @override - bool visitMixinDeclaration(MixinDeclaration node) { + void visitMixinDeclaration(MixinDeclaration node) { safelyVisitNodeListWithSeparatorAndSuffix(node.metadata, " ", " "); sink.write("mixin "); safelyVisitNode(node.name); @@ -9154,94 +9022,82 @@ sink.write(" {"); safelyVisitNodeListWithSeparator(node.members, " "); sink.write("}"); - return null; } @override - Object visitNamedExpression(NamedExpression node) { + void visitNamedExpression(NamedExpression node) { safelyVisitNode(node.name); safelyVisitNodeWithPrefix(" ", node.expression); - return null; } @override - Object visitNativeClause(NativeClause node) { + void visitNativeClause(NativeClause node) { sink.write("native "); safelyVisitNode(node.name); - return null; } @override - Object visitNativeFunctionBody(NativeFunctionBody node) { + void visitNativeFunctionBody(NativeFunctionBody node) { sink.write("native "); safelyVisitNode(node.stringLiteral); sink.write(';'); - return null; } @override - Object visitNullLiteral(NullLiteral node) { + void visitNullLiteral(NullLiteral node) { sink.write("null"); - return null; } @override - bool visitOnClause(OnClause node) { + void visitOnClause(OnClause node) { sink.write('on '); safelyVisitNodeListWithSeparator(node.superclassConstraints, ", "); - return null; } @override - Object visitParenthesizedExpression(ParenthesizedExpression node) { + void visitParenthesizedExpression(ParenthesizedExpression node) { sink.write('('); safelyVisitNode(node.expression); sink.write(')'); - return null; } @override - Object visitPartDirective(PartDirective node) { + void visitPartDirective(PartDirective node) { safelyVisitNodeListWithSeparatorAndSuffix(node.metadata, " ", " "); sink.write("part "); safelyVisitNode(node.uri); sink.write(';'); - return null; } @override - Object visitPartOfDirective(PartOfDirective node) { + void visitPartOfDirective(PartOfDirective node) { safelyVisitNodeListWithSeparatorAndSuffix(node.metadata, " ", " "); sink.write("part of "); safelyVisitNode(node.libraryName); sink.write(';'); - return null; } @override - Object visitPostfixExpression(PostfixExpression node) { + void visitPostfixExpression(PostfixExpression node) { _writeOperand(node, node.operand); sink.write(node.operator.lexeme); - return null; } @override - Object visitPrefixedIdentifier(PrefixedIdentifier node) { + void visitPrefixedIdentifier(PrefixedIdentifier node) { safelyVisitNode(node.prefix); sink.write('.'); safelyVisitNode(node.identifier); - return null; } @override - Object visitPrefixExpression(PrefixExpression node) { + void visitPrefixExpression(PrefixExpression node) { sink.write(node.operator.lexeme); _writeOperand(node, node.operand); - return null; } @override - Object visitPropertyAccess(PropertyAccess node) { + void visitPropertyAccess(PropertyAccess node) { if (node.isCascaded) { sink.write(".."); } else { @@ -9249,26 +9105,23 @@ sink.write(node.operator.lexeme); } safelyVisitNode(node.propertyName); - return null; } @override - Object visitRedirectingConstructorInvocation( + void visitRedirectingConstructorInvocation( RedirectingConstructorInvocation node) { sink.write("this"); safelyVisitNodeWithPrefix(".", node.constructorName); safelyVisitNode(node.argumentList); - return null; } @override - Object visitRethrowExpression(RethrowExpression node) { + void visitRethrowExpression(RethrowExpression node) { sink.write("rethrow"); - return null; } @override - Object visitReturnStatement(ReturnStatement node) { + void visitReturnStatement(ReturnStatement node) { Expression expression = node.expression; if (expression == null) { sink.write("return;"); @@ -9277,24 +9130,33 @@ expression.accept(this); sink.write(";"); } - return null; } @override - Object visitScriptTag(ScriptTag node) { + void visitScriptTag(ScriptTag node) { sink.write(node.scriptTag.lexeme); - return null; } @override - Object visitShowCombinator(ShowCombinator node) { + void visitSetLiteral(SetLiteral node) { + if (node.constKeyword != null) { + sink.write(node.constKeyword.lexeme); + sink.write(' '); + } + safelyVisitNodeWithSuffix(node.typeArguments, " "); + sink.write("{"); + safelyVisitNodeListWithSeparator(node.elements, ", "); + sink.write("}"); + } + + @override + void visitShowCombinator(ShowCombinator node) { sink.write("show "); safelyVisitNodeListWithSeparator(node.shownNames, ", "); - return null; } @override - Object visitSimpleFormalParameter(SimpleFormalParameter node) { + void visitSimpleFormalParameter(SimpleFormalParameter node) { safelyVisitNodeListWithSeparatorAndSuffix(node.metadata, ' ', ' '); safelyVisitTokenWithSuffix(node.covariantKeyword, ' '); safelyVisitTokenWithSuffix(node.keyword, " "); @@ -9303,71 +9165,62 @@ sink.write(' '); } safelyVisitNode(node.identifier); - return null; } @override - Object visitSimpleIdentifier(SimpleIdentifier node) { + void visitSimpleIdentifier(SimpleIdentifier node) { sink.write(node.token.lexeme); - return null; } @override - Object visitSimpleStringLiteral(SimpleStringLiteral node) { + void visitSimpleStringLiteral(SimpleStringLiteral node) { sink.write(node.literal.lexeme); - return null; } @override - Object visitStringInterpolation(StringInterpolation node) { + void visitStringInterpolation(StringInterpolation node) { safelyVisitNodeList(node.elements); - return null; } @override - Object visitSuperConstructorInvocation(SuperConstructorInvocation node) { + void visitSuperConstructorInvocation(SuperConstructorInvocation node) { sink.write("super"); safelyVisitNodeWithPrefix(".", node.constructorName); safelyVisitNode(node.argumentList); - return null; } @override - Object visitSuperExpression(SuperExpression node) { + void visitSuperExpression(SuperExpression node) { sink.write("super"); - return null; } @override - Object visitSwitchCase(SwitchCase node) { + void visitSwitchCase(SwitchCase node) { safelyVisitNodeListWithSeparatorAndSuffix(node.labels, " ", " "); sink.write("case "); safelyVisitNode(node.expression); sink.write(": "); safelyVisitNodeListWithSeparator(node.statements, " "); - return null; } @override - Object visitSwitchDefault(SwitchDefault node) { + void visitSwitchDefault(SwitchDefault node) { safelyVisitNodeListWithSeparatorAndSuffix(node.labels, " ", " "); sink.write("default: "); safelyVisitNodeListWithSeparator(node.statements, " "); - return null; } @override - Object visitSwitchStatement(SwitchStatement node) { + void visitSwitchStatement(SwitchStatement node) { sink.write("switch ("); safelyVisitNode(node.expression); sink.write(") {"); safelyVisitNodeListWithSeparator(node.members, " "); sink.write("}"); - return null; } @override - Object visitSymbolLiteral(SymbolLiteral node) { + void visitSymbolLiteral(SymbolLiteral node) { sink.write("#"); List<Token> components = node.components; for (int i = 0; i < components.length; i++) { @@ -9376,110 +9229,96 @@ } sink.write(components[i].lexeme); } - return null; } @override - Object visitThisExpression(ThisExpression node) { + void visitThisExpression(ThisExpression node) { sink.write("this"); - return null; } @override - Object visitThrowExpression(ThrowExpression node) { + void visitThrowExpression(ThrowExpression node) { sink.write("throw "); safelyVisitNode(node.expression); - return null; } @override - Object visitTopLevelVariableDeclaration(TopLevelVariableDeclaration node) { + void visitTopLevelVariableDeclaration(TopLevelVariableDeclaration node) { safelyVisitNodeWithSuffix(node.variables, ";"); - return null; } @override - Object visitTryStatement(TryStatement node) { + void visitTryStatement(TryStatement node) { sink.write("try "); safelyVisitNode(node.body); safelyVisitNodeListWithSeparatorAndPrefix(" ", node.catchClauses, " "); safelyVisitNodeWithPrefix(" finally ", node.finallyBlock); - return null; } @override - Object visitTypeArgumentList(TypeArgumentList node) { + void visitTypeArgumentList(TypeArgumentList node) { sink.write('<'); safelyVisitNodeListWithSeparator(node.arguments, ", "); sink.write('>'); - return null; } @override - Object visitTypeName(TypeName node) { + void visitTypeName(TypeName node) { safelyVisitNode(node.name); safelyVisitNode(node.typeArguments); - return null; } @override - Object visitTypeParameter(TypeParameter node) { + void visitTypeParameter(TypeParameter node) { safelyVisitNodeListWithSeparatorAndSuffix(node.metadata, " ", " "); safelyVisitNode(node.name); safelyVisitNodeWithPrefix(" extends ", node.bound); - return null; } @override - Object visitTypeParameterList(TypeParameterList node) { + void visitTypeParameterList(TypeParameterList node) { sink.write('<'); safelyVisitNodeListWithSeparator(node.typeParameters, ", "); sink.write('>'); - return null; } @override - Object visitVariableDeclaration(VariableDeclaration node) { + void visitVariableDeclaration(VariableDeclaration node) { safelyVisitNodeListWithSeparatorAndSuffix(node.metadata, " ", " "); safelyVisitNode(node.name); safelyVisitNodeWithPrefix(" = ", node.initializer); - return null; } @override - Object visitVariableDeclarationList(VariableDeclarationList node) { + void visitVariableDeclarationList(VariableDeclarationList node) { safelyVisitNodeListWithSeparatorAndSuffix(node.metadata, " ", " "); safelyVisitTokenWithSuffix(node.keyword, " "); safelyVisitNodeWithSuffix(node.type, " "); safelyVisitNodeListWithSeparator(node.variables, ", "); - return null; } @override - Object visitVariableDeclarationStatement(VariableDeclarationStatement node) { + void visitVariableDeclarationStatement(VariableDeclarationStatement node) { safelyVisitNode(node.variables); sink.write(";"); - return null; } @override - Object visitWhileStatement(WhileStatement node) { + void visitWhileStatement(WhileStatement node) { sink.write("while ("); safelyVisitNode(node.condition); sink.write(") "); safelyVisitNode(node.body); - return null; } @override - Object visitWithClause(WithClause node) { + void visitWithClause(WithClause node) { sink.write("with "); safelyVisitNodeListWithSeparator(node.mixinTypes, ", "); - return null; } @override - Object visitYieldStatement(YieldStatement node) { + void visitYieldStatement(YieldStatement node) { if (node.star != null) { sink.write("yield* "); } else { @@ -9487,7 +9326,6 @@ } safelyVisitNode(node.expression); sink.write(";"); - return null; } void _writeOperand(Expression node, Expression operand) {
diff --git a/pkg/analyzer/lib/src/dart/constant/constant_verifier.dart b/pkg/analyzer/lib/src/dart/constant/constant_verifier.dart index d333f97..b271890 100644 --- a/pkg/analyzer/lib/src/dart/constant/constant_verifier.dart +++ b/pkg/analyzer/lib/src/dart/constant/constant_verifier.dart
@@ -1,4 +1,4 @@ -// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. @@ -23,7 +23,7 @@ /// for additional errors and warnings not covered by the parser and resolver. /// In particular, it looks for errors and warnings related to constant /// expressions. -class ConstantVerifier extends RecursiveAstVisitor<Object> { +class ConstantVerifier extends RecursiveAstVisitor<void> { /// The error reporter by which errors will be reported. final ErrorReporter _errorReporter; @@ -71,7 +71,7 @@ } @override - Object visitAnnotation(Annotation node) { + void visitAnnotation(Annotation node) { super.visitAnnotation(node); // check annotation creation Element element = node.element; @@ -80,14 +80,14 @@ if (!element.isConst) { _errorReporter.reportErrorForNode( CompileTimeErrorCode.NON_CONSTANT_ANNOTATION_CONSTRUCTOR, node); - return null; + return; } // should have arguments ArgumentList argumentList = node.arguments; if (argumentList == null) { _errorReporter.reportErrorForNode( CompileTimeErrorCode.NO_ANNOTATION_CONSTRUCTOR_ARGUMENTS, node); - return null; + return; } // arguments should be constants _validateConstantArguments(argumentList); @@ -99,28 +99,26 @@ _errorReporter.reportErrorForNode( HintCode.INVALID_SEALED_ANNOTATION, node.parent, [node.element.name]); } - return null; } @override - Object visitConstructorDeclaration(ConstructorDeclaration node) { + void visitConstructorDeclaration(ConstructorDeclaration node) { if (node.constKeyword != null) { _validateConstructorInitializers(node); _validateFieldInitializers(node.parent as ClassDeclaration, node); } _validateDefaultValues(node.parameters); - return super.visitConstructorDeclaration(node); + super.visitConstructorDeclaration(node); } @override - Object visitFunctionExpression(FunctionExpression node) { + void visitFunctionExpression(FunctionExpression node) { super.visitFunctionExpression(node); _validateDefaultValues(node.parameters); - return null; } @override - Object visitInstanceCreationExpression(InstanceCreationExpression node) { + void visitInstanceCreationExpression(InstanceCreationExpression node) { if (node.isConst) { TypeName typeName = node.constructorName.type; _checkForConstWithTypeParameters(typeName); @@ -138,14 +136,13 @@ constantVisitor, _errorReporter); } - return null; } else { - return super.visitInstanceCreationExpression(node); + super.visitInstanceCreationExpression(node); } } @override - Object visitListLiteral(ListLiteral node) { + void visitListLiteral(ListLiteral node) { super.visitListLiteral(node); if (node.isConst) { DartObjectImpl result; @@ -160,11 +157,10 @@ } } } - return null; } @override - Object visitMapLiteral(MapLiteral node) { + void visitMapLiteral(MapLiteral node) { super.visitMapLiteral(node); bool isConst = node.isConst; bool reportEqualKeys = true; @@ -227,18 +223,41 @@ StaticWarningCode.EQUAL_KEYS_IN_MAP, invalidKeys[i]); } } - return null; } @override - Object visitMethodDeclaration(MethodDeclaration node) { + void visitMethodDeclaration(MethodDeclaration node) { super.visitMethodDeclaration(node); _validateDefaultValues(node.parameters); - return null; } @override - Object visitSwitchStatement(SwitchStatement node) { + void visitSetLiteral(SetLiteral node) { + super.visitSetLiteral(node); + if (node.isConst) { + DartObjectImpl result; + for (Expression element in node.elements) { + result = + _validate(element, CompileTimeErrorCode.NON_CONSTANT_SET_ELEMENT); + if (result != null) { + _reportErrorIfFromDeferredLibrary( + element, + CompileTimeErrorCode + .NON_CONSTANT_SET_ELEMENT_FROM_DEFERRED_LIBRARY); + DartType type = result.type; + if (_implementsEqualsWhenNotAllowed(type)) { + _errorReporter.reportErrorForNode( + CompileTimeErrorCode.CONST_SET_ELEMENT_TYPE_IMPLEMENTS_EQUALS, + element, + [type.displayName]); + } + } + } + } + } + + @override + void visitSwitchStatement(SwitchStatement node) { // TODO(paulberry): to minimize error messages, it would be nice to // compare all types with the most popular type rather than the first // type. @@ -274,11 +293,11 @@ if (!foundError) { _checkForCaseExpressionTypeImplementsEquals(node, firstType); } - return super.visitSwitchStatement(node); + super.visitSwitchStatement(node); } @override - Object visitVariableDeclaration(VariableDeclaration node) { + void visitVariableDeclaration(VariableDeclaration node) { super.visitVariableDeclaration(node); Expression initializer = node.initializer; if (initializer != null && (node.isConst || node.isFinal)) { @@ -290,7 +309,7 @@ // values computed if the value was needed (e.g. final variables in a // class containing const constructors). assert(!node.isConst); - return null; + return; } _reportErrors(result.errors, CompileTimeErrorCode.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE); @@ -299,7 +318,6 @@ CompileTimeErrorCode .CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE_FROM_DEFERRED_LIBRARY); } - return null; } /// This verifies that the passed switch statement does not have a case @@ -409,12 +427,12 @@ identical(dataErrorCode, CompileTimeErrorCode.CONST_EVAL_TYPE_BOOL_NUM_STRING) || identical(dataErrorCode, CompileTimeErrorCode.CONST_EVAL_TYPE_BOOL) || + identical( + dataErrorCode, CompileTimeErrorCode.CONST_EVAL_TYPE_BOOL_INT) || identical(dataErrorCode, CompileTimeErrorCode.CONST_EVAL_TYPE_INT) || identical(dataErrorCode, CompileTimeErrorCode.CONST_EVAL_TYPE_NUM) || identical(dataErrorCode, CompileTimeErrorCode.RECURSIVE_COMPILE_TIME_CONSTANT) || - identical(dataErrorCode, - CheckedModeCompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION) || identical( dataErrorCode, CheckedModeCompileTimeErrorCode
diff --git a/pkg/analyzer/lib/src/dart/constant/evaluation.dart b/pkg/analyzer/lib/src/dart/constant/evaluation.dart index 3cab468..922caa0 100644 --- a/pkg/analyzer/lib/src/dart/constant/evaluation.dart +++ b/pkg/analyzer/lib/src/dart/constant/evaluation.dart
@@ -1,4 +1,4 @@ -// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file +// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. @@ -14,6 +14,7 @@ import 'package:analyzer/dart/element/type.dart'; import 'package:analyzer/error/error.dart'; import 'package:analyzer/error/listener.dart'; +import 'package:analyzer/src/dart/analysis/experiments.dart'; import 'package:analyzer/src/dart/constant/utilities.dart'; import 'package:analyzer/src/dart/constant/value.dart'; import 'package:analyzer/src/dart/element/element.dart'; @@ -36,6 +37,7 @@ * Parameter to "fromEnvironment" methods that denotes the default value. */ static String _DEFAULT_VALUE_PARAM = "defaultValue"; + /** * Source of RegExp matching declarable operator names. * From sdk/lib/internal/symbol.dart. @@ -84,6 +86,11 @@ final DeclaredVariables _declaredVariables; /** + * Return the object representing the state of active experiments. + */ + final Experiments experiments; + + /** * Validator used to verify correct dependency analysis when running unit * tests. */ @@ -103,12 +110,14 @@ */ ConstantEvaluationEngine(TypeProvider typeProvider, this._declaredVariables, {ConstantEvaluationValidator validator, + Experiments experiments, TypeSystem typeSystem, this.forAnalysisDriver: false}) : typeProvider = typeProvider, validator = validator ?? new ConstantEvaluationValidator_ForProduction(), - typeSystem = typeSystem ?? new StrongTypeSystemImpl(typeProvider); + typeSystem = typeSystem ?? new StrongTypeSystemImpl(typeProvider), + experiments = experiments ?? new Experiments(new AnalysisOptionsImpl()); /** * Check that the arguments to a call to fromEnvironment() are correct. The @@ -246,7 +255,7 @@ // ignore it here. constant.evaluationResult = new EvaluationResultImpl(null); } - } else if (element is ConstructorElementImpl && + } else if (element is ConstructorElement && element.isConst && constNode.arguments != null) { RecordingErrorListener errorListener = new RecordingErrorListener(); @@ -445,6 +454,7 @@ CompileTimeErrorCode.CONST_WITH_NON_CONST, node); return null; } + if (!getConstructorImpl(constructor).isCycleFree) { // It's not safe to evaluate this constructor, so bail out. // TODO(paulberry): ensure that a reasonable error message is produced @@ -453,34 +463,35 @@ // itself") return new DartObjectImpl.validWithUnknownValue(constructor.returnType); } + int argumentCount = arguments.length; - List<DartObjectImpl> argumentValues = - new List<DartObjectImpl>(argumentCount); - List<DartObjectImpl> positionalArguments = <DartObjectImpl>[]; - List<Expression> argumentNodes = new List<Expression>(argumentCount); - Map<String, DartObjectImpl> namedArgumentValues = - new HashMap<String, DartObjectImpl>(); - Map<String, NamedExpression> namedArgumentNodes = - new HashMap<String, NamedExpression>(); + var argumentValues = new List<DartObjectImpl>(argumentCount); + Map<String, NamedExpression> namedNodes; + Map<String, DartObjectImpl> namedValues; for (int i = 0; i < argumentCount; i++) { Expression argument = arguments[i]; if (argument is NamedExpression) { + namedNodes ??= new HashMap<String, NamedExpression>(); + namedValues ??= new HashMap<String, DartObjectImpl>(); String name = argument.name.label.name; - namedArgumentValues[name] = - constantVisitor._valueOf(argument.expression); - namedArgumentNodes[name] = argument; - argumentValues[i] = typeProvider.nullObject; + namedNodes[name] = argument; + namedValues[name] = constantVisitor._valueOf(argument.expression); } else { var argumentValue = constantVisitor._valueOf(argument); argumentValues[i] = argumentValue; - positionalArguments.add(argumentValue); - argumentNodes[i] = argument; } } + namedNodes ??= const {}; + namedValues ??= const {}; + if (invocation == null) { invocation = new ConstructorInvocation( - constructor, positionalArguments, namedArgumentValues); + constructor, + argumentValues, + namedValues, + ); } + constructor = followConstantRedirectionChain(constructor); InterfaceType definingClass = constructor.returnType as InterfaceType; if (constructor.isFactory) { @@ -489,7 +500,7 @@ // that we can emulate. if (constructor.name == "fromEnvironment") { if (!checkFromEnvironmentArguments( - arguments, argumentValues, namedArgumentValues, definingClass)) { + arguments, argumentValues, namedValues, definingClass)) { errorReporter.reportErrorForNode( CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION, node); return null; @@ -503,7 +514,7 @@ return computeValueFromEnvironment( valueFromEnvironment, new DartObjectImpl(typeProvider.boolType, BoolState.FALSE_STATE), - namedArgumentValues); + namedValues); } else if (definingClass == typeProvider.intType) { DartObject valueFromEnvironment; valueFromEnvironment = @@ -511,7 +522,7 @@ return computeValueFromEnvironment( valueFromEnvironment, new DartObjectImpl(typeProvider.nullType, NullState.NULL_STATE), - namedArgumentValues); + namedValues); } else if (definingClass == typeProvider.stringType) { DartObject valueFromEnvironment; valueFromEnvironment = @@ -519,13 +530,12 @@ return computeValueFromEnvironment( valueFromEnvironment, new DartObjectImpl(typeProvider.nullType, NullState.NULL_STATE), - namedArgumentValues); + namedValues); } } else if (constructor.name == "" && definingClass == typeProvider.symbolType && argumentCount == 1) { - if (!checkSymbolArguments( - arguments, argumentValues, namedArgumentValues)) { + if (!checkSymbolArguments(arguments, argumentValues, namedValues)) { errorReporter.reportErrorForNode( CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION, node); return null; @@ -562,28 +572,10 @@ // into the current ErrorReporter, because they usually happen in a // different source. But they still should cause a constant evaluation // error for the current node. - var externalErrorListener = new RecordingErrorListener(); + var externalErrorListener = new BooleanErrorListener(); var externalErrorReporter = new ErrorReporter(externalErrorListener, constructor.source); - void reportLocalErrorForRecordedExternalErrors() { - ErrorCode errorCode; - for (AnalysisError error in externalErrorListener.errors) { - if (error.errorCode is CompileTimeErrorCode) { - errorCode = CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION; - break; - } - if (error.errorCode is CheckedModeCompileTimeErrorCode) { - errorCode = - CheckedModeCompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION; - break; - } - } - if (errorCode != null) { - errorReporter.reportErrorForNode(errorCode, node); - } - } - // Start with final fields that are initialized at their declaration site. List<FieldElement> fields = constructor.enclosingElement.fields; for (int i = 0; i < fields.length; i++) { @@ -629,11 +621,11 @@ DartObjectImpl argumentValue = null; AstNode errorTarget = null; if (baseParameter.isNamed) { - argumentValue = namedArgumentValues[baseParameter.name]; - errorTarget = namedArgumentNodes[baseParameter.name]; + argumentValue = namedValues[baseParameter.name]; + errorTarget = namedNodes[baseParameter.name]; } else if (i < argumentCount) { argumentValue = argumentValues[i]; - errorTarget = argumentNodes[i]; + errorTarget = arguments[i]; } if (errorTarget == null) { // No argument node that we can direct error messages to, because we @@ -695,7 +687,8 @@ lexicalEnvironment: parameterMap); String superName = null; NodeList<Expression> superArguments = null; - for (ConstructorInitializer initializer in initializers) { + for (var i = 0; i < initializers.length; i++) { + var initializer = initializers[i]; if (initializer is ConstructorFieldInitializer) { Expression initializerExpression = initializer.expression; DartObjectImpl evaluationResult = @@ -743,23 +736,24 @@ initializerVisitor, externalErrorReporter, invocation: invocation); - reportLocalErrorForRecordedExternalErrors(); + if (externalErrorListener.errorReported) { + errorReporter.reportErrorForNode( + CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION, node); + } return result; } } else if (initializer is AssertInitializer) { Expression condition = initializer.condition; if (condition == null) { errorReporter.reportErrorForNode( - CheckedModeCompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION, - node); + CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION, node); } DartObjectImpl evaluationResult = condition.accept(initializerVisitor); if (evaluationResult == null || !evaluationResult.isBool || evaluationResult.toBoolValue() != true) { errorReporter.reportErrorForNode( - CheckedModeCompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION, - node); + CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION, node); return null; } } @@ -778,7 +772,10 @@ superArguments, initializerVisitor, externalErrorReporter); } } - reportLocalErrorForRecordedExternalErrors(); + if (externalErrorListener.errorReported) { + errorReporter.reportErrorForNode( + CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION, node); + } return new DartObjectImpl( definingClass, new GenericState(fieldMap, invocation: invocation)); } @@ -1075,10 +1072,9 @@ } /** - * Convenience getter to gain access to the [evalationEngine]'s type - * provider. + * Return the object representing the state of active experiments. */ - TypeProvider get _typeProvider => evaluationEngine.typeProvider; + Experiments get experiments => evaluationEngine.experiments; /** * Convenience getter to gain access to the [evaluationEngine]'s type system. @@ -1086,6 +1082,12 @@ TypeSystem get typeSystem => evaluationEngine.typeSystem; /** + * Convenience getter to gain access to the [evaluationEngine]'s type + * provider. + */ + TypeProvider get _typeProvider => evaluationEngine.typeProvider; + + /** * Given a [type] that may contain free type variables, evaluate them against * the current lexical environment and return the substituted type. */ @@ -1133,27 +1135,50 @@ } @override + DartObjectImpl visitAsExpression(AsExpression node) { + if (experiments.constantUpdate2018) { + DartObjectImpl expressionResult = node.expression.accept(this); + DartObjectImpl typeResult = node.type.accept(this); + return _dartObjectComputer.castToType(node, expressionResult, typeResult); + } + // TODO(brianwilkerson) Figure out which error to report. + _error(node, null); + return null; + } + + @override DartObjectImpl visitBinaryExpression(BinaryExpression node) { TokenType operatorType = node.operator.type; DartObjectImpl leftResult = node.leftOperand.accept(this); // evaluate lazy operators if (operatorType == TokenType.AMPERSAND_AMPERSAND) { - return _dartObjectComputer.logicalAnd( + return _dartObjectComputer.lazyAnd( node, leftResult, () => node.rightOperand.accept(this)); } else if (operatorType == TokenType.BAR_BAR) { - return _dartObjectComputer.logicalOr( + return _dartObjectComputer.lazyOr( node, leftResult, () => node.rightOperand.accept(this)); + } else if (operatorType == TokenType.QUESTION_QUESTION) { + if (experiments.constantUpdate2018) { + return _dartObjectComputer.lazyQuestionQuestion( + node, leftResult, () => node.rightOperand.accept(this)); + } else { + return _dartObjectComputer.eagerQuestionQuestion( + node, leftResult, node.rightOperand.accept(this)); + } } // evaluate eager operators DartObjectImpl rightResult = node.rightOperand.accept(this); if (operatorType == TokenType.AMPERSAND) { - return _dartObjectComputer.bitAnd(node, leftResult, rightResult); + return _dartObjectComputer.eagerAnd( + node, leftResult, rightResult, experiments.constantUpdate2018); } else if (operatorType == TokenType.BANG_EQ) { return _dartObjectComputer.notEqual(node, leftResult, rightResult); } else if (operatorType == TokenType.BAR) { - return _dartObjectComputer.bitOr(node, leftResult, rightResult); + return _dartObjectComputer.eagerOr( + node, leftResult, rightResult, experiments.constantUpdate2018); } else if (operatorType == TokenType.CARET) { - return _dartObjectComputer.bitXor(node, leftResult, rightResult); + return _dartObjectComputer.eagerXor( + node, leftResult, rightResult, experiments.constantUpdate2018); } else if (operatorType == TokenType.EQ_EQ) { return _dartObjectComputer.equalEqual(node, leftResult, rightResult); } else if (operatorType == TokenType.GT) { @@ -1181,9 +1206,6 @@ return _dartObjectComputer.divide(node, leftResult, rightResult); } else if (operatorType == TokenType.TILDE_SLASH) { return _dartObjectComputer.integerDivide(node, leftResult, rightResult); - } else if (operatorType == TokenType.QUESTION_QUESTION) { - return _dartObjectComputer.questionQuestion( - node, leftResult, rightResult); } else { // TODO(brianwilkerson) Figure out which error to report. _error(node, null); @@ -1199,6 +1221,30 @@ DartObjectImpl visitConditionalExpression(ConditionalExpression node) { Expression condition = node.condition; DartObjectImpl conditionResult = condition.accept(this); + if (experiments.constantUpdate2018) { + if (conditionResult == null) { + return conditionResult; + } else if (!conditionResult.isBool) { + _errorReporter.reportErrorForNode( + CompileTimeErrorCode.CONST_EVAL_TYPE_BOOL, condition); + return null; + } + conditionResult = _dartObjectComputer.applyBooleanConversion( + condition, conditionResult); + if (conditionResult == null) { + return conditionResult; + } + if (conditionResult.toBoolValue() == true) { + return node.thenExpression.accept(this); + } else if (conditionResult.toBoolValue() == false) { + return node.elseExpression.accept(this); + } + // We used to return an object with a known type and an unknown value, but + // we can't do that without evaluating both the 'then' and 'else' + // expressions, and we're not suppose to do that under lazy semantics. I'm + // not sure which failure mode is worse. + return null; + } DartObjectImpl thenResult = node.thenExpression.accept(this); DartObjectImpl elseResult = node.elseExpression.accept(this); if (conditionResult == null) { @@ -1270,6 +1316,18 @@ new DartObjectImpl(_typeProvider.stringType, new StringState(node.value)); @override + DartObjectImpl visitIsExpression(IsExpression node) { + if (experiments.constantUpdate2018) { + DartObjectImpl expressionResult = node.expression.accept(this); + DartObjectImpl typeResult = node.type.accept(this); + return _dartObjectComputer.typeTest(node, expressionResult, typeResult); + } + // TODO(brianwilkerson) Figure out which error to report. + _error(node, null); + return null; + } + + @override DartObjectImpl visitListLiteral(ListLiteral node) { if (!node.isConst) { _errorReporter.reportErrorForNode( @@ -1433,6 +1491,35 @@ } @override + DartObjectImpl visitSetLiteral(SetLiteral node) { + if (!node.isConst) { + _errorReporter.reportErrorForNode( + CompileTimeErrorCode.MISSING_CONST_IN_SET_LITERAL, node); + return null; + } + bool errorOccurred = false; + Set<DartObjectImpl> elements = new Set<DartObjectImpl>(); + for (Expression element in node.elements) { + DartObjectImpl elementResult = element.accept(this); + if (elementResult == null) { + errorOccurred = true; + } else { + elements.add(elementResult); + } + } + if (errorOccurred) { + return null; + } + DartType nodeType = node.staticType; + DartType elementType = + nodeType is InterfaceType && nodeType.typeArguments.isNotEmpty + ? nodeType.typeArguments[0] + : _typeProvider.dynamicType; + InterfaceType setType = _typeProvider.setType.instantiate([elementType]); + return new DartObjectImpl(setType, new SetState(elements)); + } + + @override DartObjectImpl visitSimpleIdentifier(SimpleIdentifier node) { if (_lexicalEnvironment != null && _lexicalEnvironment.containsKey(node.name)) { @@ -1521,8 +1608,9 @@ // Driver, we compute values of all dependencies first (or detect cycle). // So, the value has already been computed. Just return it. if (evaluationEngine.forAnalysisDriver) { - if (variableElement.isConst) { - return variableElement.evaluationResult.value; + EvaluationResultImpl value = variableElement.evaluationResult; + if (variableElement.isConst && value != null) { + return value.value; } } else { // TODO(scheglov) Once we remove task model, we can remove this code. @@ -1626,18 +1714,6 @@ return null; } - DartObjectImpl bitAnd(BinaryExpression node, DartObjectImpl leftOperand, - DartObjectImpl rightOperand) { - if (leftOperand != null && rightOperand != null) { - try { - return leftOperand.bitAnd(_typeProvider, rightOperand); - } on EvaluationException catch (exception) { - _errorReporter.reportErrorForNode(exception.errorCode, node); - } - } - return null; - } - DartObjectImpl bitNot(Expression node, DartObjectImpl evaluationResult) { if (evaluationResult != null) { try { @@ -1649,23 +1725,11 @@ return null; } - DartObjectImpl bitOr(BinaryExpression node, DartObjectImpl leftOperand, - DartObjectImpl rightOperand) { - if (leftOperand != null && rightOperand != null) { + DartObjectImpl castToType( + AsExpression node, DartObjectImpl expression, DartObjectImpl type) { + if (expression != null && type != null) { try { - return leftOperand.bitOr(_typeProvider, rightOperand); - } on EvaluationException catch (exception) { - _errorReporter.reportErrorForNode(exception.errorCode, node); - } - } - return null; - } - - DartObjectImpl bitXor(BinaryExpression node, DartObjectImpl leftOperand, - DartObjectImpl rightOperand) { - if (leftOperand != null && rightOperand != null) { - try { - return leftOperand.bitXor(_typeProvider, rightOperand); + return expression.castToType(_typeProvider, type); } on EvaluationException catch (exception) { _errorReporter.reportErrorForNode(exception.errorCode, node); } @@ -1697,6 +1761,53 @@ return null; } + DartObjectImpl eagerAnd(BinaryExpression node, DartObjectImpl leftOperand, + DartObjectImpl rightOperand, bool allowBool) { + if (leftOperand != null && rightOperand != null) { + try { + return leftOperand.eagerAnd(_typeProvider, rightOperand, allowBool); + } on EvaluationException catch (exception) { + _errorReporter.reportErrorForNode(exception.errorCode, node); + } + } + return null; + } + + DartObjectImpl eagerOr(BinaryExpression node, DartObjectImpl leftOperand, + DartObjectImpl rightOperand, bool allowBool) { + if (leftOperand != null && rightOperand != null) { + try { + return leftOperand.eagerOr(_typeProvider, rightOperand, allowBool); + } on EvaluationException catch (exception) { + _errorReporter.reportErrorForNode(exception.errorCode, node); + } + } + return null; + } + + DartObjectImpl eagerQuestionQuestion(Expression node, + DartObjectImpl leftOperand, DartObjectImpl rightOperand) { + if (leftOperand != null && rightOperand != null) { + if (leftOperand.isNull) { + return rightOperand; + } + return leftOperand; + } + return null; + } + + DartObjectImpl eagerXor(BinaryExpression node, DartObjectImpl leftOperand, + DartObjectImpl rightOperand, bool allowBool) { + if (leftOperand != null && rightOperand != null) { + try { + return leftOperand.eagerXor(_typeProvider, rightOperand, allowBool); + } on EvaluationException catch (exception) { + _errorReporter.reportErrorForNode(exception.errorCode, node); + } + } + return null; + } + DartObjectImpl equalEqual(Expression node, DartObjectImpl leftOperand, DartObjectImpl rightOperand) { if (leftOperand != null && rightOperand != null) { @@ -1757,6 +1868,41 @@ return null; } + DartObjectImpl lazyAnd(BinaryExpression node, DartObjectImpl leftOperand, + DartObjectImpl rightOperandComputer()) { + if (leftOperand != null) { + try { + return leftOperand.lazyAnd(_typeProvider, rightOperandComputer); + } on EvaluationException catch (exception) { + _errorReporter.reportErrorForNode(exception.errorCode, node); + } + } + return null; + } + + DartObjectImpl lazyOr(BinaryExpression node, DartObjectImpl leftOperand, + DartObjectImpl rightOperandComputer()) { + if (leftOperand != null) { + try { + return leftOperand.lazyOr(_typeProvider, rightOperandComputer); + } on EvaluationException catch (exception) { + _errorReporter.reportErrorForNode(exception.errorCode, node); + } + } + return null; + } + + DartObjectImpl lazyQuestionQuestion(Expression node, + DartObjectImpl leftOperand, DartObjectImpl rightOperandComputer()) { + if (leftOperand != null) { + if (leftOperand.isNull) { + return rightOperandComputer(); + } + return leftOperand; + } + return null; + } + DartObjectImpl lessThan(BinaryExpression node, DartObjectImpl leftOperand, DartObjectImpl rightOperand) { if (leftOperand != null && rightOperand != null) { @@ -1781,18 +1927,6 @@ return null; } - DartObjectImpl logicalAnd(BinaryExpression node, DartObjectImpl leftOperand, - DartObjectImpl rightOperandComputer()) { - if (leftOperand != null) { - try { - return leftOperand.logicalAnd(_typeProvider, rightOperandComputer); - } on EvaluationException catch (exception) { - _errorReporter.reportErrorForNode(exception.errorCode, node); - } - } - return null; - } - DartObjectImpl logicalNot(Expression node, DartObjectImpl evaluationResult) { if (evaluationResult != null) { try { @@ -1804,18 +1938,6 @@ return null; } - DartObjectImpl logicalOr(BinaryExpression node, DartObjectImpl leftOperand, - DartObjectImpl rightOperandComputer()) { - if (leftOperand != null) { - try { - return leftOperand.logicalOr(_typeProvider, rightOperandComputer); - } on EvaluationException catch (exception) { - _errorReporter.reportErrorForNode(exception.errorCode, node); - } - } - return null; - } - DartObjectImpl minus(BinaryExpression node, DartObjectImpl leftOperand, DartObjectImpl rightOperand) { if (leftOperand != null && rightOperand != null) { @@ -1863,17 +1985,6 @@ return null; } - DartObjectImpl questionQuestion(Expression node, DartObjectImpl leftOperand, - DartObjectImpl rightOperand) { - if (leftOperand != null && rightOperand != null) { - if (leftOperand.isNull) { - return rightOperand; - } - return leftOperand; - } - return null; - } - DartObjectImpl remainder(BinaryExpression node, DartObjectImpl leftOperand, DartObjectImpl rightOperand) { if (leftOperand != null && rightOperand != null) { @@ -1939,6 +2050,22 @@ } return null; } + + DartObjectImpl typeTest( + IsExpression node, DartObjectImpl expression, DartObjectImpl type) { + if (expression != null && type != null) { + try { + DartObjectImpl result = expression.hasType(_typeProvider, type); + if (node.notOperator != null) { + return result.logicalNot(_typeProvider); + } + return result; + } on EvaluationException catch (exception) { + _errorReporter.reportErrorForNode(exception.errorCode, node); + } + } + return null; + } } /**
diff --git a/pkg/analyzer/lib/src/dart/constant/utilities.dart b/pkg/analyzer/lib/src/dart/constant/utilities.dart index 50480ad..b0aa23a 100644 --- a/pkg/analyzer/lib/src/dart/constant/utilities.dart +++ b/pkg/analyzer/lib/src/dart/constant/utilities.dart
@@ -1,4 +1,4 @@ -// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file +// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. @@ -106,6 +106,16 @@ } @override + SetLiteral visitSetLiteral(SetLiteral node) { + SetLiteral literal = super.visitSetLiteral(node); + literal.staticType = node.staticType; + if (node.constKeyword == null && node.isConst) { + literal.constKeyword = new KeywordToken(Keyword.CONST, node.offset); + } + return literal; + } + + @override SimpleIdentifier visitSimpleIdentifier(SimpleIdentifier node) { SimpleIdentifier identifier = super.visitSimpleIdentifier(node); identifier.staticElement = node.staticElement; @@ -173,6 +183,15 @@ } @override + void visitSetLiteral(SetLiteral node) { + if (node.isConst) { + _find(node); + } else { + super.visitSetLiteral(node); + } + } + + @override void visitSwitchCase(SwitchCase node) { _find(node.expression); node.statements.accept(this); @@ -192,7 +211,7 @@ * constructors, constant constructor invocations, and annotations found in * those compilation units. */ -class ConstantFinder extends RecursiveAstVisitor<Object> { +class ConstantFinder extends RecursiveAstVisitor<void> { /** * The elements and AST nodes whose constant values need to be computed. */ @@ -206,7 +225,7 @@ bool treatFinalInstanceVarAsConst = false; @override - Object visitAnnotation(Annotation node) { + void visitAnnotation(Annotation node) { super.visitAnnotation(node); ElementAnnotation elementAnnotation = node.elementAnnotation; if (elementAnnotation == null) { @@ -217,11 +236,10 @@ } else { constantsToCompute.add(elementAnnotation); } - return null; } @override - Object visitClassDeclaration(ClassDeclaration node) { + void visitClassDeclaration(ClassDeclaration node) { bool prevTreatFinalInstanceVarAsConst = treatFinalInstanceVarAsConst; if (resolutionMap .elementDeclaredByClassDeclaration(node) @@ -233,14 +251,14 @@ treatFinalInstanceVarAsConst = true; } try { - return super.visitClassDeclaration(node); + super.visitClassDeclaration(node); } finally { treatFinalInstanceVarAsConst = prevTreatFinalInstanceVarAsConst; } } @override - Object visitConstructorDeclaration(ConstructorDeclaration node) { + void visitConstructorDeclaration(ConstructorDeclaration node) { super.visitConstructorDeclaration(node); if (node.constKeyword != null) { ConstructorElement element = node.declaredElement; @@ -249,22 +267,20 @@ constantsToCompute.addAll(element.parameters); } } - return null; } @override - Object visitDefaultFormalParameter(DefaultFormalParameter node) { + void visitDefaultFormalParameter(DefaultFormalParameter node) { super.visitDefaultFormalParameter(node); Expression defaultValue = node.defaultValue; if (defaultValue != null && node.declaredElement != null) { constantsToCompute .add(resolutionMap.elementDeclaredByFormalParameter(node)); } - return null; } @override - Object visitVariableDeclaration(VariableDeclaration node) { + void visitVariableDeclaration(VariableDeclaration node) { super.visitVariableDeclaration(node); Expression initializer = node.initializer; VariableElement element = node.declaredElement; @@ -278,7 +294,6 @@ constantsToCompute.add(element); } } - return null; } } @@ -286,7 +301,7 @@ * An object used to add reference information for a given variable to the * bi-directional mapping used to order the evaluation of constants. */ -class ReferenceFinder extends RecursiveAstVisitor<Object> { +class ReferenceFinder extends RecursiveAstVisitor<void> { /** * The callback which should be used to report any dependencies that were * found. @@ -301,39 +316,37 @@ ReferenceFinder(this._callback); @override - Object visitInstanceCreationExpression(InstanceCreationExpression node) { + void visitInstanceCreationExpression(InstanceCreationExpression node) { if (node.isConst) { ConstructorElement constructor = getConstructorImpl(node.staticElement); if (constructor != null) { _callback(constructor); } } - return super.visitInstanceCreationExpression(node); + super.visitInstanceCreationExpression(node); } @override - Object visitLabel(Label node) { + void visitLabel(Label node) { // We are visiting the "label" part of a named expression in a function // call (presumably a constructor call), e.g. "const C(label: ...)". We // don't want to visit the SimpleIdentifier for the label because that's a // reference to a function parameter that needs to be filled in; it's not a // constant whose value we depend on. - return null; } @override - Object visitRedirectingConstructorInvocation( + void visitRedirectingConstructorInvocation( RedirectingConstructorInvocation node) { super.visitRedirectingConstructorInvocation(node); ConstructorElement target = getConstructorImpl(node.staticElement); if (target != null) { _callback(target); } - return null; } @override - Object visitSimpleIdentifier(SimpleIdentifier node) { + void visitSimpleIdentifier(SimpleIdentifier node) { Element staticElement = node.staticElement; Element element = staticElement is PropertyAccessorElement ? staticElement.variable @@ -341,16 +354,14 @@ if (element is VariableElement && element.isConst) { _callback(element); } - return null; } @override - Object visitSuperConstructorInvocation(SuperConstructorInvocation node) { + void visitSuperConstructorInvocation(SuperConstructorInvocation node) { super.visitSuperConstructorInvocation(node); ConstructorElement constructor = getConstructorImpl(node.staticElement); if (constructor != null) { _callback(constructor); } - return null; } }
diff --git a/pkg/analyzer/lib/src/dart/constant/value.dart b/pkg/analyzer/lib/src/dart/constant/value.dart index cca4d22..e15ba2e 100644 --- a/pkg/analyzer/lib/src/dart/constant/value.dart +++ b/pkg/analyzer/lib/src/dart/constant/value.dart
@@ -98,7 +98,7 @@ } @override - BoolState logicalAnd(InstanceState rightOperandComputer()) { + BoolState lazyAnd(InstanceState rightOperandComputer()) { if (value == false) { return FALSE_STATE; } @@ -108,6 +108,16 @@ } @override + BoolState lazyOr(InstanceState rightOperandComputer()) { + if (value == true) { + return TRUE_STATE; + } + InstanceState rightOperand = rightOperandComputer(); + assertBool(rightOperand); + return value == null ? UNKNOWN_VALUE : rightOperand.convertToBool(); + } + + @override BoolState logicalNot() { if (value == null) { return UNKNOWN_VALUE; @@ -116,16 +126,6 @@ } @override - BoolState logicalOr(InstanceState rightOperandComputer()) { - if (value == true) { - return TRUE_STATE; - } - InstanceState rightOperand = rightOperandComputer(); - assertBool(rightOperand); - return value == null ? UNKNOWN_VALUE : rightOperand.convertToBool(); - } - - @override String toString() => value == null ? "-unknown-" : (value ? "true" : "false"); /** @@ -145,9 +145,10 @@ final ConstructorElement constructor; /** - * The positional arguments passed to the constructor. + * Values of specified arguments, actual values for positional, and `null` + * for named (which are provided as [namedArguments]). */ - final List<DartObjectImpl> positionalArguments; + final List<DartObjectImpl> _argumentValues; /** * The named arguments passed to the constructor. @@ -155,7 +156,14 @@ final Map<String, DartObjectImpl> namedArguments; ConstructorInvocation( - this.constructor, this.positionalArguments, this.namedArguments); + this.constructor, this._argumentValues, this.namedArguments); + + /** + * The positional arguments passed to the constructor. + */ + List<DartObjectImpl> get positionalArguments { + return _argumentValues.takeWhile((v) => v != null).toList(); + } } /** @@ -219,6 +227,11 @@ */ bool get isBoolNumStringOrNull => _state.isBoolNumStringOrNull; + /** + * Return `true` if this object represents an object whose type is 'int'. + */ + bool get isInt => _state.isInt; + @override bool get isNull => _state is NullState; @@ -265,19 +278,6 @@ } /** - * Return the result of invoking the '&' operator on this object with the - * [rightOperand]. The [typeProvider] is the type provider used to find known - * types. - * - * Throws an [EvaluationException] if the operator is not appropriate for an - * object of this kind. - */ - DartObjectImpl bitAnd( - TypeProvider typeProvider, DartObjectImpl rightOperand) => - new DartObjectImpl( - typeProvider.intType, _state.bitAnd(rightOperand._state)); - - /** * Return the result of invoking the '~' operator on this object. The * [typeProvider] is the type provider used to find known types. * @@ -288,30 +288,20 @@ new DartObjectImpl(typeProvider.intType, _state.bitNot()); /** - * Return the result of invoking the '|' operator on this object with the - * [rightOperand]. The [typeProvider] is the type provider used to find known - * types. - * - * Throws an [EvaluationException] if the operator is not appropriate for an - * object of this kind. + * Return the result of casting this object to the given [castType]. */ - DartObjectImpl bitOr( - TypeProvider typeProvider, DartObjectImpl rightOperand) => - new DartObjectImpl( - typeProvider.intType, _state.bitOr(rightOperand._state)); - - /** - * Return the result of invoking the '^' operator on this object with the - * [rightOperand]. The [typeProvider] is the type provider used to find known - * types. - * - * Throws an [EvaluationException] if the operator is not appropriate for an - * object of this kind. - */ - DartObjectImpl bitXor( - TypeProvider typeProvider, DartObjectImpl rightOperand) => - new DartObjectImpl( - typeProvider.intType, _state.bitXor(rightOperand._state)); + DartObjectImpl castToType( + TypeProvider typeProvider, DartObjectImpl castType) { + _assertType(castType); + if (isNull) { + return this; + } + if (!type.isSubtypeOf((castType._state as TypeState)._type)) { + throw new EvaluationException( + CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION); + } + return this; + } /** * Return the result of invoking the ' ' operator on this object with the @@ -364,6 +354,69 @@ } /** + * Return the result of invoking the '&' operator on this object with the + * [rightOperand]. The [typeProvider] is the type provider used to find known + * types. + * + * Throws an [EvaluationException] if the operator is not appropriate for an + * object of this kind. + */ + DartObjectImpl eagerAnd( + TypeProvider typeProvider, DartObjectImpl rightOperand, bool allowBool) { + if (allowBool && isBool && rightOperand.isBool) { + return new DartObjectImpl( + typeProvider.boolType, _state.logicalAnd(rightOperand._state)); + } else if (isInt && rightOperand.isInt) { + return new DartObjectImpl( + typeProvider.intType, _state.bitAnd(rightOperand._state)); + } + throw new EvaluationException( + CompileTimeErrorCode.CONST_EVAL_TYPE_BOOL_INT); + } + + /** + * Return the result of invoking the '|' operator on this object with the + * [rightOperand]. The [typeProvider] is the type provider used to find known + * types. + * + * Throws an [EvaluationException] if the operator is not appropriate for an + * object of this kind. + */ + DartObjectImpl eagerOr( + TypeProvider typeProvider, DartObjectImpl rightOperand, bool allowBool) { + if (allowBool && isBool && rightOperand.isBool) { + return new DartObjectImpl( + typeProvider.boolType, _state.logicalOr(rightOperand._state)); + } else if (isInt && rightOperand.isInt) { + return new DartObjectImpl( + typeProvider.intType, _state.bitOr(rightOperand._state)); + } + throw new EvaluationException( + CompileTimeErrorCode.CONST_EVAL_TYPE_BOOL_INT); + } + + /** + * Return the result of invoking the '^' operator on this object with the + * [rightOperand]. The [typeProvider] is the type provider used to find known + * types. + * + * Throws an [EvaluationException] if the operator is not appropriate for an + * object of this kind. + */ + DartObjectImpl eagerXor( + TypeProvider typeProvider, DartObjectImpl rightOperand, bool allowBool) { + if (allowBool && isBool && rightOperand.isBool) { + return new DartObjectImpl( + typeProvider.boolType, _state.logicalXor(rightOperand._state)); + } else if (isInt && rightOperand.isInt) { + return new DartObjectImpl( + typeProvider.intType, _state.bitXor(rightOperand._state)); + } + throw new EvaluationException( + CompileTimeErrorCode.CONST_EVAL_TYPE_BOOL_INT); + } + + /** * Return the result of invoking the '==' operator on this object with the * [rightOperand]. The [typeProvider] is the type provider used to find known * types. @@ -434,6 +487,27 @@ _state.greaterThanOrEqual(rightOperand._state)); /** + * Return the result of testing whether this object has the given [testedType]. + */ + DartObjectImpl hasType(TypeProvider typeProvider, DartObjectImpl testedType) { + _assertType(testedType); + DartType typeType = (testedType._state as TypeState)._type; + BoolState state; + if (isNull) { + if (typeType == typeProvider.objectType || + typeType == typeProvider.dynamicType || + typeType == typeProvider.nullType) { + state = BoolState.TRUE_STATE; + } else { + state = BoolState.FALSE_STATE; + } + } else { + state = BoolState.from(type.isSubtypeOf(typeType)); + } + return new DartObjectImpl(typeProvider.boolType, state); + } + + /** * Return the result of invoking the '~/' operator on this object with the * [rightOperand]. The [typeProvider] is the type provider used to find known * types. @@ -458,6 +532,32 @@ } /** + * Return the result of invoking the '&&' operator on this object with the + * [rightOperand]. The [typeProvider] is the type provider used to find known + * types. + * + * Throws an [EvaluationException] if the operator is not appropriate for an + * object of this kind. + */ + DartObjectImpl lazyAnd( + TypeProvider typeProvider, DartObjectImpl rightOperandComputer()) => + new DartObjectImpl(typeProvider.boolType, + _state.lazyAnd(() => rightOperandComputer()?._state)); + + /** + * Return the result of invoking the '||' operator on this object with the + * [rightOperand]. The [typeProvider] is the type provider used to find known + * types. + * + * Throws an [EvaluationException] if the operator is not appropriate for an + * object of this kind. + */ + DartObjectImpl lazyOr( + TypeProvider typeProvider, DartObjectImpl rightOperandComputer()) => + new DartObjectImpl(typeProvider.boolType, + _state.lazyOr(() => rightOperandComputer()?._state)); + + /** * Return the result of invoking the '<' operator on this object with the * [rightOperand]. The [typeProvider] is the type provider used to find known * types. @@ -484,19 +584,6 @@ typeProvider.boolType, _state.lessThanOrEqual(rightOperand._state)); /** - * Return the result of invoking the '&&' operator on this object with the - * [rightOperand]. The [typeProvider] is the type provider used to find known - * types. - * - * Throws an [EvaluationException] if the operator is not appropriate for an - * object of this kind. - */ - DartObjectImpl logicalAnd( - TypeProvider typeProvider, DartObjectImpl rightOperandComputer()) => - new DartObjectImpl(typeProvider.boolType, - _state.logicalAnd(() => rightOperandComputer()?._state)); - - /** * Return the result of invoking the '!' operator on this object. The * [typeProvider] is the type provider used to find known types. * @@ -507,19 +594,6 @@ new DartObjectImpl(typeProvider.boolType, _state.logicalNot()); /** - * Return the result of invoking the '||' operator on this object with the - * [rightOperand]. The [typeProvider] is the type provider used to find known - * types. - * - * Throws an [EvaluationException] if the operator is not appropriate for an - * object of this kind. - */ - DartObjectImpl logicalOr( - TypeProvider typeProvider, DartObjectImpl rightOperandComputer()) => - new DartObjectImpl(typeProvider.boolType, - _state.logicalOr(() => rightOperandComputer()?._state)); - - /** * Return the result of invoking the '-' operator on this object with the * [rightOperand]. The [typeProvider] is the type provider used to find known * types. @@ -722,6 +796,15 @@ } @override + Set<DartObject> toSetValue() { + InstanceState state = _state; + if (state is SetState) { + return state._elements; + } + return null; + } + + @override String toString() => "${type.displayName} ($_state)"; @override @@ -750,6 +833,16 @@ } return null; } + + /** + * Throw an exception if the given [object]'s state does not represent a Type + * value. + */ + void _assertType(DartObjectImpl object) { + if (object._state is! TypeState) { + throw new EvaluationException(CompileTimeErrorCode.CONST_EVAL_TYPE_TYPE); + } + } } /** @@ -1183,6 +1276,19 @@ } @override + BoolState lazyAnd(InstanceState rightOperandComputer()) { + assertBool(rightOperandComputer()); + return BoolState.UNKNOWN_VALUE; + } + + @override + BoolState lazyOr(InstanceState rightOperandComputer()) { + InstanceState rightOperand = rightOperandComputer(); + assertBool(rightOperand); + return rightOperand.convertToBool(); + } + + @override BoolState lessThan(InstanceState rightOperand) { assertNumOrNull(rightOperand); return BoolState.UNKNOWN_VALUE; @@ -1195,22 +1301,9 @@ } @override - BoolState logicalAnd(InstanceState rightOperandComputer()) { - assertBool(rightOperandComputer()); - return BoolState.UNKNOWN_VALUE; - } - - @override BoolState logicalNot() => BoolState.UNKNOWN_VALUE; @override - BoolState logicalOr(InstanceState rightOperandComputer()) { - InstanceState rightOperand = rightOperandComputer(); - assertBool(rightOperand); - return rightOperand.convertToBool(); - } - - @override NumState minus(InstanceState rightOperand) { assertNumOrNull(rightOperand); return _unknownNum(rightOperand); @@ -1461,6 +1554,16 @@ bool get isBoolNumStringOrNull => false; /** + * Return `true` if this object represents an object whose type is 'int'. + */ + bool get isInt => false; + + /** + * Return `true` if this object represents the value 'null'. + */ + bool get isNull => false; + + /** * Return `true` if this object represents an unknown value. */ bool get isUnknown => false; @@ -1704,6 +1807,40 @@ BoolState isIdentical(InstanceState rightOperand); /** + * Return the result of invoking the '&&' operator on this object with the + * [rightOperand]. + * + * Throws an [EvaluationException] if the operator is not appropriate for an + * object of this kind. + */ + BoolState lazyAnd(InstanceState rightOperandComputer()) { + assertBool(this); + if (convertToBool() == BoolState.FALSE_STATE) { + return this; + } + InstanceState rightOperand = rightOperandComputer(); + assertBool(rightOperand); + return rightOperand.convertToBool(); + } + + /** + * Return the result of invoking the '||' operator on this object with the + * [rightOperand]. + * + * Throws an [EvaluationException] if the operator is not appropriate for an + * object of this kind. + */ + BoolState lazyOr(InstanceState rightOperandComputer()) { + assertBool(this); + if (convertToBool() == BoolState.TRUE_STATE) { + return this; + } + InstanceState rightOperand = rightOperandComputer(); + assertBool(rightOperand); + return rightOperand.convertToBool(); + } + + /** * Return the result of invoking the '<' operator on this object with the * [rightOperand]. * @@ -1732,20 +1869,17 @@ } /** - * Return the result of invoking the '&&' operator on this object with the + * Return the result of invoking the '&' operator on this object with the * [rightOperand]. * * Throws an [EvaluationException] if the operator is not appropriate for an * object of this kind. */ - BoolState logicalAnd(InstanceState rightOperandComputer()) { + BoolState logicalAnd(InstanceState rightOperand) { assertBool(this); - if (convertToBool() == BoolState.FALSE_STATE) { - return this; - } - InstanceState rightOperand = rightOperandComputer(); assertBool(rightOperand); - return rightOperand.convertToBool(); + return BoolState.from( + convertToBool().value & rightOperand.convertToBool().value); } /** @@ -1760,20 +1894,31 @@ } /** - * Return the result of invoking the '||' operator on this object with the + * Return the result of invoking the '|' operator on this object with the * [rightOperand]. * * Throws an [EvaluationException] if the operator is not appropriate for an * object of this kind. */ - BoolState logicalOr(InstanceState rightOperandComputer()) { + BoolState logicalOr(InstanceState rightOperand) { assertBool(this); - if (convertToBool() == BoolState.TRUE_STATE) { - return this; - } - InstanceState rightOperand = rightOperandComputer(); assertBool(rightOperand); - return rightOperand.convertToBool(); + return BoolState.from( + convertToBool().value | rightOperand.convertToBool().value); + } + + /** + * Return the result of invoking the '^' operator on this object with the + * [rightOperand]. + * + * Throws an [EvaluationException] if the operator is not appropriate for an + * object of this kind. + */ + BoolState logicalXor(InstanceState rightOperand) { + assertBool(this); + assertBool(rightOperand); + return BoolState.from( + convertToBool().value ^ rightOperand.convertToBool().value); } /** @@ -1898,6 +2043,9 @@ bool get isBoolNumStringOrNull => true; @override + bool get isInt => true; + + @override bool get isUnknown => value == null; @override @@ -2521,6 +2669,9 @@ bool get isBoolNumStringOrNull => true; @override + bool get isNull => true; + + @override String get typeName => "Null"; @override @@ -2676,6 +2827,89 @@ } /** + * The state of an object representing a set. + */ +class SetState extends InstanceState { + /** + * The elements of the set. + */ + final Set<DartObjectImpl> _elements; + + /** + * Initialize a newly created state to represent a set with the given + * [elements]. + */ + SetState(this._elements); + + @override + int get hashCode { + int value = 0; + for (DartObjectImpl element in _elements) { + value = (value << 3) ^ element.hashCode; + } + return value; + } + + @override + String get typeName => "Set"; + + @override + bool operator ==(Object object) { + if (object is SetState) { + List<DartObjectImpl> elements = _elements.toList(); + List<DartObjectImpl> otherElements = object._elements.toList(); + int count = elements.length; + if (otherElements.length != count) { + return false; + } else if (count == 0) { + return true; + } + for (int i = 0; i < count; i++) { + if (elements[i] != otherElements[i]) { + return false; + } + } + return true; + } + return false; + } + + @override + StringState convertToString() => StringState.UNKNOWN_VALUE; + + @override + BoolState equalEqual(InstanceState rightOperand) { + assertBoolNumStringOrNull(rightOperand); + return isIdentical(rightOperand); + } + + @override + BoolState isIdentical(InstanceState rightOperand) { + if (rightOperand is DynamicState) { + return BoolState.UNKNOWN_VALUE; + } + return BoolState.from(this == rightOperand); + } + + @override + String toString() { + StringBuffer buffer = new StringBuffer(); + buffer.write('{'); + bool first = true; + _elements.forEach((DartObjectImpl element) { + if (first) { + first = false; + } else { + buffer.write(', '); + } + buffer.write(element); + }); + buffer.write('}'); + return buffer.toString(); + } +} + +/** * The state of an object representing a string. */ class StringState extends InstanceState {
diff --git a/pkg/analyzer/lib/src/dart/element/ast_provider.dart b/pkg/analyzer/lib/src/dart/element/ast_provider.dart deleted file mode 100644 index ba94d53..0000000 --- a/pkg/analyzer/lib/src/dart/element/ast_provider.dart +++ /dev/null
@@ -1,46 +0,0 @@ -// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file -// for details. All rights reserved. Use of this source code is governed by a -// BSD-style license that can be found in the LICENSE file. - -import 'dart:async'; - -import 'package:analyzer/dart/ast/ast.dart'; -import 'package:analyzer/dart/element/element.dart'; -import 'package:analyzer/src/dart/analysis/driver.dart'; - -/** - * Provider for resolved and unresolved [CompilationUnit]s that contain, or - * [AstNode]s that declare [Element]s. - */ -abstract class AstProvider { - /** - * Return the driver that is used to provide ASTs. - */ - AnalysisDriver get driver; - - /** - * Completes with the [SimpleIdentifier] that declares the [element]. The - * enclosing unit is only parsed, but not resolved. Completes with `null` if - * the [element] is synthetic, or the file where it is declared cannot be - * parsed, etc. - */ - Future<SimpleIdentifier> getParsedNameForElement(Element element); - - /** - * Completes with the parsed [CompilationUnit] that contains the [element]. - */ - Future<CompilationUnit> getParsedUnitForElement(Element element); - - /** - * Completes with the [SimpleIdentifier] that declares the [element]. The - * enclosing unit is fully resolved. Completes with `null` if the [element] - * is synthetic, or the file where it is declared cannot be parsed and - * resolved, etc. - */ - Future<SimpleIdentifier> getResolvedNameForElement(Element element); - - /** - * Completes with the resolved [CompilationUnit] that contains the [element]. - */ - Future<CompilationUnit> getResolvedUnitForElement(Element element); -}
diff --git a/pkg/analyzer/lib/src/dart/element/builder.dart b/pkg/analyzer/lib/src/dart/element/builder.dart index 2e518e3..cefb1d8 100644 --- a/pkg/analyzer/lib/src/dart/element/builder.dart +++ b/pkg/analyzer/lib/src/dart/element/builder.dart
@@ -48,7 +48,7 @@ : super(initialHolder, compilationUnitElement); @override - Object visitAnnotation(Annotation node) { + void visitAnnotation(Annotation node) { // Although it isn't valid to do so because closures are not constant // expressions, it's possible for one of the arguments to the constructor to // contain a closure. Wrapping the processing of the annotation this way @@ -62,16 +62,13 @@ } finally { _currentHolder = previousHolder; } - return null; } @override - Object visitBlockFunctionBody(BlockFunctionBody node) { - return null; - } + void visitBlockFunctionBody(BlockFunctionBody node) {} @override - Object visitClassDeclaration(ClassDeclaration node) { + void visitClassDeclaration(ClassDeclaration node) { _enclosingClassHasConstConstructor = false; for (var constructor in node.members) { if (constructor is ConstructorDeclaration && @@ -90,12 +87,10 @@ _fillClassElement(node, element, holder); _currentHolder.addType(element); - - return null; } @override - Object visitClassTypeAlias(ClassTypeAlias node) { + void visitClassTypeAlias(ClassTypeAlias node) { ElementHolder holder = new ElementHolder(); _visitChildren(holder, node); SimpleIdentifier className = node.name; @@ -109,19 +104,18 @@ _currentHolder.addType(element); className.staticElement = element; holder.validate(); - return null; } @override - Object visitCompilationUnit(CompilationUnit node) { + void visitCompilationUnit(CompilationUnit node) { if (_unitElement is ElementImpl) { _setCodeRange(_unitElement, node); } - return super.visitCompilationUnit(node); + super.visitCompilationUnit(node); } @override - Object visitConstructorDeclaration(ConstructorDeclaration node) { + void visitConstructorDeclaration(ConstructorDeclaration node) { ElementHolder holder = new ElementHolder(); _visitChildren(holder, node); FunctionBody body = node.body; @@ -163,11 +157,10 @@ element.nameEnd = constructorName.end; } holder.validate(); - return null; } @override - Object visitEnumDeclaration(EnumDeclaration node) { + void visitEnumDeclaration(EnumDeclaration node) { SimpleIdentifier enumName = node.name; EnumElementImpl enumElement = new EnumElementImpl.forNode(enumName); _setCodeRange(enumElement, node); @@ -199,24 +192,22 @@ _currentHolder.addEnum(enumElement); enumName.staticElement = enumElement; - return super.visitEnumDeclaration(node); + super.visitEnumDeclaration(node); } @override - Object visitExportDirective(ExportDirective node) { + void visitExportDirective(ExportDirective node) { List<ElementAnnotation> annotations = _createElementAnnotations(node.metadata); _unitElement.setAnnotations(node.offset, annotations); - return super.visitExportDirective(node); + super.visitExportDirective(node); } @override - Object visitExpressionFunctionBody(ExpressionFunctionBody node) { - return null; - } + void visitExpressionFunctionBody(ExpressionFunctionBody node) {} @override - Object visitFunctionDeclaration(FunctionDeclaration node) { + void visitFunctionDeclaration(FunctionDeclaration node) { FunctionExpression expression = node.functionExpression; if (expression != null) { ElementHolder holder = new ElementHolder(); @@ -254,7 +245,7 @@ SimpleIdentifier propertyNameNode = node.name; if (propertyNameNode == null) { // TODO(brianwilkerson) Report this internal error. - return null; + return; } String propertyName = propertyNameNode.name; TopLevelVariableElementImpl variable = _currentHolder @@ -327,15 +318,15 @@ } holder.validate(); } - return null; } @override - Object visitFunctionExpression(FunctionExpression node) { + void visitFunctionExpression(FunctionExpression node) { if (node.parent is FunctionDeclaration) { // visitFunctionDeclaration has already created the element for the // declaration. We just need to visit children. - return super.visitFunctionExpression(node); + super.visitFunctionExpression(node); + return; } ElementHolder holder = new ElementHolder(); _visitChildren(holder, node); @@ -359,11 +350,10 @@ _currentHolder.addFunction(element); node.element = element; holder.validate(); - return null; } @override - Object visitFunctionTypeAlias(FunctionTypeAlias node) { + void visitFunctionTypeAlias(FunctionTypeAlias node) { ElementHolder holder = new ElementHolder(); _visitChildren(holder, node); SimpleIdentifier aliasName = node.name; @@ -382,11 +372,10 @@ _currentHolder.addTypeAlias(element); aliasName.staticElement = element; holder.validate(); - return null; } @override - Object visitGenericTypeAlias(GenericTypeAlias node) { + void visitGenericTypeAlias(GenericTypeAlias node) { ElementHolder holder = new ElementHolder(); _visitChildren(holder, node); SimpleIdentifier aliasName = node.name; @@ -403,27 +392,26 @@ _currentHolder.addTypeAlias(element); aliasName.staticElement = element; holder.validate(); - return null; } @override - Object visitImportDirective(ImportDirective node) { + void visitImportDirective(ImportDirective node) { List<ElementAnnotation> annotations = _createElementAnnotations(node.metadata); _unitElement.setAnnotations(node.offset, annotations); - return super.visitImportDirective(node); + super.visitImportDirective(node); } @override - Object visitLibraryDirective(LibraryDirective node) { + void visitLibraryDirective(LibraryDirective node) { List<ElementAnnotation> annotations = _createElementAnnotations(node.metadata); _unitElement.setAnnotations(node.offset, annotations); - return super.visitLibraryDirective(node); + super.visitLibraryDirective(node); } @override - Object visitMethodDeclaration(MethodDeclaration node) { + void visitMethodDeclaration(MethodDeclaration node) { try { ElementHolder holder = new ElementHolder(); _visitChildren(holder, node); @@ -539,7 +527,7 @@ } catch (exception, stackTrace) { if (node.name.staticElement == null) { ClassDeclaration classNode = - node.getAncestor((node) => node is ClassDeclaration); + node.thisOrAncestorOfType<ClassDeclaration>(); StringBuffer buffer = new StringBuffer(); buffer.write("The element for the method "); buffer.write(node.name); @@ -557,7 +545,7 @@ } finally { if (node.name.staticElement == null) { ClassDeclaration classNode = - node.getAncestor((node) => node is ClassDeclaration); + node.thisOrAncestorOfType<ClassDeclaration>(); StringBuffer buffer = new StringBuffer(); buffer.write("The element for the method "); buffer.write(node.name); @@ -570,11 +558,10 @@ new AnalysisException(buffer.toString()), null)); } } - return null; } @override - Object visitMixinDeclaration(MixinDeclaration node) { + void visitMixinDeclaration(MixinDeclaration node) { ElementHolder holder = _buildClassMembers(node); SimpleIdentifier nameNode = node.name; @@ -583,20 +570,18 @@ _fillClassElement(node, element, holder); _currentHolder.addMixin(element); - - return null; } @override - Object visitPartDirective(PartDirective node) { + void visitPartDirective(PartDirective node) { List<ElementAnnotation> annotations = _createElementAnnotations(node.metadata); _unitElement.setAnnotations(node.offset, annotations); - return super.visitPartDirective(node); + super.visitPartDirective(node); } @override - Object visitVariableDeclaration(VariableDeclaration node) { + void visitVariableDeclaration(VariableDeclaration node) { bool isConst = node.isConst; bool isFinal = node.isFinal; Expression initializerNode = node.initializer; @@ -658,11 +643,10 @@ _currentHolder.addAccessor(setter); } } - return null; } @override - Object visitVariableDeclarationList(VariableDeclarationList node) { + void visitVariableDeclarationList(VariableDeclarationList node) { super.visitVariableDeclarationList(node); AstNode parent = node.parent; List<ElementAnnotation> elementAnnotations; @@ -676,7 +660,6 @@ } _setVariableDeclarationListAnnotations(node, elementAnnotations); _setVariableDeclarationListCodeRanges(node); - return null; } ElementHolder _buildClassMembers(AstNode classNode) { @@ -827,7 +810,7 @@ * Instances of the class `DirectiveElementBuilder` build elements for top * level library directives. */ -class DirectiveElementBuilder extends SimpleAstVisitor<Object> { +class DirectiveElementBuilder extends SimpleAstVisitor<void> { /** * The analysis context within which directive elements are being built. */ @@ -903,7 +886,7 @@ this.exportSourceKindMap); @override - Object visitCompilationUnit(CompilationUnit node) { + void visitCompilationUnit(CompilationUnit node) { // // Resolve directives. // @@ -926,11 +909,10 @@ // libraryElement.imports = imports; libraryElement.exports = exports; - return null; } @override - Object visitExportDirective(ExportDirective node) { + void visitExportDirective(ExportDirective node) { // Remove previous element. (It will remain null if the target is missing.) node.element = null; Source exportedSource = node.selectedSource; @@ -962,11 +944,10 @@ errors.add(new AnalysisError(libraryElement.source, offset, length, CompileTimeErrorCode.EXPORT_OF_NON_LIBRARY, [uriLiteral.toSource()])); } - return null; } @override - Object visitImportDirective(ImportDirective node) { + void visitImportDirective(ImportDirective node) { // Remove previous element. (It will remain null if the target is missing.) node.element = null; Source importedSource = node.selectedSource; @@ -1017,21 +998,18 @@ errors.add(new AnalysisError(libraryElement.source, offset, length, errorCode, [uriLiteral.toSource()])); } - return null; } @override - Object visitLibraryDirective(LibraryDirective node) { + void visitLibraryDirective(LibraryDirective node) { (node.element as LibraryElementImpl)?.metadata = _getElementAnnotations(node.metadata); - return null; } @override - Object visitPartDirective(PartDirective node) { + void visitPartDirective(PartDirective node) { (node.element as CompilationUnitElementImpl)?.metadata = _getElementAnnotations(node.metadata); - return null; } /** @@ -1080,30 +1058,27 @@ : super(initialHolder, compilationUnitElement); @override - Object visitBlockFunctionBody(BlockFunctionBody node) { + void visitBlockFunctionBody(BlockFunctionBody node) { _buildLocal(node); - return null; } @override - Object visitDefaultFormalParameter(DefaultFormalParameter node) { + void visitDefaultFormalParameter(DefaultFormalParameter node) { super.visitDefaultFormalParameter(node); buildParameterInitializer( node.declaredElement as ParameterElementImpl, node.defaultValue); - return null; } @override - Object visitExpressionFunctionBody(ExpressionFunctionBody node) { + void visitExpressionFunctionBody(ExpressionFunctionBody node) { _buildLocal(node); - return null; } @override - Object visitMixinDeclaration(MixinDeclaration node) { + void visitMixinDeclaration(MixinDeclaration node) { _mixinSuperInvokedNames = new Set<String>(); try { - return super.visitMixinDeclaration(node); + super.visitMixinDeclaration(node); } finally { MixinElementImpl element = node.declaredElement; element.superInvokedNames = _mixinSuperInvokedNames.toList(); @@ -1112,11 +1087,10 @@ } @override - Object visitVariableDeclaration(VariableDeclaration node) { + void visitVariableDeclaration(VariableDeclaration node) { super.visitVariableDeclaration(node); VariableElementImpl element = node.declaredElement as VariableElementImpl; buildVariableInitializer(element, node.initializer); - return null; } void _buildLocal(FunctionBody body) { @@ -1142,6 +1116,13 @@ : super(initialHolder, compilationUnitElement); /** + * Initialize a newly created element builder as a first step to analyzing a + * dangling dart expression. + */ + LocalElementBuilder.forDanglingExpression() + : super(new ElementHolder(), null); + + /** * Builds the variable elements associated with [node] and stores them in * the element holder. */ @@ -1186,13 +1167,13 @@ } @override - Object visitCatchClause(CatchClause node) { + void visitCatchClause(CatchClause node) { buildCatchVariableElements(node); - return super.visitCatchClause(node); + super.visitCatchClause(node); } @override - Object visitDeclaredIdentifier(DeclaredIdentifier node) { + void visitDeclaredIdentifier(DeclaredIdentifier node) { SimpleIdentifier variableName = node.identifier; LocalVariableElementImpl element = new LocalVariableElementImpl.forNode(variableName); @@ -1211,22 +1192,20 @@ } _currentHolder.addLocalVariable(element); variableName.staticElement = element; - return null; } @override - Object visitDefaultFormalParameter(DefaultFormalParameter node) { + void visitDefaultFormalParameter(DefaultFormalParameter node) { super.visitDefaultFormalParameter(node); buildParameterInitializer( node.declaredElement as ParameterElementImpl, node.defaultValue); - return null; } @override - Object visitFunctionDeclaration(FunctionDeclaration node) { + void visitFunctionDeclaration(FunctionDeclaration node) { FunctionExpression expression = node.functionExpression; if (expression == null) { - return null; + return; } ElementHolder holder = new ElementHolder(); @@ -1255,7 +1234,7 @@ } { - Block enclosingBlock = node.getAncestor((node) => node is Block); + Block enclosingBlock = node.thisOrAncestorOfType<Block>(); if (enclosingBlock != null) { element.setVisibleRange(enclosingBlock.offset, enclosingBlock.length); } @@ -1269,15 +1248,15 @@ expression.element = element; node.name.staticElement = element; holder.validate(); - return null; } @override - Object visitFunctionExpression(FunctionExpression node) { + void visitFunctionExpression(FunctionExpression node) { if (node.parent is FunctionDeclaration) { // visitFunctionDeclaration has already created the element for the // declaration. We just need to visit children. - return super.visitFunctionExpression(node); + super.visitFunctionExpression(node); + return; } ElementHolder holder = new ElementHolder(); @@ -1298,43 +1277,38 @@ if (body.isGenerator) { element.generator = true; } - - { - Block enclosingBlock = node.getAncestor((node) => node is Block); - if (enclosingBlock != null) { - element.setVisibleRange(enclosingBlock.offset, enclosingBlock.length); - } + Block enclosingBlock = node.thisOrAncestorOfType<Block>(); + if (enclosingBlock != null) { + element.setVisibleRange(enclosingBlock.offset, enclosingBlock.length); } - element.type = new FunctionTypeImpl(element); element.hasImplicitReturnType = true; _currentHolder.addFunction(element); node.element = element; holder.validate(); - return null; } @override - Object visitLabeledStatement(LabeledStatement node) { + void visitLabeledStatement(LabeledStatement node) { bool onSwitchStatement = node.statement is SwitchStatement; buildLabelElements(node.labels, onSwitchStatement, false); - return super.visitLabeledStatement(node); + super.visitLabeledStatement(node); } @override - Object visitSwitchCase(SwitchCase node) { + void visitSwitchCase(SwitchCase node) { buildLabelElements(node.labels, false, true); - return super.visitSwitchCase(node); + super.visitSwitchCase(node); } @override - Object visitSwitchDefault(SwitchDefault node) { + void visitSwitchDefault(SwitchDefault node) { buildLabelElements(node.labels, false, true); - return super.visitSwitchDefault(node); + super.visitSwitchDefault(node); } @override - Object visitVariableDeclaration(VariableDeclaration node) { + void visitVariableDeclaration(VariableDeclaration node) { bool isConst = node.isConst; bool isFinal = node.isFinal; Expression initializerNode = node.initializer; @@ -1354,17 +1328,15 @@ element.isConst = isConst; element.isFinal = isFinal; buildVariableInitializer(element, initializerNode); - return null; } @override - Object visitVariableDeclarationList(VariableDeclarationList node) { + void visitVariableDeclarationList(VariableDeclarationList node) { super.visitVariableDeclarationList(node); List<ElementAnnotation> elementAnnotations = _createElementAnnotations(node.metadata); _setVariableDeclarationListAnnotations(node, elementAnnotations); _setVariableDeclarationListCodeRanges(node); - return null; } void _setVariableVisibleRange( @@ -1374,7 +1346,7 @@ if (parent2 is ForStatement) { scopeNode = parent2; } else { - scopeNode = node.getAncestor((node) => node is Block); + scopeNode = node.thisOrAncestorOfType<Block>(); } element.setVisibleRange(scopeNode.offset, scopeNode.length); } @@ -1383,7 +1355,7 @@ /** * Base class for API and local element builders. */ -abstract class _BaseElementBuilder extends RecursiveAstVisitor<Object> { +abstract class _BaseElementBuilder extends RecursiveAstVisitor<void> { /** * The compilation unit element into which the elements being built will be * stored. @@ -1444,7 +1416,7 @@ } @override - Object visitDefaultFormalParameter(DefaultFormalParameter node) { + void visitDefaultFormalParameter(DefaultFormalParameter node) { NormalFormalParameter normalParameter = node.parameter; SimpleIdentifier parameterName = normalParameter.identifier; ParameterElementImpl parameter; @@ -1474,11 +1446,10 @@ } parameterName?.staticElement = parameter; normalParameter.accept(this); - return null; } @override - Object visitFieldFormalParameter(FieldFormalParameter node) { + void visitFieldFormalParameter(FieldFormalParameter node) { if (node.parent is! DefaultFormalParameter) { SimpleIdentifier parameterName = node.identifier; FieldFormalParameterElementImpl parameter = @@ -1505,11 +1476,10 @@ _createGenericFunctionType(element, holder); } holder.validate(); - return null; } @override - Object visitFunctionTypedFormalParameter(FunctionTypedFormalParameter node) { + void visitFunctionTypedFormalParameter(FunctionTypedFormalParameter node) { if (node.parent is! DefaultFormalParameter) { SimpleIdentifier parameterName = node.identifier; ParameterElementImpl parameter = @@ -1534,11 +1504,10 @@ element.metadata = _createElementAnnotations(node.metadata); _createGenericFunctionType(element, holder); holder.validate(); - return null; } @override - Object visitGenericFunctionType(GenericFunctionType node) { + void visitGenericFunctionType(GenericFunctionType node) { ElementHolder holder = new ElementHolder(); _visitChildren(holder, node); GenericFunctionTypeElementImpl element = @@ -1550,11 +1519,10 @@ element.type = type; (node as GenericFunctionTypeImpl).type = type; holder.validate(); - return null; } @override - Object visitSimpleFormalParameter(SimpleFormalParameter node) { + void visitSimpleFormalParameter(SimpleFormalParameter node) { ParameterElementImpl parameter; if (node.parent is! DefaultFormalParameter) { SimpleIdentifier parameterName = node.identifier; @@ -1576,11 +1544,10 @@ super.visitSimpleFormalParameter(node); parameter ??= node.declaredElement; parameter?.metadata = _createElementAnnotations(node.metadata); - return null; } @override - Object visitTypeParameter(TypeParameter node) { + void visitTypeParameter(TypeParameter node) { SimpleIdentifier parameterName = node.name; TypeParameterElementImpl typeParameter = new TypeParameterElementImpl.forNode(parameterName); @@ -1591,7 +1558,7 @@ typeParameter.type = typeParameterType; _currentHolder.addTypeParameter(typeParameter); parameterName.staticElement = typeParameter; - return super.visitTypeParameter(node); + super.visitTypeParameter(node); } /** @@ -1720,54 +1687,50 @@ /** * Builds elements for all node that are not constructors or methods. */ -class _ClassNotExecutableElementsBuilder extends UnifyingAstVisitor<Object> { +class _ClassNotExecutableElementsBuilder extends UnifyingAstVisitor<void> { final ApiElementBuilder builder; final List<ClassMember> nonFields; _ClassNotExecutableElementsBuilder(this.builder, this.nonFields); @override - Object visitConstructorDeclaration(ConstructorDeclaration node) { + void visitConstructorDeclaration(ConstructorDeclaration node) { nonFields.add(node); - return null; } @override - Object visitMethodDeclaration(MethodDeclaration node) { + void visitMethodDeclaration(MethodDeclaration node) { nonFields.add(node); - return null; } @override - Object visitNode(AstNode node) => node.accept(builder); + void visitNode(AstNode node) => node.accept(builder); } /** * Instances of the class [_NamespaceCombinatorBuilder] can be used to visit * [Combinator] AST nodes and generate [NamespaceCombinator] elements. */ -class _NamespaceCombinatorBuilder extends SimpleAstVisitor<Object> { +class _NamespaceCombinatorBuilder extends SimpleAstVisitor<void> { /** * Elements generated so far. */ final List<NamespaceCombinator> combinators = <NamespaceCombinator>[]; @override - Object visitHideCombinator(HideCombinator node) { + void visitHideCombinator(HideCombinator node) { HideElementCombinatorImpl hide = new HideElementCombinatorImpl(); hide.hiddenNames = _getIdentifiers(node.hiddenNames); combinators.add(hide); - return null; } @override - Object visitShowCombinator(ShowCombinator node) { + void visitShowCombinator(ShowCombinator node) { ShowElementCombinatorImpl show = new ShowElementCombinatorImpl(); show.offset = node.offset; show.end = node.end; show.shownNames = _getIdentifiers(node.shownNames); combinators.add(show); - return null; } /**
diff --git a/pkg/analyzer/lib/src/dart/element/element.dart b/pkg/analyzer/lib/src/dart/element/element.dart index 513799f..27fc635 100644 --- a/pkg/analyzer/lib/src/dart/element/element.dart +++ b/pkg/analyzer/lib/src/dart/element/element.dart
@@ -1,15 +1,17 @@ -// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file +// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. import 'dart:collection'; import 'dart:math' show min; +import 'package:analyzer/dart/analysis/session.dart'; import 'package:analyzer/dart/ast/ast.dart'; import 'package:analyzer/dart/ast/token.dart'; import 'package:analyzer/dart/constant/value.dart'; import 'package:analyzer/dart/element/element.dart'; import 'package:analyzer/dart/element/type.dart'; +import 'package:analyzer/error/error.dart'; import 'package:analyzer/src/dart/ast/utilities.dart'; import 'package:analyzer/src/dart/constant/compute.dart'; import 'package:analyzer/src/dart/constant/value.dart'; @@ -106,6 +108,7 @@ @override T accept<T>(ElementVisitor<T> visitor) => visitor.visitClassElement(this); + @deprecated @override NamedCompilationUnitMember computeNode() { if (isEnum) { @@ -507,22 +510,49 @@ @override List<ConstructorElement> get constructors { + if (_constructors != null) { + return _constructors; + } + if (isMixinApplication) { - return _computeMixinAppConstructors(); + return _constructors = _computeMixinAppConstructors(); } - if (_unlinkedClass != null && _constructors == null) { - _constructors = _unlinkedClass.executables - .where((e) => e.kind == UnlinkedExecutableKind.constructor) - .map((e) => new ConstructorElementImpl.forSerialized(e, this)) - .toList(growable: false); - // Ensure at least implicit default constructor. - if (_constructors.isEmpty) { - ConstructorElementImpl constructor = new ConstructorElementImpl('', -1); - constructor.isSynthetic = true; - constructor.enclosingElement = this; - _constructors = <ConstructorElement>[constructor]; + + if (_unlinkedClass != null) { + var unlinkedExecutables = _unlinkedClass.executables; + + var length = unlinkedExecutables.length; + if (length != 0) { + var count = 0; + for (var i = 0; i < length; i++) { + var e = unlinkedExecutables[i]; + if (e.kind == UnlinkedExecutableKind.constructor) { + count++; + } + } + + if (count != 0) { + var constructors = new List<ConstructorElement>(count); + var index = 0; + for (var i = 0; i < length; i++) { + var e = unlinkedExecutables[i]; + if (e.kind == UnlinkedExecutableKind.constructor) { + constructors[index++] = + new ConstructorElementImpl.forSerialized(e, this); + } + } + return _constructors = constructors; + } } + + // There are no explicit constructors. + // Create the implicit default constructor. + var constructor = new ConstructorElementImpl('', -1); + constructor.isSynthetic = true; + constructor.enclosingElement = this; + _constructors = <ConstructorElement>[constructor]; } + assert(_constructors != null); return _constructors ?? const <ConstructorElement>[]; } @@ -646,17 +676,39 @@ @override List<InterfaceType> get interfaces { - if (_interfaces == null) { - if (_unlinkedClass != null) { - ResynthesizerContext context = enclosingUnit.resynthesizerContext; - _interfaces = _unlinkedClass.interfaces - .map((EntityRef t) => context.resolveTypeRef(this, t)) - .where(_isInterfaceTypeInterface) - .cast<InterfaceType>() - .toList(growable: false); - } + if (_interfaces != null) { + return _interfaces; } - return _interfaces ?? const <InterfaceType>[]; + + if (_unlinkedClass != null) { + var unlinkedInterfaces = _unlinkedClass.interfaces; + var length = unlinkedInterfaces.length; + if (length == 0) { + return _interfaces = const <InterfaceType>[]; + } + + ResynthesizerContext context = enclosingUnit.resynthesizerContext; + var interfaces = new List<InterfaceType>(length); + var index = 0; + var hasNonInterfaceType = false; + for (var i = 0; i < length; i++) { + var t = unlinkedInterfaces[i]; + var type = context.resolveTypeRef(this, t); + if (_isInterfaceTypeInterface(type)) { + interfaces[index++] = type; + } else { + hasNonInterfaceType = true; + } + } + + if (hasNonInterfaceType) { + interfaces = interfaces.sublist(0, index); + } + + return _interfaces = interfaces; + } + + return _interfaces = const <InterfaceType>[]; } void set interfaces(List<InterfaceType> interfaces) { @@ -721,13 +773,40 @@ @override List<MethodElement> get methods { - if (_unlinkedClass != null) { - _methods ??= _unlinkedClass.executables - .where((e) => e.kind == UnlinkedExecutableKind.functionOrMethod) - .map((e) => new MethodElementImpl.forSerialized(e, this)) - .toList(growable: false); + if (_methods != null) { + return _methods; } - return _methods ?? const <MethodElement>[]; + + if (_unlinkedClass != null) { + var unlinkedExecutables = _unlinkedClass.executables; + + var length = unlinkedExecutables.length; + if (length == 0) { + return _methods = const <MethodElement>[]; + } + + var count = 0; + for (var i = 0; i < length; i++) { + var e = unlinkedExecutables[i]; + if (e.kind == UnlinkedExecutableKind.functionOrMethod) { + count++; + } + } + if (count == 0) { + return _methods = const <MethodElement>[]; + } + + var methods = new List<MethodElement>(count); + var index = 0; + for (var i = 0; i < length; i++) { + var e = unlinkedExecutables[i]; + if (e.kind == UnlinkedExecutableKind.functionOrMethod) { + methods[index++] = new MethodElementImpl.forSerialized(e, this); + } + } + return _methods = methods; + } + return _methods = const <MethodElement>[]; } /// Set the methods contained in this class to the given [methods]. @@ -747,17 +826,39 @@ @override List<InterfaceType> get mixins { - if (_mixins == null) { - if (_unlinkedClass != null) { - ResynthesizerContext context = enclosingUnit.resynthesizerContext; - _mixins = _unlinkedClass.mixins - .map((EntityRef t) => context.resolveTypeRef(this, t)) - .where(_isInterfaceTypeInterface) - .cast<InterfaceType>() - .toList(growable: false); - } + if (_mixins != null) { + return _mixins; } - return _mixins ?? const <InterfaceType>[]; + + if (_unlinkedClass != null) { + var unlinkedMixins = _unlinkedClass.mixins; + var length = unlinkedMixins.length; + if (length == 0) { + return _mixins = const <InterfaceType>[]; + } + + ResynthesizerContext context = enclosingUnit.resynthesizerContext; + var mixins = new List<InterfaceType>(length); + var index = 0; + var hasNonInterfaceType = false; + for (var i = 0; i < length; i++) { + var t = unlinkedMixins[i]; + var type = context.resolveTypeRef(this, t); + if (_isInterfaceTypeInterface(type)) { + mixins[index++] = type; + } else { + hasNonInterfaceType = true; + } + } + + if (hasNonInterfaceType) { + mixins = mixins.sublist(0, index); + } + + return _mixins = mixins; + } + + return _mixins = const <InterfaceType>[]; } void set mixins(List<InterfaceType> mixins) { @@ -1067,60 +1168,105 @@ void _resynthesizeFieldsAndPropertyAccessors() { assert(_fields == null); assert(_accessors == null); - var explicitFields = <FieldElement>[]; - var implicitAccessors = <PropertyAccessorElement>[]; - var explicitAccessors = <PropertyAccessorElement>[]; - var implicitFields = <String, FieldElementImpl>{}; + + var unlinkedFields = _unlinkedClass.fields; + var unlinkedExecutables = _unlinkedClass.executables; // Build explicit fields and implicit property accessors. - for (UnlinkedVariable v in _unlinkedClass.fields) { - FieldElementImpl field = - new FieldElementImpl.forSerializedFactory(v, this); - explicitFields.add(field); - implicitAccessors.add( - new PropertyAccessorElementImpl_ImplicitGetter(field) - ..enclosingElement = this); - if (!field.isConst && !field.isFinal) { + List<FieldElement> explicitFields; + List<PropertyAccessorElement> implicitAccessors; + var unlinkedFieldsLength = unlinkedFields.length; + if (unlinkedFieldsLength != 0) { + explicitFields = new List<FieldElement>(unlinkedFieldsLength); + implicitAccessors = <PropertyAccessorElement>[]; + for (var i = 0; i < unlinkedFieldsLength; i++) { + var v = unlinkedFields[i]; + FieldElementImpl field = + new FieldElementImpl.forSerializedFactory(v, this); + explicitFields[i] = field; implicitAccessors.add( - new PropertyAccessorElementImpl_ImplicitSetter(field) + new PropertyAccessorElementImpl_ImplicitGetter(field) ..enclosingElement = this); + if (!field.isConst && !field.isFinal) { + implicitAccessors.add( + new PropertyAccessorElementImpl_ImplicitSetter(field) + ..enclosingElement = this); + } } + } else { + explicitFields = const <FieldElement>[]; + implicitAccessors = const <PropertyAccessorElement>[]; } - // Build explicit property accessors and implicit fields. - for (UnlinkedExecutable e in _unlinkedClass.executables) { + + var unlinkedExecutablesLength = unlinkedExecutables.length; + var getterSetterCount = 0; + for (var i = 0; i < unlinkedExecutablesLength; i++) { + var e = unlinkedExecutables[i]; if (e.kind == UnlinkedExecutableKind.getter || e.kind == UnlinkedExecutableKind.setter) { - PropertyAccessorElementImpl accessor = - new PropertyAccessorElementImpl.forSerialized(e, this); - explicitAccessors.add(accessor); - // Create or update the implicit field. - String fieldName = accessor.displayName; - FieldElementImpl field = implicitFields[fieldName]; - if (field == null) { - field = new FieldElementImpl(fieldName, -1); - implicitFields[fieldName] = field; - field.enclosingElement = this; - field.isSynthetic = true; - field.isFinal = e.kind == UnlinkedExecutableKind.getter; - field.isStatic = e.isStatic; - } else { - field.isFinal = false; - } - accessor.variable = field; - if (e.kind == UnlinkedExecutableKind.getter) { - field.getter = accessor; - } else { - field.setter = accessor; - } + getterSetterCount++; } } + + // Build explicit property accessors and implicit fields. + List<PropertyAccessorElement> explicitAccessors; + Map<String, FieldElementImpl> implicitFields; + if (getterSetterCount != 0) { + explicitAccessors = new List<PropertyAccessorElement>(getterSetterCount); + implicitFields = <String, FieldElementImpl>{}; + var index = 0; + for (var i = 0; i < unlinkedExecutablesLength; i++) { + var e = unlinkedExecutables[i]; + if (e.kind == UnlinkedExecutableKind.getter || + e.kind == UnlinkedExecutableKind.setter) { + PropertyAccessorElementImpl accessor = + new PropertyAccessorElementImpl.forSerialized(e, this); + explicitAccessors[index++] = accessor; + // Create or update the implicit field. + String fieldName = accessor.displayName; + FieldElementImpl field = implicitFields[fieldName]; + if (field == null) { + field = new FieldElementImpl(fieldName, -1); + implicitFields[fieldName] = field; + field.enclosingElement = this; + field.isSynthetic = true; + field.isFinal = e.kind == UnlinkedExecutableKind.getter; + field.isStatic = e.isStatic; + } else { + field.isFinal = false; + } + accessor.variable = field; + if (e.kind == UnlinkedExecutableKind.getter) { + field.getter = accessor; + } else { + field.setter = accessor; + } + } + } + } else { + explicitAccessors = const <PropertyAccessorElement>[]; + implicitFields = const <String, FieldElementImpl>{}; + } + // Combine explicit and implicit fields and property accessors. - _fields = <FieldElement>[] - ..addAll(explicitFields) - ..addAll(implicitFields.values); - _accessors = <PropertyAccessorElement>[] - ..addAll(explicitAccessors) - ..addAll(implicitAccessors); + if (implicitFields.isEmpty) { + _fields = explicitFields; + } else if (explicitFields.isEmpty) { + _fields = implicitFields.values.toList(growable: false); + } else { + _fields = <FieldElement>[] + ..addAll(explicitFields) + ..addAll(implicitFields.values); + } + if (explicitAccessors.isEmpty) { + _accessors = implicitAccessors; + } else if (implicitAccessors.isEmpty) { + _accessors = explicitAccessors; + } else { + _accessors = <PropertyAccessorElement>[] + ..addAll(explicitAccessors) + ..addAll(implicitAccessors); + } } bool _safeIsOrInheritsProxy( @@ -1524,6 +1670,7 @@ } } + @deprecated @override CompilationUnit computeNode() => unit; @@ -2049,6 +2196,7 @@ super.appendTo(buffer); } + @deprecated @override ConstructorDeclaration computeNode() => getNodeMatching((node) => node is ConstructorDeclaration); @@ -2141,8 +2289,7 @@ /// This interface is only used for constant variables that have initializers. /// /// This class is not intended to be part of the public API for analyzer. -abstract class ConstVariableElement - implements ElementImpl, ConstantEvaluationTarget { +mixin ConstVariableElement implements ElementImpl, ConstantEvaluationTarget { /// If this element represents a constant variable, and it has an initializer, /// a copy of the initializer for the constant. Otherwise `null`. /// @@ -2233,6 +2380,7 @@ UnlinkedParam unlinkedParam, ElementImpl enclosingElement) : super.forSerialized(unlinkedParam, enclosingElement); + @deprecated @override DefaultFormalParameter computeNode() => getNodeMatching((node) => node is DefaultFormalParameter); @@ -2363,6 +2511,10 @@ ElementAnnotationImpl(this.compilationUnit); @override + List<AnalysisError> get constantEvaluationErrors => + evaluationResult?.errors ?? const <AnalysisError>[]; + + @override DartObject get constantValue => evaluationResult?.value; @override @@ -2852,6 +3004,11 @@ } @override + AnalysisSession get session { + return _enclosingElement?.session; + } + + @override Source get source { if (_enclosingElement == null) { return null; @@ -2866,6 +3023,7 @@ return _enclosingElement?.typeParameterContext; } + @deprecated @override CompilationUnit get unit => context.resolveCompilationUnit(source, library); @@ -2912,6 +3070,7 @@ @override String computeDocumentationComment() => documentationComment; + @deprecated @override AstNode computeNode() => getNodeMatching((node) => node is AstNode); @@ -2949,6 +3108,7 @@ } /// Return the resolved [AstNode] of the given type enclosing [getNameOffset]. + @deprecated AstNode getNodeMatching(Predicate<AstNode> predicate) { CompilationUnit unit = this.unit; if (unit == null) { @@ -2959,7 +3119,7 @@ if (node == null) { return null; } - return node.getAncestor(predicate); + return node.thisOrAncestorMatching(predicate); } /// Return `true` if this element has the given [modifier] associated with it. @@ -3768,7 +3928,7 @@ /// order in which they were specified. List<NamespaceCombinator> _combinators; - /// The URI that was selected based on the [context] declared variables. + /// The URI that was selected based on the declared variables. String _selectedUri; /// Initialize a newly created export element at the given [offset]. @@ -3975,6 +4135,7 @@ @override T accept<T>(ElementVisitor<T> visitor) => visitor.visitFieldElement(this); + @deprecated @override AstNode computeNode() { if (isEnumConstant) { @@ -4147,6 +4308,7 @@ super.appendTo(buffer); } + @deprecated @override FunctionDeclaration computeNode() => getNodeMatching((node) => node is FunctionDeclaration); @@ -4619,6 +4781,7 @@ } } + @deprecated @override GenericTypeAlias computeNode() => getNodeMatching((node) => node is GenericTypeAlias); @@ -4746,7 +4909,7 @@ ///` if there was no prefix specified. PrefixElement _prefix; - /// The URI that was selected based on the [context] declared variables. + /// The URI that was selected based on the declared variables. String _selectedUri; /// The cached value of [namespace]. @@ -5030,6 +5193,9 @@ /// The analysis context in which this library is defined. final AnalysisContext context; + @override + final AnalysisSession session; + final LibraryResynthesizerContext resynthesizerContext; final UnlinkedUnit unlinkedDefiningUnit; @@ -5084,22 +5250,29 @@ /// Initialize a newly created library element in the given [context] to have /// the given [name] and [offset]. - LibraryElementImpl(this.context, String name, int offset, this.nameLength) + LibraryElementImpl( + this.context, this.session, String name, int offset, this.nameLength) : resynthesizerContext = null, unlinkedDefiningUnit = null, super(name, offset); /// Initialize a newly created library element in the given [context] to have /// the given [name]. - LibraryElementImpl.forNode(this.context, LibraryIdentifier name) + LibraryElementImpl.forNode(this.context, this.session, LibraryIdentifier name) : nameLength = name != null ? name.length : 0, resynthesizerContext = null, unlinkedDefiningUnit = null, super.forNode(name); /// Initialize using the given serialized information. - LibraryElementImpl.forSerialized(this.context, String name, int offset, - this.nameLength, this.resynthesizerContext, this.unlinkedDefiningUnit) + LibraryElementImpl.forSerialized( + this.context, + this.session, + String name, + int offset, + this.nameLength, + this.resynthesizerContext, + this.unlinkedDefiningUnit) : super.forSerialized(null) { _name = name; _nameOffset = offset; @@ -5491,6 +5664,19 @@ } @override + Iterable<Element> get topLevelElements sync* { + for (var unit in units) { + yield* unit.accessors; + yield* unit.enums; + yield* unit.functionTypeAliases; + yield* unit.functions; + yield* unit.mixins; + yield* unit.topLevelVariables; + yield* unit.types; + } + } + + @override List<CompilationUnitElement> get units { List<CompilationUnitElement> units = new List<CompilationUnitElement>(); units.add(_definingCompilationUnit); @@ -5793,6 +5979,7 @@ buffer.write(displayName); } + @deprecated @override Declaration computeNode() => getNodeMatching( (node) => node is DeclaredIdentifier || node is VariableDeclaration); @@ -5889,6 +6076,7 @@ super.appendTo(buffer); } + @deprecated @override MethodDeclaration computeNode() => getNodeMatching((node) => node is MethodDeclaration); @@ -6166,6 +6354,9 @@ @override final AnalysisContext context; + @override + final AnalysisSession session; + /// The name of the conflicting elements. @override final String name; @@ -6175,7 +6366,8 @@ /// Initialize a newly created element in the given [context] to represent /// the given non-empty [conflictingElements]. - MultiplyDefinedElementImpl(this.context, this.name, this.conflictingElements); + MultiplyDefinedElementImpl( + this.context, this.session, this.name, this.conflictingElements); @override String get displayName => name; @@ -6300,6 +6492,7 @@ @override String computeDocumentationComment() => null; + @deprecated @override AstNode computeNode() => null; @@ -6924,6 +7117,7 @@ buffer.write(right); } + @deprecated @override FormalParameter computeNode() => getNodeMatching((node) => node is FormalParameter); @@ -7047,7 +7241,7 @@ /// A mixin that provides a common implementation for methods defined in /// [ParameterElement]. -abstract class ParameterElementMixin implements ParameterElement { +mixin ParameterElementMixin implements ParameterElement { @override bool get isNamed => parameterKind == ParameterKind.NAMED; @@ -7301,6 +7495,7 @@ super.appendTo(buffer); } + @deprecated @override AstNode computeNode() { if (isSynthetic) { @@ -7569,7 +7764,7 @@ /// Mixin providing the implementation of /// [TypeParameterizedElement.isSimplyBounded] for elements that define a type. -abstract class SimplyBoundableMixin implements TypeParameterizedElement { +mixin SimplyBoundableMixin implements TypeParameterizedElement { CompilationUnitElementImpl get enclosingUnit; @override @@ -7618,6 +7813,7 @@ T accept<T>(ElementVisitor<T> visitor) => visitor.visitTopLevelVariableElement(this); + @deprecated @override VariableDeclaration computeNode() => getNodeMatching((node) => node is VariableDeclaration); @@ -7754,7 +7950,7 @@ } /// Mixin representing an element which can have type parameters. -abstract class TypeParameterizedElementMixin +mixin TypeParameterizedElementMixin implements TypeParameterizedElement, ElementImpl,
diff --git a/pkg/analyzer/lib/src/dart/element/handle.dart b/pkg/analyzer/lib/src/dart/element/handle.dart index 728ff86..97f978f 100644 --- a/pkg/analyzer/lib/src/dart/element/handle.dart +++ b/pkg/analyzer/lib/src/dart/element/handle.dart
@@ -2,6 +2,7 @@ // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. +import 'package:analyzer/dart/analysis/session.dart'; import 'package:analyzer/dart/ast/ast.dart'; import 'package:analyzer/dart/constant/value.dart'; import 'package:analyzer/dart/element/element.dart'; @@ -117,6 +118,7 @@ @override ConstructorElement get unnamedConstructor => actualElement.unnamedConstructor; + @deprecated @override NamedCompilationUnitMember computeNode() => super.computeNode(); @@ -246,6 +248,7 @@ @override int get uriOffset => actualElement.uriOffset; + @deprecated @override CompilationUnit computeNode() => actualElement.computeNode(); @@ -302,6 +305,7 @@ ConstructorElement get redirectedConstructor => actualElement.redirectedConstructor; + @deprecated @override ConstructorDeclaration computeNode() => actualElement.computeNode(); } @@ -458,8 +462,12 @@ int get nameOffset => actualElement.nameOffset; @override + AnalysisSession get session => _resynthesizer.session; + + @override Source get source => actualElement.source; + @deprecated @override CompilationUnit get unit => actualElement.unit; @@ -473,6 +481,7 @@ @override String computeDocumentationComment() => documentationComment; + @deprecated @override AstNode computeNode() => actualElement.computeNode(); @@ -509,10 +518,17 @@ final AnalysisContext context; /** + * The session that owns the element to be resynthesized. + * + * Note that this will be `null` if the task model is being used. + */ + final AnalysisSession session; + + /** * Initialize a newly created resynthesizer to resynthesize elements in the * given [context]. */ - ElementResynthesizer(this.context); + ElementResynthesizer(this.context, this.session); /** * Return the element referenced by the given [location]. @@ -646,6 +662,7 @@ @override ElementKind get kind => ElementKind.FIELD; + @deprecated @override VariableDeclaration computeNode() => actualElement.computeNode(); } @@ -676,6 +693,7 @@ @override SourceRange get visibleRange => actualElement.visibleRange; + @deprecated @override FunctionDeclaration computeNode() => actualElement.computeNode(); } @@ -723,6 +741,7 @@ @override List<TypeParameterElement> get typeParameters => actualElement.typeParameters; + @deprecated @override FunctionTypeAlias computeNode() => actualElement.computeNode(); @@ -769,6 +788,7 @@ @override List<TypeParameterElement> get typeParameters => actualElement.typeParameters; + @deprecated @override FunctionTypeAlias computeNode() => actualElement.computeNode(); @@ -923,6 +943,9 @@ Namespace get publicNamespace => actualElement.publicNamespace; @override + Iterable<Element> get topLevelElements => actualElement.topLevelElements; + + @override List<CompilationUnitElement> get units => actualElement.units; @override @@ -957,6 +980,7 @@ @override SourceRange get visibleRange => actualElement.visibleRange; + @deprecated @override VariableDeclaration computeNode() => actualElement.computeNode(); } @@ -987,6 +1011,7 @@ @override ElementKind get kind => ElementKind.METHOD; + @deprecated @override MethodDeclaration computeNode() => actualElement.computeNode(); @@ -1039,6 +1064,7 @@ @override SourceRange get visibleRange => actualElement.visibleRange; + @deprecated @override FormalParameter computeNode() => super.computeNode(); } @@ -1164,6 +1190,7 @@ @override ElementKind get kind => ElementKind.TOP_LEVEL_VARIABLE; + @deprecated @override VariableDeclaration computeNode() => super.computeNode(); }
diff --git a/pkg/analyzer/lib/src/dart/element/inheritance_manager2.dart b/pkg/analyzer/lib/src/dart/element/inheritance_manager2.dart index 8d18330..d523d07 100644 --- a/pkg/analyzer/lib/src/dart/element/inheritance_manager2.dart +++ b/pkg/analyzer/lib/src/dart/element/inheritance_manager2.dart
@@ -71,13 +71,13 @@ return Interface._empty; } - Map<Name, FunctionType> map = {}; Map<Name, List<FunctionType>> namedCandidates = {}; List<Map<Name, FunctionType>> superImplemented = []; + Map<Name, FunctionType> declared; try { // If a class declaration has a member declaration, the signature of that // member declaration becomes the signature in the interface. - _addTypeMembers(map, type); + declared = _getTypeMembers(type); for (var interface in type.interfaces) { _addCandidates(namedCandidates, interface); @@ -123,6 +123,7 @@ // super-interfaces that is a valid override of all the other // super-interface signatures with the same name. That "most specific" // signature becomes the signature of the class's interface. + Map<Name, FunctionType> map = new Map.of(declared); List<Conflict> conflicts = _findMostSpecificFromNamedCandidates( map, namedCandidates, @@ -130,6 +131,7 @@ var interface = new Interface._( map, + declared, namedCandidates, superImplemented, conflicts ?? const [], @@ -197,20 +199,6 @@ } } - void _addTypeMembers(Map<Name, FunctionType> map, InterfaceType type) { - var libraryUri = type.element.librarySource.uri; - - void addTypeMember(ExecutableElement member) { - if (!member.isStatic) { - var name = new Name(libraryUri, member.name); - map[name] = member.type; - } - } - - type.methods.forEach(addTypeMember); - type.accessors.forEach(addTypeMember); - } - /// Check that all [candidates] for the given [name] have the same kind, all /// getters, all methods, or all setter. If a conflict found, return the /// new [Conflict] instance that describes it. @@ -389,6 +377,31 @@ _mixinMembers[type] = implemented; return implemented; } + + Map<Name, FunctionType> _getTypeMembers(InterfaceType type) { + var declared = <Name, FunctionType>{}; + var libraryUri = type.element.librarySource.uri; + + var methods = type.methods; + for (var i = 0; i < methods.length; i++) { + var method = methods[i]; + if (!method.isStatic) { + var name = new Name(libraryUri, method.name); + declared[name] = method.type; + } + } + + var accessors = type.accessors; + for (var i = 0; i < accessors.length; i++) { + var accessor = accessors[i]; + if (!accessor.isStatic) { + var name = new Name(libraryUri, accessor.name); + declared[name] = accessor.type; + } + } + + return declared; + } } /// The instance interface of an [InterfaceType]. @@ -396,6 +409,7 @@ static const _empty = const Interface._( const {}, const {}, + const {}, const [{}], const [], ); @@ -403,6 +417,9 @@ /// The map of names to their signature in the interface. final Map<Name, FunctionType> map; + /// The map of declared names to their signatures. + final Map<Name, FunctionType> declared; + /// The map of names to their signatures from the mixins, superclasses, /// or interfaces. final Map<Name, List<FunctionType>> _overridden; @@ -420,6 +437,7 @@ const Interface._( this.map, + this.declared, this._overridden, this._superImplemented, this.conflicts,
diff --git a/pkg/analyzer/lib/src/dart/element/member.dart b/pkg/analyzer/lib/src/dart/element/member.dart index c5f7657..bc18d7b7 100644 --- a/pkg/analyzer/lib/src/dart/element/member.dart +++ b/pkg/analyzer/lib/src/dart/element/member.dart
@@ -2,6 +2,7 @@ // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. +import 'package:analyzer/dart/analysis/session.dart'; import 'package:analyzer/dart/ast/ast.dart'; import 'package:analyzer/dart/constant/value.dart'; import 'package:analyzer/dart/element/element.dart'; @@ -63,6 +64,7 @@ T accept<T>(ElementVisitor<T> visitor) => visitor.visitConstructorElement(this); + @deprecated @override ConstructorDeclaration computeNode() => baseElement.computeNode(); @@ -268,6 +270,7 @@ @override T accept<T>(ElementVisitor<T> visitor) => visitor.visitFieldElement(this); + @deprecated @override VariableDeclaration computeNode() => baseElement.computeNode(); @@ -326,6 +329,7 @@ @override T accept<T>(ElementVisitor<T> visitor) => visitor.visitFunctionElement(this); + @deprecated @override FunctionDeclaration computeNode() => baseElement.computeNode(); @@ -496,14 +500,19 @@ int get nameOffset => _baseElement.nameOffset; @override + AnalysisSession get session => _baseElement.session; + + @override Source get source => _baseElement.source; + @deprecated @override CompilationUnit get unit => _baseElement.unit; @override String computeDocumentationComment() => documentationComment; + @deprecated @override AstNode computeNode() => _baseElement.computeNode(); @@ -586,6 +595,7 @@ @override T accept<T>(ElementVisitor<T> visitor) => visitor.visitMethodElement(this); + @deprecated @override MethodDeclaration computeNode() => baseElement.computeNode(); @@ -729,6 +739,7 @@ @override T accept<T>(ElementVisitor<T> visitor) => visitor.visitParameterElement(this); + @deprecated @override FormalParameter computeNode() => baseElement.computeNode();
diff --git a/pkg/analyzer/lib/src/dart/element/type.dart b/pkg/analyzer/lib/src/dart/element/type.dart index b566cbb..86b41bc 100644 --- a/pkg/analyzer/lib/src/dart/element/type.dart +++ b/pkg/analyzer/lib/src/dart/element/type.dart
@@ -2053,6 +2053,16 @@ @override DartType replaceTopAndBottom(TypeProvider typeProvider, {bool isCovariant: true}) { + // First check if this is actually an instance of Bottom + if (this.isDartCoreNull) { + if (isCovariant) { + return this; + } else { + return typeProvider.objectType; + } + } + + // Otherwise, recurse over type arguments. var typeArguments = _transformOrShare( this.typeArguments, (t) => (t as TypeImpl)
diff --git a/pkg/analyzer/lib/src/dart/element/wrapped.dart b/pkg/analyzer/lib/src/dart/element/wrapped.dart index aaad9cd..3dfc8d6 100644 --- a/pkg/analyzer/lib/src/dart/element/wrapped.dart +++ b/pkg/analyzer/lib/src/dart/element/wrapped.dart
@@ -2,6 +2,7 @@ // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. +import 'package:analyzer/dart/analysis/session.dart'; import 'package:analyzer/dart/ast/ast.dart' hide Directive; import 'package:analyzer/dart/element/element.dart'; import 'package:analyzer/src/dart/resolver/scope.dart'; @@ -151,6 +152,9 @@ int get nameOffset => wrappedUnit.nameOffset; @override + AnalysisSession get session => wrappedUnit.session; + + @override Source get source => wrappedUnit.source; @override @@ -160,6 +164,7 @@ @override List<ClassElement> get types => wrappedUnit.types; + @deprecated @override CompilationUnit get unit => wrappedUnit.unit; @@ -179,6 +184,7 @@ String computeDocumentationComment() => wrappedUnit .computeDocumentationComment(); // ignore: deprecated_member_use + @deprecated @override CompilationUnit computeNode() => wrappedUnit.computeNode(); @@ -342,8 +348,12 @@ int get prefixOffset => wrappedImport.prefixOffset; @override + AnalysisSession get session => wrappedImport.session; + + @override Source get source => wrappedImport.source; + @deprecated @override CompilationUnit get unit => wrappedImport.unit; @@ -363,6 +373,7 @@ String computeDocumentationComment() => wrappedImport .computeDocumentationComment(); // ignore: deprecated_member_use + @deprecated @override AstNode computeNode() => wrappedImport.computeNode(); @@ -560,9 +571,16 @@ Namespace get publicNamespace => wrappedLib.publicNamespace; @override + AnalysisSession get session => wrappedLib.session; + + @override Source get source => wrappedLib.source; @override + Iterable<Element> get topLevelElements => wrappedLib.topLevelElements; + + @deprecated + @override CompilationUnit get unit => wrappedLib.unit; @override @@ -575,6 +593,7 @@ String computeDocumentationComment() => wrappedLib.computeDocumentationComment(); // ignore: deprecated_member_use + @deprecated @override AstNode computeNode() => wrappedLib.computeNode();
diff --git a/pkg/analyzer/lib/src/dart/error/hint_codes.dart b/pkg/analyzer/lib/src/dart/error/hint_codes.dart index 12f0423..b6364f8 100644 --- a/pkg/analyzer/lib/src/dart/error/hint_codes.dart +++ b/pkg/analyzer/lib/src/dart/error/hint_codes.dart
@@ -571,21 +571,6 @@ /** * This hint is generated anywhere where the - * [StaticTypeWarningCode.UNDEFINED_METHOD] would have been generated, if we - * used propagated information for the warnings. - * - * Parameters: - * 0: the name of the method that is undefined - * 1: the resolved type name that the method lookup is happening on - */ - static const HintCode UNDEFINED_METHOD = const HintCode( - 'UNDEFINED_METHOD', "The method '{0}' isn't defined for the class '{1}'.", - correction: - "Try correcting the name to the name of an existing method, or " - "defining a method named '{0}'."); - - /** - * This hint is generated anywhere where the * [StaticTypeWarningCode.UNDEFINED_OPERATOR] would have been generated, if we * used propagated information for the warnings. *
diff --git a/pkg/analyzer/lib/src/dart/resolver/method_invocation_resolver.dart b/pkg/analyzer/lib/src/dart/resolver/method_invocation_resolver.dart new file mode 100644 index 0000000..46f8334 --- /dev/null +++ b/pkg/analyzer/lib/src/dart/resolver/method_invocation_resolver.dart
@@ -0,0 +1,625 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:analyzer/dart/ast/ast.dart'; +import 'package:analyzer/dart/ast/token.dart'; +import 'package:analyzer/dart/element/element.dart'; +import 'package:analyzer/dart/element/type.dart'; +import 'package:analyzer/src/dart/ast/ast.dart'; +import 'package:analyzer/src/dart/element/element.dart'; +import 'package:analyzer/src/dart/element/inheritance_manager2.dart'; +import 'package:analyzer/src/dart/element/member.dart'; +import 'package:analyzer/src/dart/element/type.dart'; +import 'package:analyzer/src/dart/resolver/scope.dart'; +import 'package:analyzer/src/error/codes.dart'; +import 'package:analyzer/src/generated/resolver.dart'; + +class MethodInvocationResolver { + static final _nameCall = new Name(null, 'call'); + + /// The resolver driving this participant. + final ResolverVisitor _resolver; + + /// The type representing the type 'dynamic'. + final DynamicTypeImpl _dynamicType = DynamicTypeImpl.instance; + + /// The type representing the type 'type'. + final InterfaceType _typeType; + + /// The manager for the inheritance mappings. + final InheritanceManager2 _inheritance; + + /// The element for the library containing the compilation unit being visited. + final LibraryElement _definingLibrary; + + /// The URI of [_definingLibrary]. + final Uri _definingLibraryUri; + + /// The object keeping track of which elements have had their types promoted. + final TypePromotionManager _promoteManager; + + /// The [Name] object of the invocation being resolved by [resolve]. + Name _currentName; + + MethodInvocationResolver(this._resolver) + : _typeType = _resolver.typeProvider.typeType, + _inheritance = _resolver.inheritance, + _definingLibrary = _resolver.definingLibrary, + _definingLibraryUri = _resolver.definingLibrary.source.uri, + _promoteManager = _resolver.promoteManager; + + /// The scope used to resolve identifiers. + Scope get nameScope => _resolver.nameScope; + + void resolve(MethodInvocation node) { + SimpleIdentifier nameNode = node.methodName; + String name = nameNode.name; + _currentName = Name(_definingLibraryUri, name); + + // + // Synthetic identifiers have been already reported during parsing. + // + if (nameNode.isSynthetic) { + return; + } + + Expression receiver = node.realTarget; + + if (receiver == null) { + _resolveReceiverNull(node, nameNode, name); + return; + } + + if (receiver is NullLiteral) { + _setDynamicResolution(node); + return; + } + + if (receiver is SimpleIdentifier) { + var receiverElement = receiver.staticElement; + if (receiverElement is PrefixElement) { + _resolveReceiverPrefix(node, receiver, receiverElement, nameNode, name); + return; + } + } + + if (receiver is SuperExpression) { + _resolveReceiverSuper(node, receiver, nameNode, name); + return; + } + + ClassElement typeReference = getTypeReference(receiver); + if (typeReference != null) { + _resolveReceiverTypeLiteral(node, typeReference, nameNode, name); + return; + } + + DartType receiverType = receiver.staticType; + receiverType = _resolveTypeParameter(receiverType); + + if (receiverType is InterfaceType) { + _resolveReceiverInterfaceType(node, receiverType, nameNode, name); + return; + } + + if (receiverType is DynamicTypeImpl) { + _resolveReceiverDynamic(node, name); + return; + } + + if (receiverType is FunctionType) { + _resolveReceiverFunctionType( + node, receiver, receiverType, nameNode, name); + return; + } + + if (receiverType is VoidType) { + _reportUseOfVoidType(node, receiver); + return; + } + } + + /// Given an [argumentList] and the executable [element] that will be invoked + /// using those arguments, compute the list of parameters that correspond to + /// the list of arguments. Return the parameters that correspond to the + /// arguments, or `null` if no correspondence could be computed. + List<ParameterElement> _computeCorrespondingParameters( + ArgumentList argumentList, DartType type) { + if (type is InterfaceType) { + MethodElement callMethod = + type.lookUpMethod(FunctionElement.CALL_METHOD_NAME, _definingLibrary); + if (callMethod != null) { + return _resolveArgumentsToFunction(false, argumentList, callMethod); + } + } else if (type is FunctionType) { + return _resolveArgumentsToParameters( + false, argumentList, type.parameters); + } + return null; + } + + DartType _getCalleeType(FunctionType targetType) { + if (targetType.element.kind == ElementKind.GETTER) { + var calleeType = (targetType as FunctionTypeImpl).returnType; + calleeType = _resolveTypeParameter(calleeType); + return calleeType; + } + return targetType; + } + + /// Check for a generic type, and apply type arguments. + FunctionType _instantiateFunctionType( + FunctionType invokeType, TypeArgumentList typeArguments, AstNode node) { + var typeFormals = invokeType.typeFormals; + var arguments = typeArguments?.arguments; + if (arguments != null && arguments.length != typeFormals.length) { + _resolver.errorReporter.reportErrorForNode( + StaticTypeWarningCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS_METHOD, + node, + [invokeType, typeFormals.length, arguments?.length ?? 0]); + arguments = null; + } + + if (typeFormals.isNotEmpty) { + if (arguments == null) { + return _resolver.typeSystem.instantiateToBounds(invokeType); + } else { + return invokeType.instantiate(arguments.map((n) => n.type).toList()); + } + } + + return invokeType; + } + + bool _isCoreFunction(DartType type) { + // TODO(scheglov) Can we optimize this? + return type is InterfaceType && type.isDartCoreFunction; + } + + ExecutableElement _lookUpClassMember(ClassElement element, String name) { + // TODO(scheglov) Use class hierarchy. + return element.lookUpMethod(name, _definingLibrary); + } + + void _reportInvocationOfNonFunction(MethodInvocation node) { + _setDynamicResolution(node, setNameTypeToDynamic: false); + _resolver.errorReporter.reportErrorForNode( + StaticTypeWarningCode.INVOCATION_OF_NON_FUNCTION, + node.methodName, + [node.methodName.name], + ); + } + + void _reportPrefixIdentifierNotFollowedByDot(SimpleIdentifier target) { + _resolver.errorReporter.reportErrorForNode( + CompileTimeErrorCode.PREFIX_IDENTIFIER_NOT_FOLLOWED_BY_DOT, + target, + [target.name], + ); + } + + void _reportUndefinedFunction( + MethodInvocation node, Identifier ignorableIdentifier) { + _setDynamicResolution(node); + + // TODO(scheglov) This is duplication. + if (nameScope.shouldIgnoreUndefined(ignorableIdentifier)) { + return; + } + + _resolver.errorReporter.reportErrorForNode( + StaticTypeWarningCode.UNDEFINED_FUNCTION, + node.methodName, + [node.methodName.name], + ); + } + + void _reportUndefinedMethod( + MethodInvocation node, String name, ClassElement typeReference) { + _setDynamicResolution(node); + _resolver.errorReporter.reportErrorForNode( + StaticTypeWarningCode.UNDEFINED_METHOD, + node.methodName, + [name, typeReference.displayName], + ); + } + + void _reportUseOfVoidType(MethodInvocation node, AstNode errorNode) { + _setDynamicResolution(node); + _resolver.errorReporter.reportErrorForNode( + StaticWarningCode.USE_OF_VOID_RESULT, + errorNode, + ); + } + + /// Given an [argumentList] and the [executableElement] that will be invoked + /// using those argument, compute the list of parameters that correspond to the + /// list of arguments. An error will be reported if any of the arguments cannot + /// be matched to a parameter. The flag [reportAsError] should be `true` if a + /// compile-time error should be reported; or `false` if a compile-time warning + /// should be reported. Return the parameters that correspond to the arguments, + /// or `null` if no correspondence could be computed. + List<ParameterElement> _resolveArgumentsToFunction(bool reportAsError, + ArgumentList argumentList, ExecutableElement executableElement) { + if (executableElement == null) { + return null; + } + List<ParameterElement> parameters = executableElement.parameters; + return _resolveArgumentsToParameters( + reportAsError, argumentList, parameters); + } + + /// Given an [argumentList] and the [parameters] related to the element that + /// will be invoked using those arguments, compute the list of parameters that + /// correspond to the list of arguments. An error will be reported if any of + /// the arguments cannot be matched to a parameter. The flag [reportAsError] + /// should be `true` if a compile-time error should be reported; or `false` if + /// a compile-time warning should be reported. Return the parameters that + /// correspond to the arguments. + List<ParameterElement> _resolveArgumentsToParameters(bool reportAsError, + ArgumentList argumentList, List<ParameterElement> parameters) { + return ResolverVisitor.resolveArgumentsToParameters( + argumentList, parameters, _resolver.errorReporter.reportErrorForNode, + reportAsError: reportAsError); + } + + /// Given that we are accessing a property of the given [classElement] with the + /// given [propertyName], return the element that represents the property. + Element _resolveElement( + ClassElement classElement, SimpleIdentifier propertyName) { + // TODO(scheglov) Replace with class hierarchy. + String name = propertyName.name; + Element element = null; + if (propertyName.inSetterContext()) { + element = classElement.getSetter(name); + } + if (element == null) { + element = classElement.getGetter(name); + } + if (element == null) { + element = classElement.getMethod(name); + } + if (element != null && element.isAccessibleIn(_definingLibrary)) { + return element; + } + return null; + } + + void _resolveReceiverDynamic(MethodInvocation node, String name) { + _setDynamicResolution(node); + } + + void _resolveReceiverFunctionType(MethodInvocation node, Expression receiver, + FunctionType receiverType, SimpleIdentifier nameNode, String name) { + if (name == FunctionElement.CALL_METHOD_NAME) { + _setResolution(node, receiverType); + // TODO(scheglov) Replace this with using FunctionType directly. + // Here was erase resolution that _setResolution() sets. + nameNode.staticElement = null; + nameNode.staticType = _dynamicType; + return; + } + + // We can invoke Object methods on Function. + var type = _inheritance.getMember( + _resolver.typeProvider.objectType, + new Name(null, name), + ); + if (type != null) { + nameNode.staticElement = type.element; + return _setResolution(node, type); + } + + _reportUndefinedMethod( + node, + name, + _resolver.typeProvider.functionType.element, + ); + } + + void _resolveReceiverInterfaceType(MethodInvocation node, + InterfaceType receiverType, SimpleIdentifier nameNode, String name) { + if (_isCoreFunction(receiverType) && + name == FunctionElement.CALL_METHOD_NAME) { + _setDynamicResolution(node); + return; + } + + var targetType = _inheritance.getMember(receiverType, _currentName); + if (targetType != null) { + var calleeType = _getCalleeType(targetType); + + // TODO(scheglov) This is bad, we have to create members here. + // Find a way to avoid this. + Element element; + var baseElement = targetType.element; + if (baseElement is MethodElement) { + element = MethodMember.from(baseElement, receiverType); + } else if (baseElement is PropertyAccessorElement) { + element = PropertyAccessorMember.from(baseElement, receiverType); + } + nameNode.staticElement = element; + + return _setResolution(node, calleeType); + } + + // The interface of the receiver does not have an instance member. + // Try to recover and find a member in the class. + var targetElement = _lookUpClassMember(receiverType.element, name); + if (targetElement != null && targetElement.isStatic) { + nameNode.staticElement = targetElement; + _setDynamicResolution(node); + _resolver.errorReporter.reportErrorForNode( + StaticTypeWarningCode.INSTANCE_ACCESS_TO_STATIC_MEMBER, + nameNode, + [ + name, + targetElement.kind.displayName, + targetElement.enclosingElement.displayName, + ], + ); + return; + } + + _setDynamicResolution(node); + _resolver.errorReporter.reportErrorForNode( + StaticTypeWarningCode.UNDEFINED_METHOD, + nameNode, + [name, receiverType.element.displayName], + ); + } + + void _resolveReceiverNull( + MethodInvocation node, SimpleIdentifier nameNode, String name) { + var element = nameScope.lookup(nameNode, _definingLibrary); + if (element != null) { + nameNode.staticElement = element; + if (element is MultiplyDefinedElement) { + MultiplyDefinedElement multiply = element; + element = multiply.conflictingElements[0]; + } + if (element is ExecutableElement) { + var calleeType = _getCalleeType(element.type); + return _setResolution(node, calleeType); + } + if (element is VariableElement) { + var targetType = _promoteManager.getStaticType(element); + return _setResolution(node, targetType); + } + // TODO(scheglov) This is a questionable distinction. + if (element is PrefixElement) { + _setDynamicResolution(node); + return _reportPrefixIdentifierNotFollowedByDot(nameNode); + } + return _reportInvocationOfNonFunction(node); + } + + ClassElement enclosingClass = _resolver.enclosingClass; + if (enclosingClass == null) { + return _reportUndefinedFunction(node, node.methodName); + } + + var receiverType = enclosingClass.type; + var targetType = _inheritance.getMember(receiverType, _currentName); + + if (targetType != null) { + nameNode.staticElement = targetType.element; + var calleeType = _getCalleeType(targetType); + return _setResolution(node, calleeType); + } + + var targetElement = _lookUpClassMember(enclosingClass, name); + if (targetElement != null && targetElement.isStatic) { + nameNode.staticElement = targetElement; + _setDynamicResolution(node); + _resolver.errorReporter.reportErrorForNode( + StaticTypeWarningCode.UNQUALIFIED_REFERENCE_TO_NON_LOCAL_STATIC_MEMBER, + nameNode, + [receiverType.displayName], + ); + return; + } + + return _reportUndefinedMethod(node, name, enclosingClass); + } + + void _resolveReceiverPrefix(MethodInvocation node, SimpleIdentifier receiver, + PrefixElement prefix, SimpleIdentifier nameNode, String name) { + if (node.operator.type == TokenType.QUESTION_PERIOD) { + _reportPrefixIdentifierNotFollowedByDot(receiver); + } + + if (name == FunctionElement.LOAD_LIBRARY_NAME) { + var imports = _definingLibrary.getImportsWithPrefix(prefix); + if (imports.length == 1 && imports[0].isDeferred) { + var importedLibrary = imports[0].importedLibrary; + var loadLibraryFunction = importedLibrary?.loadLibraryFunction; + nameNode.staticElement = loadLibraryFunction; + node.staticInvokeType = loadLibraryFunction?.type; + node.staticType = loadLibraryFunction?.returnType; + return; + } + } + + // TODO(scheglov) I don't like how we resolve prefixed names. + // But maybe this is the only one solution. + var prefixedName = new PrefixedIdentifierImpl.temp(receiver, nameNode); + var element = nameScope.lookup(prefixedName, _definingLibrary); + nameNode.staticElement = element; + + if (element is MultiplyDefinedElement) { + MultiplyDefinedElement multiply = element; + element = multiply.conflictingElements[0]; + } + + if (element is ExecutableElement) { + var calleeType = _getCalleeType(element.type); + return _setResolution(node, calleeType); + } + + _reportUndefinedFunction(node, prefixedName); + } + + void _resolveReceiverSuper(MethodInvocation node, SuperExpression receiver, + SimpleIdentifier nameNode, String name) { + if (!_isSuperInValidContext(receiver)) { + return; + } + + var receiverType = _resolver.enclosingClass.type; + var targetType = _inheritance.getMember( + receiverType, + _currentName, + forSuper: true, + ); + + // If there is that concrete dispatch target, then we are done. + if (targetType != null) { + nameNode.staticElement = targetType.element; + var calleeType = _getCalleeType(targetType); + _setResolution(node, calleeType); + return; + } + + // Otherwise, this is an error. + // But we would like to give the user at least some resolution. + // So, we try to find the interface target. + targetType = _inheritance.getInherited(receiverType, _currentName); + if (targetType != null) { + nameNode.staticElement = targetType.element; + var calleeType = _getCalleeType(targetType); + _setResolution(node, calleeType); + + ClassElementImpl receiverSuperClass = AbstractClassElementImpl.getImpl( + receiverType.element.supertype.element, + ); + if (receiverSuperClass.hasNoSuchMethod) { + return; + } + + _resolver.errorReporter.reportErrorForNode( + CompileTimeErrorCode.ABSTRACT_SUPER_MEMBER_REFERENCE, + nameNode, + [targetType.element.kind.displayName, name]); + return; + } + + // Nothing help, there is no target at all. + _setDynamicResolution(node); + _resolver.errorReporter.reportErrorForNode( + StaticTypeWarningCode.UNDEFINED_SUPER_METHOD, + nameNode, + [name, _resolver.enclosingClass.displayName]); + } + + void _resolveReceiverTypeLiteral(MethodInvocation node, ClassElement receiver, + SimpleIdentifier nameNode, String name) { + if (node.isCascaded) { + receiver = _typeType.element; + } + + var element = _resolveElement(receiver, nameNode); + if (element != null) { + if (element is ExecutableElement) { + nameNode.staticElement = element; + var calleeType = _getCalleeType(element.type); + _setResolution(node, calleeType); + } else { + _reportInvocationOfNonFunction(node); + } + return; + } + + _reportUndefinedMethod(node, name, receiver); + } + + /// If the given [type] is a type parameter, replace with its bound. + /// Otherwise, return the original type. + DartType _resolveTypeParameter(DartType type) { + if (type is TypeParameterType) { + return type.resolveToBound(_resolver.typeProvider.objectType); + } + return type; + } + + void _setDynamicResolution(MethodInvocation node, + {bool setNameTypeToDynamic: true}) { + if (setNameTypeToDynamic) { + node.methodName.staticType = _dynamicType; + } + node.staticInvokeType = _dynamicType; + node.staticType = _dynamicType; + } + + void _setResolution(MethodInvocation node, DartType type) { + if (type == _dynamicType || _isCoreFunction(type)) { + _setDynamicResolution(node); + return; + } + + // TODO(scheglov) We need this for StaticTypeAnalyzer to run inference. + // But it seems weird. Do we need to know the raw type of a function?! + node.methodName.staticType = type; + + if (type is InterfaceType) { + var call = _inheritance.getMember(type, _nameCall); + if (call != null && call.element.kind == ElementKind.METHOD) { + type = call; + } + } + + if (type is FunctionType) { + // TODO(scheglov) Extract this when receiver is already FunctionType? + var instantiatedType = _instantiateFunctionType( + type, + node.typeArguments, + node.methodName, + ); + node.staticInvokeType = instantiatedType; + node.staticType = instantiatedType.returnType; + // TODO(scheglov) too much magic + node.argumentList.correspondingStaticParameters = + _computeCorrespondingParameters( + node.argumentList, + instantiatedType, + ); + return; + } + + if (type is VoidType) { + return _reportUseOfVoidType(node, node.methodName); + } + + _reportInvocationOfNonFunction(node); + } + + /// Checks whether the given [expression] is a reference to a class. If it is + /// then the element representing the class is returned, otherwise `null` is + /// returned. + static ClassElement getTypeReference(Expression expression) { + if (expression is Identifier) { + Element staticElement = expression.staticElement; + if (staticElement is ClassElement) { + return staticElement; + } + } + return null; + } + + /// Return `true` if the given 'super' [expression] is used in a valid context. + static bool _isSuperInValidContext(SuperExpression expression) { + for (AstNode node = expression; node != null; node = node.parent) { + if (node is CompilationUnit) { + return false; + } else if (node is ConstructorDeclaration) { + return node.factoryKeyword == null; + } else if (node is ConstructorFieldInitializer) { + return false; + } else if (node is MethodDeclaration) { + return !node.isStatic; + } + } + return false; + } +}
diff --git a/pkg/analyzer/lib/src/dart/resolver/scope.dart b/pkg/analyzer/lib/src/dart/resolver/scope.dart index 4d71222..f1fb360 100644 --- a/pkg/analyzer/lib/src/dart/resolver/scope.dart +++ b/pkg/analyzer/lib/src/dart/resolver/scope.dart
@@ -537,8 +537,11 @@ var conflictingElements = <Element>[] ..addAll(sdkElements) ..addAll(nonSdkElements); - return new MultiplyDefinedElementImpl(_definingLibrary.context, - conflictingElements.first.name, conflictingElements); + return new MultiplyDefinedElementImpl( + _definingLibrary.context, + _definingLibrary.session, + conflictingElements.first.name, + conflictingElements); } if (nonSdkElements.isNotEmpty) { result = nonSdkElements.first; @@ -1011,8 +1014,7 @@ * not be determined. */ Source getSource(AstNode identifier) { - CompilationUnit unit = - identifier.getAncestor((node) => node is CompilationUnit); + CompilationUnit unit = identifier.thisOrAncestorOfType<CompilationUnit>(); if (unit != null) { CompilationUnitElement unitElement = unit.declaredElement; if (unitElement != null) {
diff --git a/pkg/analyzer/lib/src/dart/scanner/scanner.dart b/pkg/analyzer/lib/src/dart/scanner/scanner.dart index 25af788e..ab852cf 100644 --- a/pkg/analyzer/lib/src/dart/scanner/scanner.dart +++ b/pkg/analyzer/lib/src/dart/scanner/scanner.dart
@@ -54,6 +54,11 @@ bool scanLazyAssignmentOperators = false; /** + * A flag indicating whether the scanner should recognize the `>>>` operator. + */ + bool enableGtGtGt = false; + + /** * Initialize a newly created scanner to scan characters from the given * [source]. The given character [reader] will be used to read the characters * in the source. The given [_errorListener] will be informed of any errors @@ -99,6 +104,7 @@ Token tokenize() { fasta.ScannerResult result = fasta.scanString(_contents, + enableGtGtGt: enableGtGtGt, includeComments: _preserveComments, scanLazyAssignmentOperators: scanLazyAssignmentOperators);
diff --git a/pkg/analyzer/lib/src/error/codes.dart b/pkg/analyzer/lib/src/error/codes.dart index d966ee8..a3cff21 100644 --- a/pkg/analyzer/lib/src/error/codes.dart +++ b/pkg/analyzer/lib/src/error/codes.dart
@@ -1,4 +1,4 @@ -// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file +// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. @@ -49,14 +49,6 @@ "'{1}'."); /** - * 16.12.2 Const: It is a compile-time error if evaluation of a constant - * object results in an uncaught exception being thrown. - */ - static const CheckedModeCompileTimeErrorCode CONST_EVAL_THROWS_EXCEPTION = - const CheckedModeCompileTimeErrorCode('CONST_EVAL_THROWS_EXCEPTION', - "Evaluation of this constant expression throws an exception."); - - /** * 7.6.1 Generative Constructors: In checked mode, it is a dynamic type error * if o is not <b>null</b> and the interface of the class of <i>o</i> is not a * subtype of the static type of the field <i>v</i>. @@ -87,6 +79,10 @@ * the type of the named parameter <i>q</i> of <i>f</i>. It is a static * warning if <i>T<sub>j</sub></i> may not be assigned to <i>S<sub>j</sub>, * 1 <= j <= m</i>. + * + * Parameters: + * 0: the actual type of the list element + * 1: the expected type of the list element */ static const CheckedModeCompileTimeErrorCode LIST_ELEMENT_TYPE_NOT_ASSIGNABLE = const CheckedModeCompileTimeErrorCode( @@ -134,6 +130,15 @@ "'{1}'."); /** + * Parameters: + * 0: the actual type of the set element + * 1: the expected type of the set element + */ + static const CheckedModeCompileTimeErrorCode SET_ELEMENT_TYPE_NOT_ASSIGNABLE = + const CheckedModeCompileTimeErrorCode('SET_ELEMENT_TYPE_NOT_ASSIGNABLE', + "The element type '{0}' can't be assigned to the set type '{1}'."); + + /** * 16.12.2 Const: It is a compile-time error if evaluation of a constant * object results in an uncaught exception being thrown. */ @@ -659,6 +664,18 @@ correction: "Try adding an initialization to the declaration."); /** + * Parameters: + * 0: the type of the element + */ + static const CompileTimeErrorCode CONST_SET_ELEMENT_TYPE_IMPLEMENTS_EQUALS = + const CompileTimeErrorCode( + 'CONST_SET_ELEMENT_TYPE_IMPLEMENTS_EQUALS', + "The constant set element type '{0}' can't override " + "the == operator.", + correction: "Try using a different value for the element, or " + "removing the keyword 'const' from the set."); + + /** * 16.12.2 Const: An expression of one of the forms !e, e1 && e2 or e1 || e2, * where e, e1 and e2 are constant expressions that evaluate to a boolean * value. @@ -670,6 +687,17 @@ "'bool'."); /** + * 16.12.2 Const: An expression of one of the forms !e, e1 && e2 or e1 || e2, + * where e, e1 and e2 are constant expressions that evaluate to a boolean + * value. + */ + static const CompileTimeErrorCode CONST_EVAL_TYPE_BOOL_INT = + const CompileTimeErrorCode( + 'CONST_EVAL_TYPE_BOOL_INT', + "In constant expressions, operands of this operator must be of type " + "'bool' or 'int'."); + + /** * 16.12.2 Const: An expression of one of the forms e1 == e2 or e1 != e2 where * e1 and e2 are constant expressions that evaluate to a numeric, string or * boolean value or to null. @@ -703,6 +731,12 @@ "In constant expressions, operands of this operator must be of type " "'num'."); + static const CompileTimeErrorCode CONST_EVAL_TYPE_TYPE = + const CompileTimeErrorCode( + 'CONST_EVAL_TYPE_TYPE', + "In constant expressions, operands of this operator must be of type " + "'Type'."); + /** * 16.12.2 Const: It is a compile-time error if evaluation of a constant * object results in an uncaught exception being thrown. @@ -1587,6 +1621,14 @@ correction: "Try replacing the type parameter with a different type."); + static const CompileTimeErrorCode INVALID_TYPE_ARGUMENT_IN_CONST_SET = + const CompileTimeErrorCode( + 'INVALID_TYPE_ARGUMENT_IN_CONST_SET', + "Constant set literals can't include a type parameter as a type " + "argument, such as '{0}'.", + correction: + "Try replacing the type parameter with a different type."); + /** * The 'covariant' keyword was found in an inappropriate location. */ @@ -1677,6 +1719,16 @@ "expression.", correction: "Try adding the keyword 'const' before the literal."); + /** + * 12.1 Constants: A constant expression is ... a constant set literal. + */ + static const CompileTimeErrorCode MISSING_CONST_IN_SET_LITERAL = + const CompileTimeErrorCode( + 'MISSING_CONST_IN_SET_LITERAL', + "Set literals must be prefixed with 'const' when used as a constant " + "expression.", + correction: "Try adding the keyword 'const' before the literal."); + static const CompileTimeErrorCode MISSING_DART_LIBRARY = const CompileTimeErrorCode( 'MISSING_DART_LIBRARY', "Required library '{0}' is missing.", @@ -1714,7 +1766,8 @@ static const CompileTimeErrorCode MIXIN_APPLICATION_NOT_IMPLEMENTED_INTERFACE = const CompileTimeErrorCode( 'MIXIN_APPLICATION_NOT_IMPLEMENTED_INTERFACE', - "The class doesn't implement the required class '{0}'."); + "The class doesn't implement the required class '{0}'.", + correction: "Try extending the class '{0}'."); /** * It's a compile-time error to apply a mixin containing super-invocations to @@ -1967,8 +2020,8 @@ static const CompileTimeErrorCode NON_CONST_MAP_AS_EXPRESSION_STATEMENT = const CompileTimeErrorCode( 'NON_CONST_MAP_AS_EXPRESSION_STATEMENT', - "A non-constant map literal without type arguments can't be used as " - "an expression statement."); + "A non-constant map or set literal without type arguments can't be " + "used as an expression statement."); /** * 13.9 Switch: Given a switch statement of the form <i>switch (e) { @@ -2041,7 +2094,8 @@ static const CompileTimeErrorCode NON_CONSTANT_LIST_ELEMENT = const CompileTimeErrorCode('NON_CONSTANT_LIST_ELEMENT', "The values in a const list literal must be constants.", - correction: "Try removing the keyword 'const' from the map literal."); + correction: + "Try removing the keyword 'const' from the list literal."); /** * 12.6 Lists: It is a compile time error if an element of a constant list @@ -2118,6 +2172,19 @@ const CompileTimeErrorCode('NON_CONSTANT_ANNOTATION_CONSTRUCTOR', "Annotation creation can only call a const constructor."); + static const CompileTimeErrorCode NON_CONSTANT_SET_ELEMENT = + const CompileTimeErrorCode('NON_CONSTANT_SET_ELEMENT', + "The values in a const set literal must be constants.", + correction: "Try removing the keyword 'const' from the set literal."); + + static const CompileTimeErrorCode + NON_CONSTANT_SET_ELEMENT_FROM_DEFERRED_LIBRARY = + const CompileTimeErrorCode( + 'NON_CONSTANT_SET_ELEMENT_FROM_DEFERRED_LIBRARY', + "Constant values from a deferred library can't be used as values in " + "a 'const' set.", + correction: "Try removing the keyword 'const' from the set literal."); + /** * 7.6.3 Constant Constructors: Any expression that appears within the * initializer list of a constant constructor must be a potentially constant @@ -2251,9 +2318,9 @@ static const CompileTimeErrorCode PRIVATE_COLLISION_IN_MIXIN_APPLICATION = const CompileTimeErrorCode( 'PRIVATE_COLLISION_IN_MIXIN_APPLICATION', - "The private name {0}, defined by {1}, conflicts with the same name " - "defined by {2}.", - correction: "Try removing {1} from the 'with' clause."); + "The private name '{0}', defined by '{1}', " + "conflicts with the same name defined by '{2}'.", + correction: "Try removing '{1}' from the 'with' clause."); /** * 6.2.2 Optional Formals: It is a compile-time error if the name of a named @@ -2555,13 +2622,13 @@ * It is a compile-time error if a generic function type is used as an actual * type argument. */ - static const CompileTimeErrorCode GENERIC_FUNCTION_CANNOT_BE_TYPE_ARGUMENT = + static const CompileTimeErrorCode + GENERIC_FUNCTION_TYPE_CANNOT_BE_TYPE_ARGUMENT = const CompileTimeErrorCode( - 'GENERIC_FUNCTION_CANNOT_BE_TYPE_ARGUMENT', - "Generic function has type parameters '<{0}>', so it may not be used" - ' as a type argument', - correction: "Try removing the type parameters '<{0}>', or using" - " 'dynamic' as the type argument here instead of a function."); + 'GENERIC_FUNCTION_TYPE_CANNOT_BE_TYPE_ARGUMENT', + "A generic function type cannot be a type argument.", + correction: "Try removing type parameters from the generic function " + "type, or using 'dynamic' as the type argument here."); /** * 15.3.1 Typedef: Any self reference, either directly, or recursively via @@ -2808,6 +2875,17 @@ correction: "Try adjusting the number of type arguments."); /** + * Parameters: + * 0: the number of provided type arguments + */ + static const StaticTypeWarningCode EXPECTED_ONE_SET_TYPE_ARGUMENTS = + const StaticTypeWarningCode( + 'EXPECTED_ONE_SET_TYPE_ARGUMENTS', + "Set literals require exactly one type argument or none, " + "but {0} found.", + correction: "Try adjusting the number of type arguments."); + + /** * 12.8 Maps: A fresh instance (7.6.1) <i>m</i>, of size <i>n</i>, whose class * implements the built-in class <i>Map<K, V></i> is allocated. * @@ -3145,22 +3223,6 @@ "defining a method named '{0}'."); /** - * 12.15.1 Ordinary Invocation: Let <i>T</i> be the static type of <i>o</i>. - * It is a static type warning if <i>T</i> does not have an accessible - * instance member named <i>m</i>. - * - * Parameters: - * 0: the name of the method that is undefined - * 1: the resolved type name that the method lookup is happening on - */ - static const StaticTypeWarningCode UNDEFINED_METHOD_WITH_CONSTRUCTOR = - const StaticTypeWarningCode('UNDEFINED_METHOD_WITH_CONSTRUCTOR', - "The method '{0}' isn't defined for the class '{1}', but a constructor with that name is defined.", - correction: - "Try adding 'new' or 'const' to invoke the constructor, or " - "correcting the name to the name of an existing method."); - - /** * 12.18 Assignment: Evaluation of an assignment of the form * <i>e<sub>1</sub></i>[<i>e<sub>2</sub></i>] = <i>e<sub>3</sub></i> is * equivalent to the evaluation of the expression (a, i, e){a.[]=(i, e); @@ -3931,6 +3993,10 @@ * the type of the named parameter <i>q</i> of <i>f</i>. It is a static * warning if <i>T<sub>j</sub></i> may not be assigned to <i>S<sub>j</sub>, 1 * <= j <= m</i>. + * + * Parameters: + * 0: the actual type of the list element + * 1: the expected type of the list element */ static const StaticWarningCode LIST_ELEMENT_TYPE_NOT_ASSIGNABLE = const StaticWarningCode('LIST_ELEMENT_TYPE_NOT_ASSIGNABLE', @@ -4380,6 +4446,15 @@ correction: null); /** + * Parameters: + * 0: the actual type of the set element + * 1: the expected type of the set element + */ + static const StaticWarningCode SET_ELEMENT_TYPE_NOT_ASSIGNABLE = + const StaticWarningCode('SET_ELEMENT_TYPE_NOT_ASSIGNABLE', + "The element type '{0}' can't be assigned to the set type '{1}'."); + + /** * 12.16.3 Static Invocation: It is a static warning if <i>C</i> does not * declare a static method or getter <i>m</i>. * @@ -4639,6 +4714,13 @@ "type can be changed with an explicit generic type arguments or by " "changing the key and value types."); + static const StrongModeCode INVALID_CAST_LITERAL_SET = const StrongModeCode( + ErrorType.COMPILE_TIME_ERROR, + 'INVALID_CAST_LITERAL_SET', + "The set literal type '{0}' isn't of expected type '{1}'. The set's " + "type can be changed with an explicit generic type argument or by " + "changing the element types."); + static const StrongModeCode INVALID_CAST_FUNCTION_EXPR = const StrongModeCode( ErrorType.COMPILE_TIME_ERROR, 'INVALID_CAST_FUNCTION_EXPR',
diff --git a/pkg/analyzer/lib/src/error/inheritance_override.dart b/pkg/analyzer/lib/src/error/inheritance_override.dart index b74f141..d545ddc 100644 --- a/pkg/analyzer/lib/src/error/inheritance_override.dart +++ b/pkg/analyzer/lib/src/error/inheritance_override.dart
@@ -1,11 +1,11 @@ -// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. -import 'package:analyzer/analyzer.dart'; import 'package:analyzer/dart/ast/ast.dart'; import 'package:analyzer/dart/element/element.dart'; import 'package:analyzer/dart/element/type.dart'; +import 'package:analyzer/error/error.dart'; import 'package:analyzer/error/listener.dart'; import 'package:analyzer/src/dart/element/element.dart'; import 'package:analyzer/src/dart/element/inheritance_manager2.dart'; @@ -94,8 +94,12 @@ final TypeName superclass; final WithClause withClause; + /// The set of unique supertypes of the current class. + /// It is used to decide when to add a new element to [allSuperinterfaces]. + final Set<InterfaceType> allSupertypes = new Set<InterfaceType>(); + /// The list of all superinterfaces, collected so far. - final List<InterfaceType> allSuperinterfaces = []; + final List<Interface> allSuperinterfaces = []; _ClassVerifier({ this.typeSystem, @@ -122,8 +126,7 @@ // Add all superinterfaces of the direct supertype. if (type.superclass != null) { - ClassElementImpl.collectAllSupertypes( - allSuperinterfaces, type.superclass, null); + _addSuperinterfaces(type.superclass); } // Each mixin in `class C extends S with M0, M1, M2 {}` is equivalent to: @@ -136,15 +139,14 @@ var mixinNodes = withClause?.mixinTypes; var mixinTypes = type.mixins; for (var i = 0; i < mixinTypes.length; i++) { - _checkDeclaredMembers(mixinNodes[i], mixinTypes[i]); - ClassElementImpl.collectAllSupertypes( - allSuperinterfaces, mixinTypes[i], null); + var mixinType = mixinTypes[i]; + _checkDeclaredMembers(mixinNodes[i], mixinType); + _addSuperinterfaces(mixinType); } // Add all superinterfaces of the direct class interfaces. for (var interface in type.interfaces) { - ClassElementImpl.collectAllSupertypes( - allSuperinterfaces, interface, null); + _addSuperinterfaces(interface); } // Check the members if the class itself, against all the previously @@ -163,24 +165,24 @@ } // Compute the interface of the class. - var interfaceMembers = inheritance.getInterface(type); + var interface = inheritance.getInterface(type); // Report conflicts between direct superinterfaces of the class. - for (var conflict in interfaceMembers.conflicts) { + for (var conflict in interface.conflicts) { _reportInconsistentInheritance(classNameNode, conflict); } - _checkForMismatchedAccessorTypes(interfaceMembers); + _checkForMismatchedAccessorTypes(interface); if (!classElement.isAbstract) { List<FunctionType> inheritedAbstract = null; - for (var name in interfaceMembers.map.keys) { + for (var name in interface.map.keys) { if (!name.isAccessibleFor(libraryUri)) { continue; } - var interfaceType = interfaceMembers.map[name]; + var interfaceType = interface.map[name]; var concreteType = inheritance.getMember(type, name, concrete: true); // No concrete implementation of the name. @@ -226,6 +228,18 @@ } } + void _addSuperinterfaces(InterfaceType startingType) { + var supertypes = <InterfaceType>[]; + ClassElementImpl.collectAllSupertypes(supertypes, startingType, null); + for (int i = 0; i < supertypes.length; i++) { + var supertype = supertypes[i]; + if (allSupertypes.add(supertype)) { + var interface = inheritance.getInterface(supertype); + allSuperinterfaces.add(interface); + } + } + } + /// Check that the given [member] is a valid override of the corresponding /// instance members in each of [allSuperinterfaces]. The [libraryUri] is /// the URI of the library containing the [member]. @@ -238,8 +252,8 @@ if (member.isStatic) return; var name = new Name(libraryUri, member.name); - for (var superType in allSuperinterfaces) { - var superMemberType = inheritance.getInterface(superType).map[name]; + for (var superInterface in allSuperinterfaces) { + var superMemberType = superInterface.declared[name]; if (superMemberType != null) { // The case when members have different kinds is reported in verifier. // TODO(scheglov) Do it here? @@ -352,7 +366,7 @@ if (getter.element.kind == ElementKind.GETTER) { // TODO(scheglov) We should separate getters and setters. var setter = interface.map[new Name(libraryUri, '${name.name}=')]; - if (setter != null) { + if (setter != null && setter.parameters.length == 1) { var getterType = getter.returnType; var setterType = setter.parameters[0].type; if (!typeSystem.isAssignableTo(getterType, setterType)) {
diff --git a/pkg/analyzer/lib/src/fasta/ast_builder.dart b/pkg/analyzer/lib/src/fasta/ast_builder.dart index e816bf5..bb0a1296 100644 --- a/pkg/analyzer/lib/src/fasta/ast_builder.dart +++ b/pkg/analyzer/lib/src/fasta/ast_builder.dart
@@ -890,6 +890,29 @@ push(ast.nullLiteral(token)); } + @override + void handleEmptyLiteralSetOrMap( + Token leftBrace, Token constKeyword, Token rightBrace) { + // TODO(danrubel): From a type resolution standpoint, this could be either + // a set literal or a map literal depending upon the context + // in which this expression occurs. + // For now, generate a map literal. + handleLiteralMap(0, leftBrace, constKeyword, rightBrace); + } + + void handleLiteralSet( + int count, Token leftBracket, Token constKeyword, Token rightBracket) { + assert(optional('{', leftBracket)); + assert(optionalOrNull('const', constKeyword)); + assert(optional('}', rightBracket)); + debugEvent("LiteralSet"); + + List<Expression> entries = popTypedList(count) ?? <Expression>[]; + TypeArgumentList typeArguments = pop(); + push(ast.setLiteral( + constKeyword, typeArguments, leftBracket, entries, rightBracket)); + } + void handleLiteralMap( int count, Token leftBracket, Token constKeyword, Token rightBracket) { assert(optional('{', leftBracket));
diff --git a/pkg/analyzer/lib/src/fasta/error_converter.dart b/pkg/analyzer/lib/src/fasta/error_converter.dart index 8464578..b99d26f 100644 --- a/pkg/analyzer/lib/src/fasta/error_converter.dart +++ b/pkg/analyzer/lib/src/fasta/error_converter.dart
@@ -1,10 +1,12 @@ -// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file +// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. -import 'package:analyzer/analyzer.dart'; import 'package:analyzer/dart/ast/token.dart' show Token; +import 'package:analyzer/error/error.dart'; +import 'package:analyzer/error/listener.dart'; import 'package:analyzer/src/dart/error/syntactic_errors.dart'; +import 'package:analyzer/src/error/codes.dart'; import 'package:front_end/src/fasta/messages.dart' show Code, Message; /// An error reporter that knows how to convert a Fasta error into an analyzer
diff --git a/pkg/analyzer/lib/src/generated/element_resolver.dart b/pkg/analyzer/lib/src/generated/element_resolver.dart index b759dd0..53f150f 100644 --- a/pkg/analyzer/lib/src/generated/element_resolver.dart +++ b/pkg/analyzer/lib/src/generated/element_resolver.dart
@@ -1,4 +1,4 @@ -// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file +// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. @@ -19,6 +19,7 @@ import 'package:analyzer/src/dart/element/element.dart'; import 'package:analyzer/src/dart/element/inheritance_manager2.dart'; import 'package:analyzer/src/dart/element/type.dart'; +import 'package:analyzer/src/dart/resolver/method_invocation_resolver.dart'; import 'package:analyzer/src/error/codes.dart'; import 'package:analyzer/src/generated/engine.dart'; import 'package:analyzer/src/generated/resolver.dart'; @@ -82,7 +83,7 @@ * combinators that are not defined in the imported library (which is not an * error). */ -class ElementResolver extends SimpleAstVisitor<Object> { +class ElementResolver extends SimpleAstVisitor<void> { /** * The manager for the inheritance mappings. */ @@ -104,28 +105,25 @@ DartType _dynamicType; /** - * The type representing the type 'type'. + * The type representing the type 'Type'. */ InterfaceType _typeType; - /** - * The object keeping track of which elements have had their types promoted. - */ - TypePromotionManager _promoteManager; - /// Whether constant evaluation errors should be reported during resolution. final bool reportConstEvaluationErrors; + final MethodInvocationResolver _methodInvocationResolver; + /** * Initialize a newly created visitor to work for the given [_resolver] to * resolve the nodes in a compilation unit. */ ElementResolver(this._resolver, {this.reportConstEvaluationErrors: true}) : _inheritance = _resolver.inheritance, - _definingLibrary = _resolver.definingLibrary { + _definingLibrary = _resolver.definingLibrary, + _methodInvocationResolver = new MethodInvocationResolver(_resolver) { _dynamicType = _resolver.typeProvider.dynamicType; _typeType = _resolver.typeProvider.typeType; - _promoteManager = _resolver.promoteManager; } /** @@ -141,7 +139,7 @@ } @override - Object visitAssignmentExpression(AssignmentExpression node) { + void visitAssignmentExpression(AssignmentExpression node) { Token operator = node.operator; TokenType operatorType = operator.type; Expression leftHandSide = node.leftHandSide; @@ -154,7 +152,7 @@ staticType.isVoid) { _recordUndefinedToken( null, StaticWarningCode.USE_OF_VOID_RESULT, operator, []); - return null; + return; } if (operatorType != TokenType.AMPERSAND_AMPERSAND_EQ && @@ -176,40 +174,35 @@ } } } - return null; } @override - Object visitBinaryExpression(BinaryExpression node) { + void visitBinaryExpression(BinaryExpression node) { Token operator = node.operator; if (operator.isUserDefinableOperator) { _resolveBinaryExpression(node, operator.lexeme); } else if (operator.type == TokenType.BANG_EQ) { _resolveBinaryExpression(node, TokenType.EQ_EQ.lexeme); } - return null; } @override - Object visitBreakStatement(BreakStatement node) { + void visitBreakStatement(BreakStatement node) { node.target = _lookupBreakOrContinueTarget(node, node.label, false); - return null; } @override - Object visitClassDeclaration(ClassDeclaration node) { + void visitClassDeclaration(ClassDeclaration node) { resolveMetadata(node); - return null; } @override - Object visitClassTypeAlias(ClassTypeAlias node) { + void visitClassTypeAlias(ClassTypeAlias node) { resolveMetadata(node); - return null; } @override - Object visitCommentReference(CommentReference node) { + void visitCommentReference(CommentReference node) { Identifier identifier = node.identifier; if (identifier is SimpleIdentifier) { Element element = _resolveSimpleIdentifier(identifier); @@ -249,7 +242,7 @@ // TODO(brianwilkerson) Report this error? element = _resolver.nameScope.lookup(identifier, _definingLibrary); name.staticElement = element; - return null; + return; } LibraryElement library = element.library; if (library == null) { @@ -293,11 +286,10 @@ } } } - return null; } @override - Object visitConstructorDeclaration(ConstructorDeclaration node) { + void visitConstructorDeclaration(ConstructorDeclaration node) { super.visitConstructorDeclaration(node); ConstructorElement element = node.declaredElement; if (element is ConstructorElementImpl) { @@ -317,20 +309,18 @@ } resolveMetadata(node); } - return null; } @override - Object visitConstructorFieldInitializer(ConstructorFieldInitializer node) { + void visitConstructorFieldInitializer(ConstructorFieldInitializer node) { SimpleIdentifier fieldName = node.fieldName; ClassElement enclosingClass = _resolver.enclosingClass; FieldElement fieldElement = enclosingClass.getField(fieldName.name); fieldName.staticElement = fieldElement; - return null; } @override - Object visitConstructorName(ConstructorName node) { + void visitConstructorName(ConstructorName node) { DartType type = node.type.type; if (type != null && type.isDynamic) { // Nothing to do. @@ -358,29 +348,25 @@ // // This is part of a redirecting factory constructor; not sure which error code to use // } } - return null; } @override - Object visitContinueStatement(ContinueStatement node) { + void visitContinueStatement(ContinueStatement node) { node.target = _lookupBreakOrContinueTarget(node, node.label, true); - return null; } @override - Object visitDeclaredIdentifier(DeclaredIdentifier node) { + void visitDeclaredIdentifier(DeclaredIdentifier node) { resolveMetadata(node); - return null; } @override - Object visitEnumDeclaration(EnumDeclaration node) { + void visitEnumDeclaration(EnumDeclaration node) { resolveMetadata(node); - return null; } @override - Object visitExportDirective(ExportDirective node) { + void visitExportDirective(ExportDirective node) { ExportElement exportElement = node.element; if (exportElement != null) { // The element is null when the URI is invalid @@ -389,23 +375,21 @@ _resolveCombinators(exportElement.exportedLibrary, node.combinators); resolveMetadata(node); } - return null; } @override - Object visitFieldFormalParameter(FieldFormalParameter node) { + void visitFieldFormalParameter(FieldFormalParameter node) { _resolveMetadataForParameter(node); - return super.visitFieldFormalParameter(node); + super.visitFieldFormalParameter(node); } @override - Object visitFunctionDeclaration(FunctionDeclaration node) { + void visitFunctionDeclaration(FunctionDeclaration node) { resolveMetadata(node); - return null; } @override - Object visitFunctionExpressionInvocation(FunctionExpressionInvocation node) { + void visitFunctionExpressionInvocation(FunctionExpressionInvocation node) { Expression function = node.function; DartType staticInvokeType = _instantiateGenericMethod( function.staticType, node.typeArguments, node); @@ -417,23 +401,20 @@ if (parameters != null) { node.argumentList.correspondingStaticParameters = parameters; } - return null; } @override - Object visitFunctionTypeAlias(FunctionTypeAlias node) { + void visitFunctionTypeAlias(FunctionTypeAlias node) { resolveMetadata(node); - return null; } @override - Object visitFunctionTypedFormalParameter(FunctionTypedFormalParameter node) { + void visitFunctionTypedFormalParameter(FunctionTypedFormalParameter node) { _resolveMetadataForParameter(node); - return null; } @override - Object visitImportDirective(ImportDirective node) { + void visitImportDirective(ImportDirective node) { SimpleIdentifier prefixNode = node.prefix; if (prefixNode != null) { String prefixName = prefixNode.name; @@ -456,11 +437,10 @@ } resolveMetadata(node); } - return null; } @override - Object visitIndexExpression(IndexExpression node) { + void visitIndexExpression(IndexExpression node) { Expression target = node.realTarget; DartType staticType = _getStaticType(target); String getterMethodName = TokenType.INDEX.lexeme; @@ -475,7 +455,7 @@ node.staticElement = setterStaticMethod; // generate undefined method warning _checkForUndefinedIndexOperator( - node, target, getterMethodName, setterStaticMethod, staticType); + node, target, setterMethodName, setterStaticMethod, staticType); // lookup getter method MethodElement getterStaticMethod = _lookUpMethod(target, staticType, getterMethodName); @@ -505,11 +485,10 @@ _checkForUndefinedIndexOperator( node, target, setterMethodName, staticMethod, staticType); } - return null; } @override - Object visitInstanceCreationExpression(InstanceCreationExpression node) { + void visitInstanceCreationExpression(InstanceCreationExpression node) { ConstructorElement invokedConstructor = node.constructorName.staticElement; node.staticElement = invokedConstructor; ArgumentList argumentList = node.argumentList; @@ -520,246 +499,35 @@ if (parameters != null) { argumentList.correspondingStaticParameters = parameters; } - return null; } @override - Object visitLibraryDirective(LibraryDirective node) { + void visitLibraryDirective(LibraryDirective node) { resolveMetadata(node); - return null; } @override - Object visitMethodDeclaration(MethodDeclaration node) { + void visitMethodDeclaration(MethodDeclaration node) { resolveMetadata(node); - return null; } @override - Object visitMethodInvocation(MethodInvocation node) { - SimpleIdentifier methodName = node.methodName; - // - // Synthetic identifiers have been already reported during parsing. - // - if (methodName.isSynthetic) { - return null; - } - // - // We have a method invocation of one of two forms: 'e.m(a1, ..., an)' or - // 'm(a1, ..., an)'. The first step is to figure out which executable is - // being invoked, using both the static and the propagated type information. - // - Expression target = node.realTarget; - if (target is SuperExpression && !_isSuperInValidContext(target)) { - return null; - } - Element staticElement; - if (target == null) { - staticElement = _resolveInvokedElement(methodName); - } else if (methodName.name == FunctionElement.LOAD_LIBRARY_NAME && - _isDeferredPrefix(target)) { - if (node.operator.type == TokenType.QUESTION_PERIOD) { - _resolver.errorReporter.reportErrorForNode( - CompileTimeErrorCode.PREFIX_IDENTIFIER_NOT_FOLLOWED_BY_DOT, - target, - [(target as SimpleIdentifier).name]); - } - LibraryElement importedLibrary = _getImportedLibrary(target); - FunctionElement loadLibraryFunction = - importedLibrary?.loadLibraryFunction; - methodName.staticElement = loadLibraryFunction; - node.staticInvokeType = loadLibraryFunction?.type; - return null; - } else { - // - // If this method invocation is of the form 'C.m' where 'C' is a class, - // then we don't call resolveInvokedElement(...) which walks up the class - // hierarchy, instead we just look for the member in the type only. This - // does not apply to conditional method invocation (i.e. 'C?.m(...)'). - // - bool isConditional = node.operator.type == TokenType.QUESTION_PERIOD; - ClassElement typeReference = getTypeReference(target); - - if (typeReference != null) { - if (node.isCascaded) { - typeReference = _typeType.element; - } - staticElement = _resolveElement(typeReference, methodName); - } else { - DartType staticType = _getStaticTypeOrFunctionType(target); - - if (staticType is FunctionType && - methodName.name == FunctionElement.CALL_METHOD_NAME) { - if (target is SimpleIdentifier) { - methodName.staticElement = target.staticElement; - } - methodName.staticType = target.staticType; - node.staticType = staticType; - node.staticInvokeType = staticType; - node.argumentList.correspondingStaticParameters = - _computeCorrespondingParameters(node.argumentList, staticType); - return null; - } - - if (target is SuperExpression) { - if (staticType is InterfaceTypeImpl) { - staticElement = staticType.lookUpInheritedMember( - methodName.name, _definingLibrary, - concrete: true, forSuperInvocation: true); - // We were not able to find the concrete dispatch target. - // But we would like to give the user at least some resolution. - // So, we retry without the "concrete" requirement. - if (staticElement == null) { - staticElement = staticType.lookUpInheritedMember( - methodName.name, _definingLibrary, - concrete: false); - if (staticElement != null) { - _resolver.errorReporter.reportErrorForNode( - CompileTimeErrorCode.ABSTRACT_SUPER_MEMBER_REFERENCE, - methodName, - [staticElement.kind.displayName, methodName.name]); - } - } - } - } else { - staticElement = _resolveInvokedElementWithTarget( - target, staticType, methodName, isConditional); - } - } - } - - staticElement = _convertSetterToGetter(staticElement); - - // - // Given the elements, determine the type of the function we are invoking - // - DartType staticType = _getInvokeType(staticElement); - methodName.staticType = staticType; - - // - // Instantiate generic function or method if needed. - // - DartType staticInvokeType = _instantiateGenericMethod( - staticType, node.typeArguments, node.methodName); - - // - // Record the results. - // - methodName.staticElement = staticElement; - node.staticInvokeType = staticInvokeType; - ArgumentList argumentList = node.argumentList; - if (staticInvokeType != null) { - List<ParameterElement> parameters = - _computeCorrespondingParameters(argumentList, staticInvokeType); - argumentList.correspondingStaticParameters = parameters; - } - // - // Then check for error conditions. - // - ErrorCode errorCode = _checkForInvocationError( - target, true, staticElement, staticType, methodName.name); - if (errorCode != null && - target is SimpleIdentifier && - target.staticElement is PrefixElement) { - Identifier functionName = - new PrefixedIdentifierImpl.temp(target, methodName); - if (_resolver.nameScope.shouldIgnoreUndefined(functionName)) { - return null; - } - } - if (errorCode == null) { - return null; - } - - if (identical( - errorCode, StaticTypeWarningCode.INVOCATION_OF_NON_FUNCTION) || - identical(errorCode, - CompileTimeErrorCode.PREFIX_IDENTIFIER_NOT_FOLLOWED_BY_DOT) || - identical(errorCode, StaticTypeWarningCode.UNDEFINED_FUNCTION)) { - if (!_resolver.nameScope.shouldIgnoreUndefined(methodName)) { - _resolver.errorReporter - .reportErrorForNode(errorCode, methodName, [methodName.name]); - } - } else if (identical(errorCode, StaticTypeWarningCode.UNDEFINED_METHOD)) { - String targetTypeName; - if (target == null) { - ClassElement enclosingClass = _resolver.enclosingClass; - targetTypeName = enclosingClass.displayName; - ErrorCode proxyErrorCode = StaticTypeWarningCode.UNDEFINED_METHOD; - _recordUndefinedNode(_resolver.enclosingClass, proxyErrorCode, - methodName, [methodName.name, targetTypeName]); - } else { - // ignore Function "call" - // (if we are about to create a hint using type propagation, - // then we can use type propagation here as well) - DartType targetType = null; - targetType = _getStaticType(target); - if (targetType != null && - targetType.isDartCoreFunction && - methodName.name == FunctionElement.CALL_METHOD_NAME) { - return null; - } - if (!node.isCascaded) { - ClassElement typeReference = getTypeReference(target); - if (typeReference != null) { - ConstructorElement constructor = - typeReference.getNamedConstructor(methodName.name); - if (constructor != null) { - _recordUndefinedNode( - typeReference, - StaticTypeWarningCode.UNDEFINED_METHOD_WITH_CONSTRUCTOR, - methodName, - [methodName.name, typeReference.name]); - return null; - } - } - } - - targetTypeName = targetType?.displayName; - ErrorCode proxyErrorCode = StaticTypeWarningCode.UNDEFINED_METHOD; - - _recordUndefinedNode(targetType.element, proxyErrorCode, methodName, - [methodName.name, targetTypeName]); - } - } else if (identical( - errorCode, StaticTypeWarningCode.UNDEFINED_SUPER_METHOD)) { - // Generate the type name. - // The error code will never be generated via type propagation - DartType getSuperType(DartType type) { - if (type is InterfaceType) { - InterfaceType superclass = type.superclass; - if (superclass != null) return superclass; - } - return type; - } - - DartType targetType = getSuperType(_getStaticType(target)); - String targetTypeName = targetType?.name; - _resolver.errorReporter.reportErrorForNode( - StaticTypeWarningCode.UNDEFINED_SUPER_METHOD, - methodName, - [methodName.name, targetTypeName]); - } else if (identical(errorCode, StaticWarningCode.USE_OF_VOID_RESULT)) { - _resolver.errorReporter.reportErrorForNode( - StaticWarningCode.USE_OF_VOID_RESULT, target ?? methodName, []); - } - return null; + void visitMethodInvocation(MethodInvocation node) { + _methodInvocationResolver.resolve(node); } @override - Object visitMixinDeclaration(MixinDeclaration node) { + void visitMixinDeclaration(MixinDeclaration node) { resolveMetadata(node); - return null; } @override - Object visitPartDirective(PartDirective node) { + void visitPartDirective(PartDirective node) { resolveMetadata(node); - return null; } @override - Object visitPostfixExpression(PostfixExpression node) { + void visitPostfixExpression(PostfixExpression node) { Expression operand = node.operand; String methodName = _getPostfixOperator(node); DartType staticType = _getStaticType(operand); @@ -780,11 +548,10 @@ [methodName, staticType.displayName]); } } - return null; } @override - Object visitPrefixedIdentifier(PrefixedIdentifier node) { + void visitPrefixedIdentifier(PrefixedIdentifier node) { SimpleIdentifier prefix = node.prefix; SimpleIdentifier identifier = node.identifier; // @@ -794,7 +561,7 @@ _isDeferredPrefix(prefix)) { LibraryElement importedLibrary = _getImportedLibrary(prefix); identifier.staticElement = importedLibrary?.loadLibraryFunction; - return null; + return; } // // Check to see whether the prefix is really a prefix. @@ -810,7 +577,7 @@ element = _resolver.nameScope.lookup(setterName, _definingLibrary); } if (element == null && _resolver.nameScope.shouldIgnoreUndefined(node)) { - return null; + return; } if (element == null) { if (identifier.inSetterContext()) { @@ -818,7 +585,7 @@ StaticTypeWarningCode.UNDEFINED_SETTER, identifier, [identifier.name, prefixElement.name]); - return null; + return; } AstNode parent = node.parent; if (parent is Annotation) { @@ -832,7 +599,7 @@ identifier, [identifier.name, prefixElement.name]); } - return null; + return; } Element accessor = element; if (accessor is PropertyAccessorElement && identifier.inSetterContext()) { @@ -852,7 +619,7 @@ if (parent is Annotation) { _resolveAnnotationElement(parent); } - return null; + return; } // May be annotation, resolve invocation of "const" constructor. AstNode parent = node.parent; @@ -864,11 +631,10 @@ // identifier and this is really equivalent to a property access node. // _resolvePropertyAccess(prefix, identifier, false); - return null; } @override - Object visitPrefixExpression(PrefixExpression node) { + void visitPrefixExpression(PrefixExpression node) { Token operator = node.operator; TokenType operatorType = operator.type; if (operatorType.isUserDefinableOperator || @@ -896,27 +662,25 @@ } } } - return null; } @override - Object visitPropertyAccess(PropertyAccess node) { + void visitPropertyAccess(PropertyAccess node) { Expression target = node.realTarget; if (target is SuperExpression && !_isSuperInValidContext(target)) { - return null; + return; } SimpleIdentifier propertyName = node.propertyName; _resolvePropertyAccess(target, propertyName, node.isCascaded); - return null; } @override - Object visitRedirectingConstructorInvocation( + void visitRedirectingConstructorInvocation( RedirectingConstructorInvocation node) { ClassElement enclosingClass = _resolver.enclosingClass; if (enclosingClass == null) { // TODO(brianwilkerson) Report this error. - return null; + return; } SimpleIdentifier name = node.constructorName; ConstructorElement element; @@ -928,7 +692,7 @@ if (element == null) { // TODO(brianwilkerson) Report this error and decide what element to // associate with the node. - return null; + return; } if (name != null) { name.staticElement = element; @@ -940,41 +704,39 @@ if (parameters != null) { argumentList.correspondingStaticParameters = parameters; } - return null; } @override - Object visitSimpleFormalParameter(SimpleFormalParameter node) { + void visitSimpleFormalParameter(SimpleFormalParameter node) { _resolveMetadataForParameter(node); - return null; } @override - Object visitSimpleIdentifier(SimpleIdentifier node) { + void visitSimpleIdentifier(SimpleIdentifier node) { // // Synthetic identifiers have been already reported during parsing. // if (node.isSynthetic) { - return null; + return; } // // Ignore nodes that should have been resolved before getting here. // if (node.inDeclarationContext()) { - return null; + return; } if (node.staticElement is LocalVariableElement || node.staticElement is ParameterElement) { - return null; + return; } AstNode parent = node.parent; if (parent is FieldFormalParameter) { - return null; + return; } else if (parent is ConstructorFieldInitializer && parent.fieldName == node) { - return null; + return; } else if (parent is Annotation && parent.constructorName == node) { - return null; + return; } // // The name dynamic denotes a Type object even though dynamic is not a @@ -983,7 +745,7 @@ if (node.name == _dynamicType.name) { node.staticElement = _dynamicType.element; node.staticType = _typeType; - return null; + return; } // // Otherwise, the node should be resolved. @@ -1039,21 +801,20 @@ if (parent is Annotation) { _resolveAnnotationElement(parent); } - return null; } @override - Object visitSuperConstructorInvocation(SuperConstructorInvocation node) { + void visitSuperConstructorInvocation(SuperConstructorInvocation node) { ClassElementImpl enclosingClass = AbstractClassElementImpl.getImpl(_resolver.enclosingClass); if (enclosingClass == null) { // TODO(brianwilkerson) Report this error. - return null; + return; } InterfaceType superType = enclosingClass.supertype; if (superType == null) { // TODO(brianwilkerson) Report this error. - return null; + return; } SimpleIdentifier name = node.constructorName; String superName = name?.name; @@ -1071,7 +832,7 @@ node, [superType.displayName]); } - return null; + return; } else { if (element.isFactory) { _resolver.errorReporter.reportErrorForNode( @@ -1085,11 +846,11 @@ // TODO(brianwilkerson) Defer this check until we know there's an error (by // in-lining _resolveArgumentsToFunction below). ClassDeclaration declaration = - node.getAncestor((AstNode node) => node is ClassDeclaration); + node.thisOrAncestorOfType<ClassDeclaration>(); Identifier superclassName = declaration.extendsClause?.superclass?.name; if (superclassName != null && _resolver.nameScope.shouldIgnoreUndefined(superclassName)) { - return null; + return; } ArgumentList argumentList = node.argumentList; List<ParameterElement> parameters = _resolveArgumentsToFunction( @@ -1097,121 +858,25 @@ if (parameters != null) { argumentList.correspondingStaticParameters = parameters; } - return null; } @override - Object visitSuperExpression(SuperExpression node) { + void visitSuperExpression(SuperExpression node) { if (!_isSuperInValidContext(node)) { _resolver.errorReporter.reportErrorForNode( CompileTimeErrorCode.SUPER_IN_INVALID_CONTEXT, node); } - return super.visitSuperExpression(node); + super.visitSuperExpression(node); } @override - Object visitTypeParameter(TypeParameter node) { + void visitTypeParameter(TypeParameter node) { resolveMetadata(node); - return null; } @override - Object visitVariableDeclaration(VariableDeclaration node) { + void visitVariableDeclaration(VariableDeclaration node) { resolveMetadata(node); - return null; - } - - /** - * Given that we have found code to invoke the given [element], return the - * error code that should be reported, or `null` if no error should be - * reported. The [target] is the target of the invocation, or `null` if there - * was no target. The flag [useStaticContext] should be `true` if the - * invocation is in a static constant (does not have access to instance state). - */ - ErrorCode _checkForInvocationError(Expression target, bool useStaticContext, - Element element, DartType type, String name) { - // Prefix is not declared, instead "prefix.id" are declared. - if (element is PrefixElement) { - return CompileTimeErrorCode.PREFIX_IDENTIFIER_NOT_FOLLOWED_BY_DOT; - } else if (element is PropertyAccessorElement) { - // - // This is really a function expression invocation. - // - // TODO(brianwilkerson) Consider the possibility of re-writing the AST. - FunctionType getterType = element.type; - if (getterType != null) { - DartType returnType = getterType.returnType; - return _getErrorCodeForExecuting(returnType); - } - } else if (element is ExecutableElement) { - return null; - } else if (element is MultiplyDefinedElement) { - // The error has already been reported - return null; - } else if (element == null && target is SuperExpression) { - // TODO(jwren) We should split the UNDEFINED_METHOD into two error codes, - // this one, and a code that describes the situation where the method was - // found, but it was not accessible from the current library. - return StaticTypeWarningCode.UNDEFINED_SUPER_METHOD; - } else { - // - // This is really a function expression invocation. - // - // TODO(brianwilkerson) Consider the possibility of re-writing the AST. - if (element is PropertyInducingElement) { - PropertyAccessorElement getter = element.getter; - FunctionType getterType = getter.type; - if (getterType != null) { - DartType returnType = getterType.returnType; - return _getErrorCodeForExecuting(returnType); - } - } else if (element is VariableElement) { - return _getErrorCodeForExecuting(type); - } else { - if (target == null) { - ClassElement enclosingClass = _resolver.enclosingClass; - if (enclosingClass == null) { - return StaticTypeWarningCode.UNDEFINED_FUNCTION; - } else if (element == null) { - // Proxy-conditional warning, based on state of - // resolver.getEnclosingClass() - return StaticTypeWarningCode.UNDEFINED_METHOD; - } else { - return StaticTypeWarningCode.INVOCATION_OF_NON_FUNCTION; - } - } else { - DartType targetType; - if (useStaticContext) { - targetType = _getStaticType(target); - } else { - // Compute and use the propagated type, if it is null, then it may - // be the case that static type is some type, in which the static - // type should be used. - targetType = _getBestType(target); - } - if (targetType == null) { - if (target is Identifier && - _resolver.nameScope.shouldIgnoreUndefined(target)) { - return null; - } - return StaticTypeWarningCode.UNDEFINED_FUNCTION; - } else if (targetType.isVoid) { - return StaticWarningCode.USE_OF_VOID_RESULT; - } else if (!targetType.isDynamic && target is! NullLiteral) { - // Proxy-conditional warning, based on state of - // targetType.getElement() - return StaticTypeWarningCode.UNDEFINED_METHOD; - } else if (targetType.isDynamic) { - PropertyAccessorElement getter = - _resolver.typeProvider.objectType.getGetter(name); - if (getter != null && getter.returnType is! FunctionType) { - return StaticTypeWarningCode.INVOCATION_OF_NON_FUNCTION; - } - } - } - } - } - return null; } /** @@ -1275,50 +940,6 @@ } /** - * If the given [element] is a setter, return the getter associated with it. - * Otherwise, return the element unchanged. - */ - Element _convertSetterToGetter(Element element) { - // TODO(brianwilkerson) Determine whether and why the element could ever be - // a setter. - if (element is PropertyAccessorElement) { - return element.variable.getter; - } - return element; - } - - /** - * Return the best type of the given [expression] that is to be used for - * type analysis. - */ - DartType _getBestType(Expression expression) { - DartType bestType = _resolveTypeParameter(expression.staticType); - if (bestType is FunctionType) { - // - // All function types are subtypes of 'Function', which is itself a - // subclass of 'Object'. - // - bestType = _resolver.typeProvider.functionType; - } - return bestType; - } - - /** - * Return an error if the [type], which is presumably being invoked, is not a - * function. The errors for non functions may be broken up by type; currently, - * it returns a special value for when the type is `void`. - */ - ErrorCode _getErrorCodeForExecuting(DartType type) { - if (_isExecutableType(type)) { - return null; - } - - return type.isVoid - ? StaticWarningCode.USE_OF_VOID_RESULT - : StaticTypeWarningCode.INVOCATION_OF_NON_FUNCTION; - } - - /** * Assuming that the given [identifier] is a prefix for a deferred import, * return the library that is being imported. */ @@ -1330,28 +951,6 @@ } /** - * Given an element, computes the type of the invocation. - * - * For executable elements (like methods, functions) this is just their type. - * - * For variables it is their type taking into account any type promotion. - * - * For calls to getters in Dart, we invoke the function that is returned by - * the getter, so the invoke type is the getter's returnType. - */ - DartType _getInvokeType(Element element) { - DartType invokeType; - if (element is PropertyAccessorElement) { - invokeType = element.returnType; - } else if (element is ExecutableElement) { - invokeType = element.type; - } else if (element is VariableElement) { - invokeType = _promoteManager.getStaticType(element); - } - return invokeType ?? DynamicTypeImpl.instance; - } - - /** * Return the name of the method invoked by the given postfix [expression]. */ String _getPostfixOperator(PostfixExpression expression) => @@ -1461,25 +1060,6 @@ } /** - * Return `true` if the given [type] represents an object that could be - * invoked using the call operator '()'. - */ - bool _isExecutableType(DartType type) { - type = type?.resolveToBound(_resolver.typeProvider.objectType); - if (type.isDynamic || type is FunctionType) { - return true; - } else if (type.isDartCoreFunction) { - return true; - } else if (type is InterfaceType) { - ClassElement classElement = type.element; - MethodElement methodElement = classElement.lookUpMethod( - FunctionElement.CALL_METHOD_NAME, _definingLibrary); - return methodElement != null; - } - return false; - } - - /** * Return `true` if the given [element] is a static element. */ bool _isStatic(Element element) { @@ -1582,18 +1162,18 @@ /** * Look up the [FunctionType] of a getter or a method with the given [name] - * in the given [targetType]. The [target] is the target of the invocation, - * or `null` if there is no target. + * in the given [targetType]. */ - FunctionType _lookUpGetterType( - Expression target, DartType targetType, String name) { + FunctionType _lookUpGetterType(DartType targetType, String name, + {bool concrete: false, bool forSuper: false}) { targetType = _resolveTypeParameter(targetType); if (targetType is InterfaceType) { var nameObject = new Name(_definingLibrary.source.uri, name); return _inheritance.getMember( targetType, nameObject, - forSuper: target is SuperExpression, + concrete: concrete, + forSuper: forSuper, ); } return null; @@ -1752,8 +1332,7 @@ } // Class(args) if (element1 is ClassElement) { - constructor = new InterfaceTypeImpl(element1) - .lookUpConstructor(null, _definingLibrary); + constructor = element1.type.lookUpConstructor(null, _definingLibrary); } else if (element1 == null) { undefined = true; } @@ -1781,8 +1360,8 @@ } // Class.constructor(args) if (element1 is ClassElement) { - constructor = new InterfaceTypeImpl(element1) - .lookUpConstructor(nameNode2.name, _definingLibrary); + constructor = + element1.type.lookUpConstructor(nameNode2.name, _definingLibrary); nameNode2.staticElement = constructor; } if (element1 == null && element2 == null) { @@ -1807,8 +1386,7 @@ return; } // prefix.Class.constructor(args) - constructor = new InterfaceTypeImpl(element2) - .lookUpConstructor(name3, _definingLibrary); + constructor = element2.type.lookUpConstructor(name3, _definingLibrary); nameNode3.staticElement = constructor; } else if (element2 == null) { undefined = true; @@ -1894,12 +1472,14 @@ Expression leftOperand = node.leftOperand; if (leftOperand != null) { DartType leftType = _getStaticType(leftOperand); - var invokeType = _lookUpGetterType(leftOperand, leftType, methodName); + var isSuper = leftOperand is SuperExpression; + var invokeType = _lookUpGetterType(leftType, methodName, + concrete: isSuper, forSuper: isSuper); var invokeElement = invokeType?.element; node.staticElement = invokeElement; node.staticInvokeType = invokeType; if (_shouldReportMissingMember(leftType, invokeElement)) { - if (leftOperand is SuperExpression) { + if (isSuper) { _recordUndefinedToken( leftType.element, StaticTypeWarningCode.UNDEFINED_SUPER_OPERATOR, @@ -1978,103 +1558,6 @@ } /** - * Given an invocation of the form 'm(a1, ..., an)', resolve 'm' to the - * element being invoked. If the returned element is a method, then the method - * will be invoked. If the returned element is a getter, the getter will be - * invoked without arguments and the result of that invocation will then be - * invoked with the arguments. The [methodName] is the name of the method - * being invoked ('m'). - */ - Element _resolveInvokedElement(SimpleIdentifier methodName) { - // - // Look first in the lexical scope. - // - Element element = _resolver.nameScope.lookup(methodName, _definingLibrary); - if (element == null) { - // - // If it isn't defined in the lexical scope, and the invocation is within - // a class, then look in the inheritance scope. - // - ClassElement enclosingClass = _resolver.enclosingClass; - if (enclosingClass != null) { - InterfaceType enclosingType = enclosingClass.type; - element = _lookUpMethod(null, enclosingType, methodName.name); - if (element == null) { - // - // If there's no method, then it's possible that 'm' is a getter that - // returns a function. - // - element = _lookUpGetter(null, enclosingType, methodName.name); - } - } - } - // TODO(brianwilkerson) Report this error. - return element; - } - - /** - * Given an invocation of the form 'e.m(a1, ..., an)', resolve 'e.m' to the - * element being invoked. If the returned element is a method, then the method - * will be invoked. If the returned element is a getter, the getter will be - * invoked without arguments and the result of that invocation will then be - * invoked with the arguments. The [target] is the target of the invocation - * ('e'). The [targetType] is the type of the target. The [methodName] is th - * name of the method being invoked ('m'). [isConditional] indicates - * whether the invocation uses a '?.' operator. - */ - Element _resolveInvokedElementWithTarget(Expression target, - DartType targetType, SimpleIdentifier methodName, bool isConditional) { - String name = methodName.name; - if (targetType is InterfaceType) { - Element element = _lookUpMethod(target, targetType, name); - if (element == null) { - // - // If there's no method, then it's possible that 'm' is a getter that - // returns a function. - // - // TODO (collinsn): need to add union type support here too, in the - // style of [lookUpMethod]. - element = _lookUpGetter(target, targetType, name); - } - return element; - } else if (targetType is FunctionType && - _resolver.typeProvider.isObjectMethod(name)) { - return _resolver.typeProvider.objectType.element.getMethod(name); - } else if (target is SimpleIdentifier) { - Element targetElement = target.staticElement; - if (targetType is FunctionType && - name == FunctionElement.CALL_METHOD_NAME) { - return targetElement; - } - if (targetElement is PrefixElement) { - if (isConditional) { - _resolver.errorReporter.reportErrorForNode( - CompileTimeErrorCode.PREFIX_IDENTIFIER_NOT_FOLLOWED_BY_DOT, - target, - [target.name]); - } - // - // Look to see whether the name of the method is really part of a - // prefixed identifier for an imported top-level function or top-level - // getter that returns a function. - // - Identifier functionName = - new PrefixedIdentifierImpl.temp(target, methodName); - Element element = - _resolver.nameScope.lookup(functionName, _definingLibrary); - if (element != null) { - // TODO(brianwilkerson) This isn't a method invocation, it's a - // function invocation where the function name is a prefixed - // identifier. Consider re-writing the AST. - return element; - } - } - } - // TODO(brianwilkerson) Report this error. - return null; - } - - /** * Given a [node] that can have annotations associated with it, resolve the * annotations in the element model representing annotations to the node. */ @@ -2134,10 +1617,16 @@ propertyName.name, _definingLibrary, setter: propertyName.inSetterContext(), concrete: false); if (staticElement != null) { - _resolver.errorReporter.reportErrorForNode( - CompileTimeErrorCode.ABSTRACT_SUPER_MEMBER_REFERENCE, - propertyName, - [staticElement.kind.displayName, propertyName.name]); + ClassElementImpl receiverSuperClass = + AbstractClassElementImpl.getImpl( + staticType.element.supertype.element, + ); + if (!receiverSuperClass.hasNoSuchMethod) { + _resolver.errorReporter.reportErrorForNode( + CompileTimeErrorCode.ABSTRACT_SUPER_MEMBER_REFERENCE, + propertyName, + [staticElement.kind.displayName, propertyName.name]); + } } } }
diff --git a/pkg/analyzer/lib/src/generated/engine.dart b/pkg/analyzer/lib/src/generated/engine.dart index 91e3739..f4d63dc 100644 --- a/pkg/analyzer/lib/src/generated/engine.dart +++ b/pkg/analyzer/lib/src/generated/engine.dart
@@ -1,4 +1,4 @@ -// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file +// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. @@ -40,6 +40,7 @@ import 'package:path/path.dart' as pathos; import 'package:plugin/manager.dart'; import 'package:plugin/plugin.dart'; +import 'package:pub_semver/pub_semver.dart'; export 'package:analyzer/error/listener.dart' show RecordingErrorListener; export 'package:analyzer/src/generated/timestamped_data.dart' @@ -1147,10 +1148,10 @@ AnalyzeFunctionBodiesPredicate get analyzeFunctionBodiesPredicate; /** - * DEPRECATED: Return the maximum number of sources for which AST structures should be + * Return the maximum number of sources for which AST structures should be * kept in the cache. * - * This setting no longer has any effect. + * DEPRECATED: This setting no longer has any effect. */ @deprecated int get cacheSize; @@ -1197,6 +1198,15 @@ bool get enableConditionalDirectives; /** + * Return a list containing the names of the experiments that are enabled in + * the context associated with these options. + * + * The process around these experiments is described in this + * [doc](https://github.com/dart-lang/sdk/blob/master/docs/process/experimental-flags.md). + */ + List<String> get enabledExperiments; + + /** * Return a list of the names of the packages for which, if they define a * plugin, the plugin should be enabled. */ @@ -1301,6 +1311,12 @@ bool get previewDart2; /** + * The version range for the SDK specified in `pubspec.yaml`, or `null` if + * there is no `pubspec.yaml` or if it does not contain an SDK range. + */ + VersionConstraint get sdkVersionConstraint; + + /** * Return the opaque signature of the options. * * The length of the list is guaranteed to equal [signatureLength]. @@ -1338,6 +1354,7 @@ * Set the values of the cross-context options to match those in the given set * of [options]. */ + @deprecated void setCrossContextOptionsFrom(AnalysisOptions options); /** @@ -1394,13 +1411,8 @@ */ Uint32List _signature; - /** - * A flag indicating whether declaration casts are allowed in [strongMode] - * (they are always allowed in Dart 1.0 mode). - * - * This option is deprecated and will be removed in a future release. - */ - bool declarationCasts = true; + @override + VersionConstraint sdkVersionConstraint; @override @deprecated @@ -1410,6 +1422,9 @@ bool dart2jsHint = false; @override + List<String> enabledExperiments = const <String>[]; + + @override List<String> enabledPluginNames = const <String>[]; @override @@ -1489,13 +1504,6 @@ */ bool implicitDynamic = true; - // A no-op setter. - /** - * Return `true` to enable mixin declarations. - * https://github.com/dart-lang/language/issues/12 - */ - bool isMixinSupportEnabled = false; - /** * Initialize a newly created set of analysis options to have their default * values. @@ -1509,6 +1517,7 @@ AnalysisOptionsImpl.from(AnalysisOptions options) { analyzeFunctionBodiesPredicate = options.analyzeFunctionBodiesPredicate; dart2jsHint = options.dart2jsHint; + enabledExperiments = options.enabledExperiments; enabledPluginNames = options.enabledPluginNames; enableLazyAssignmentOperators = options.enableLazyAssignmentOperators; enableTiming = options.enableTiming; @@ -1522,15 +1531,14 @@ preserveComments = options.preserveComments; useFastaParser = options.useFastaParser; if (options is AnalysisOptionsImpl) { - declarationCasts = options.declarationCasts; strongModeHints = options.strongModeHints; implicitCasts = options.implicitCasts; implicitDynamic = options.implicitDynamic; - isMixinSupportEnabled = options.isMixinSupportEnabled; } trackCacheDependencies = options.trackCacheDependencies; disableCacheFlushing = options.disableCacheFlushing; patchPaths = options.patchPaths; + sdkVersionConstraint = options.sdkVersionConstraint; } bool get analyzeFunctionBodies { @@ -1645,6 +1653,16 @@ _excludePatterns = patterns; } + /** + * Return `true` to enable mixin declarations. + * https://github.com/dart-lang/language/issues/12 + */ + @deprecated + bool get isMixinSupportEnabled => true; + + @deprecated + set isMixinSupportEnabled(bool value) {} + @override List<Linter> get lintRules => _lintRules ??= const <Linter>[]; @@ -1656,9 +1674,11 @@ _lintRules = rules; } + @deprecated @override bool get previewDart2 => true; + @deprecated set previewDart2(bool value) {} @override @@ -1666,15 +1686,23 @@ if (_signature == null) { ApiSignature buffer = new ApiSignature(); + // Append environment. + if (sdkVersionConstraint != null) { + buffer.addString(sdkVersionConstraint.toString()); + } + // Append boolean flags. - buffer.addBool(declarationCasts); buffer.addBool(enableLazyAssignmentOperators); buffer.addBool(implicitCasts); buffer.addBool(implicitDynamic); buffer.addBool(strongModeHints); buffer.addBool(useFastaParser); - buffer.addBool(previewDart2); - buffer.addBool(isMixinSupportEnabled); + + // Append enabled experiments. + buffer.addInt(enabledExperiments.length); + for (String experimentName in enabledExperiments) { + buffer.addString(experimentName); + } // Append error processors. buffer.addInt(errorProcessors.length); @@ -1730,9 +1758,9 @@ @override void resetToDefaults() { - declarationCasts = true; dart2jsHint = false; disableCacheFlushing = false; + enabledExperiments = const <String>[]; enabledPluginNames = const <String>[]; enableLazyAssignmentOperators = false; enableTiming = false; @@ -1749,9 +1777,10 @@ preserveComments = true; strongModeHints = false; trackCacheDependencies = true; - useFastaParser = false; + useFastaParser = true; } + @deprecated @override void setCrossContextOptionsFrom(AnalysisOptions options) { enableLazyAssignmentOperators = options.enableLazyAssignmentOperators; @@ -2686,7 +2715,7 @@ * An visitor that removes any resolution information from an AST structure when * used to visit that structure. */ -class ResolutionEraser extends GeneralizingAstVisitor<Object> { +class ResolutionEraser extends GeneralizingAstVisitor<void> { /** * A flag indicating whether the elements associated with declarations should * be erased. @@ -2694,122 +2723,122 @@ bool eraseDeclarations = true; @override - Object visitAssignmentExpression(AssignmentExpression node) { + void visitAssignmentExpression(AssignmentExpression node) { node.staticElement = null; - return super.visitAssignmentExpression(node); + super.visitAssignmentExpression(node); } @override - Object visitBinaryExpression(BinaryExpression node) { + void visitBinaryExpression(BinaryExpression node) { node.staticElement = null; - return super.visitBinaryExpression(node); + super.visitBinaryExpression(node); } @override - Object visitBreakStatement(BreakStatement node) { + void visitBreakStatement(BreakStatement node) { node.target = null; - return super.visitBreakStatement(node); + super.visitBreakStatement(node); } @override - Object visitCompilationUnit(CompilationUnit node) { + void visitCompilationUnit(CompilationUnit node) { if (eraseDeclarations) { node.element = null; } - return super.visitCompilationUnit(node); + super.visitCompilationUnit(node); } @override - Object visitConstructorDeclaration(ConstructorDeclaration node) { + void visitConstructorDeclaration(ConstructorDeclaration node) { if (eraseDeclarations) { node.element = null; } - return super.visitConstructorDeclaration(node); + super.visitConstructorDeclaration(node); } @override - Object visitConstructorName(ConstructorName node) { + void visitConstructorName(ConstructorName node) { node.staticElement = null; - return super.visitConstructorName(node); + super.visitConstructorName(node); } @override - Object visitContinueStatement(ContinueStatement node) { + void visitContinueStatement(ContinueStatement node) { node.target = null; - return super.visitContinueStatement(node); + super.visitContinueStatement(node); } @override - Object visitDirective(Directive node) { + void visitDirective(Directive node) { if (eraseDeclarations) { node.element = null; } - return super.visitDirective(node); + super.visitDirective(node); } @override - Object visitExpression(Expression node) { + void visitExpression(Expression node) { node.staticType = null; - return super.visitExpression(node); + super.visitExpression(node); } @override - Object visitFunctionExpression(FunctionExpression node) { + void visitFunctionExpression(FunctionExpression node) { if (eraseDeclarations) { node.element = null; } - return super.visitFunctionExpression(node); + super.visitFunctionExpression(node); } @override - Object visitFunctionExpressionInvocation(FunctionExpressionInvocation node) { + void visitFunctionExpressionInvocation(FunctionExpressionInvocation node) { node.staticElement = null; - return super.visitFunctionExpressionInvocation(node); + super.visitFunctionExpressionInvocation(node); } @override - Object visitIndexExpression(IndexExpression node) { + void visitIndexExpression(IndexExpression node) { node.staticElement = null; - return super.visitIndexExpression(node); + super.visitIndexExpression(node); } @override - Object visitInstanceCreationExpression(InstanceCreationExpression node) { + void visitInstanceCreationExpression(InstanceCreationExpression node) { node.staticElement = null; - return super.visitInstanceCreationExpression(node); + super.visitInstanceCreationExpression(node); } @override - Object visitPostfixExpression(PostfixExpression node) { + void visitPostfixExpression(PostfixExpression node) { node.staticElement = null; - return super.visitPostfixExpression(node); + super.visitPostfixExpression(node); } @override - Object visitPrefixExpression(PrefixExpression node) { + void visitPrefixExpression(PrefixExpression node) { node.staticElement = null; - return super.visitPrefixExpression(node); + super.visitPrefixExpression(node); } @override - Object visitRedirectingConstructorInvocation( + void visitRedirectingConstructorInvocation( RedirectingConstructorInvocation node) { node.staticElement = null; - return super.visitRedirectingConstructorInvocation(node); + super.visitRedirectingConstructorInvocation(node); } @override - Object visitSimpleIdentifier(SimpleIdentifier node) { + void visitSimpleIdentifier(SimpleIdentifier node) { if (eraseDeclarations || !node.inDeclarationContext()) { node.staticElement = null; } - return super.visitSimpleIdentifier(node); + super.visitSimpleIdentifier(node); } @override - Object visitSuperConstructorInvocation(SuperConstructorInvocation node) { + void visitSuperConstructorInvocation(SuperConstructorInvocation node) { node.staticElement = null; - return super.visitSuperConstructorInvocation(node); + super.visitSuperConstructorInvocation(node); } /**
diff --git a/pkg/analyzer/lib/src/generated/error_verifier.dart b/pkg/analyzer/lib/src/generated/error_verifier.dart index 207515d..5ca19f8 100644 --- a/pkg/analyzer/lib/src/generated/error_verifier.dart +++ b/pkg/analyzer/lib/src/generated/error_verifier.dart
@@ -1,4 +1,4 @@ -// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file +// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. @@ -34,7 +34,7 @@ * A visitor used to traverse an AST structure looking for additional errors and * warnings not covered by the parser and resolver. */ -class ErrorVerifier extends RecursiveAstVisitor<Object> { +class ErrorVerifier extends RecursiveAstVisitor<void> { /** * The error reporter by which errors will be reported. */ @@ -328,38 +328,38 @@ } @override - Object visitAnnotation(Annotation node) { + void visitAnnotation(Annotation node) { _checkForInvalidAnnotationFromDeferredLibrary(node); _checkForMissingJSLibAnnotation(node); - return super.visitAnnotation(node); + super.visitAnnotation(node); } @override - Object visitArgumentList(ArgumentList node) { + void visitArgumentList(ArgumentList node) { _checkForArgumentTypesNotAssignableInList(node); - return super.visitArgumentList(node); + super.visitArgumentList(node); } @override - Object visitAsExpression(AsExpression node) { + void visitAsExpression(AsExpression node) { _checkForTypeAnnotationDeferredClass(node.type); - return super.visitAsExpression(node); + super.visitAsExpression(node); } @override - Object visitAssertInitializer(AssertInitializer node) { + void visitAssertInitializer(AssertInitializer node) { _checkForNonBoolExpression(node); - return super.visitAssertInitializer(node); + super.visitAssertInitializer(node); } @override - Object visitAssertStatement(AssertStatement node) { + void visitAssertStatement(AssertStatement node) { _checkForNonBoolExpression(node); - return super.visitAssertStatement(node); + super.visitAssertStatement(node); } @override - Object visitAssignmentExpression(AssignmentExpression node) { + void visitAssignmentExpression(AssignmentExpression node) { TokenType operatorType = node.operator.type; Expression lhs = node.leftHandSide; Expression rhs = node.rightHandSide; @@ -371,20 +371,20 @@ _checkForArgumentTypeNotAssignableForArgument(rhs); } _checkForAssignmentToFinal(lhs); - return super.visitAssignmentExpression(node); + super.visitAssignmentExpression(node); } @override - Object visitAwaitExpression(AwaitExpression node) { + void visitAwaitExpression(AwaitExpression node) { if (!_inAsync) { _errorReporter.reportErrorForToken( CompileTimeErrorCode.AWAIT_IN_WRONG_CONTEXT, node.awaitKeyword); } - return super.visitAwaitExpression(node); + super.visitAwaitExpression(node); } @override - Object visitBinaryExpression(BinaryExpression node) { + void visitBinaryExpression(BinaryExpression node) { Token operator = node.operator; TokenType type = operator.type; if (type == TokenType.AMPERSAND_AMPERSAND || type == TokenType.BAR_BAR) { @@ -398,22 +398,22 @@ _checkForArgumentTypeNotAssignableForArgument(node.rightOperand); } _checkForUseOfVoidResult(node.leftOperand); - return super.visitBinaryExpression(node); + super.visitBinaryExpression(node); } @override - Object visitBlock(Block node) { + void visitBlock(Block node) { _hiddenElements = new HiddenElements(_hiddenElements, node); try { _checkDuplicateDeclarationInStatements(node.statements); - return super.visitBlock(node); + super.visitBlock(node); } finally { _hiddenElements = _hiddenElements.outerElements; } } @override - Object visitBlockFunctionBody(BlockFunctionBody node) { + void visitBlockFunctionBody(BlockFunctionBody node) { bool wasInAsync = _inAsync; bool wasInGenerator = _inGenerator; bool previousHasReturnWithoutValue = _hasReturnWithoutValue; @@ -434,11 +434,10 @@ _returnsWithout = previousReturnsWithout; _hasReturnWithoutValue = previousHasReturnWithoutValue; } - return null; } @override - Object visitBreakStatement(BreakStatement node) { + void visitBreakStatement(BreakStatement node) { SimpleIdentifier labelNode = node.label; if (labelNode != null) { Element labelElement = labelNode.staticElement; @@ -447,24 +446,23 @@ ResolverErrorCode.BREAK_LABEL_ON_SWITCH_MEMBER, labelNode); } } - return null; } @override - Object visitCatchClause(CatchClause node) { + void visitCatchClause(CatchClause node) { _checkDuplicateDefinitionInCatchClause(node); bool previousIsInCatchClause = _isInCatchClause; try { _isInCatchClause = true; _checkForTypeAnnotationDeferredClass(node.exceptionType); - return super.visitCatchClause(node); + super.visitCatchClause(node); } finally { _isInCatchClause = previousIsInCatchClause; } } @override - Object visitClassDeclaration(ClassDeclaration node) { + void visitClassDeclaration(ClassDeclaration node) { ClassElementImpl outerClass = _enclosingClass; try { _isInNativeClass = node.nativeClause != null; @@ -491,7 +489,7 @@ _initializeInitialFieldElementsMap(_enclosingClass.fields); _checkForFinalNotInitializedInClass(members); _checkForBadFunctionUse(node); - return super.visitClassDeclaration(node); + super.visitClassDeclaration(node); } finally { _isInNativeClass = false; _initialFieldElementsMap = null; @@ -500,7 +498,7 @@ } @override - Object visitClassTypeAlias(ClassTypeAlias node) { + void visitClassTypeAlias(ClassTypeAlias node) { _checkForBuiltInIdentifierAsName( node.name, CompileTimeErrorCode.BUILT_IN_IDENTIFIER_AS_TYPEDEF_NAME); ClassElementImpl outerClassElement = _enclosingClass; @@ -511,37 +509,37 @@ } finally { _enclosingClass = outerClassElement; } - return super.visitClassTypeAlias(node); + super.visitClassTypeAlias(node); } @override - Object visitComment(Comment node) { + void visitComment(Comment node) { _isInComment = true; try { - return super.visitComment(node); + super.visitComment(node); } finally { _isInComment = false; } } @override - Object visitCompilationUnit(CompilationUnit node) { + void visitCompilationUnit(CompilationUnit node) { _checkDuplicateUnitMembers(node); _checkForDeferredPrefixCollisions(node); - return super.visitCompilationUnit(node); + super.visitCompilationUnit(node); } @override - Object visitConditionalExpression(ConditionalExpression node) { + void visitConditionalExpression(ConditionalExpression node) { _checkForNonBoolCondition(node.condition); // TODO(mfairhurst) Enable this and get code compliant. //_checkForUseOfVoidResult(node.thenExpression); //_checkForUseOfVoidResult(node.elseExpression); - return super.visitConditionalExpression(node); + super.visitConditionalExpression(node); } @override - Object visitConstructorDeclaration(ConstructorDeclaration node) { + void visitConstructorDeclaration(ConstructorDeclaration node) { ExecutableElement outerFunction = _enclosingFunction; try { ConstructorElement constructorElement = node.declaredElement; @@ -563,7 +561,7 @@ _checkForUndefinedConstructorInInitializerImplicit(node); _checkForRedirectToNonConstConstructor(node, constructorElement); _checkForReturnInGenerativeConstructor(node); - return super.visitConstructorDeclaration(node); + super.visitConstructorDeclaration(node); } finally { _isEnclosingConstructorConst = false; _isInFactory = false; @@ -572,7 +570,7 @@ } @override - Object visitConstructorFieldInitializer(ConstructorFieldInitializer node) { + void visitConstructorFieldInitializer(ConstructorFieldInitializer node) { _isInConstructorInitializer = true; try { SimpleIdentifier fieldName = node.fieldName; @@ -581,14 +579,14 @@ if (staticElement is FieldElement) { _checkForFieldInitializerNotAssignable(node, staticElement); } - return super.visitConstructorFieldInitializer(node); + super.visitConstructorFieldInitializer(node); } finally { _isInConstructorInitializer = false; } } @override - Object visitContinueStatement(ContinueStatement node) { + void visitContinueStatement(ContinueStatement node) { SimpleIdentifier labelNode = node.label; if (labelNode != null) { Element labelElement = labelNode.staticElement; @@ -598,36 +596,35 @@ ResolverErrorCode.CONTINUE_LABEL_ON_SWITCH, labelNode); } } - return null; } @override - Object visitDefaultFormalParameter(DefaultFormalParameter node) { + void visitDefaultFormalParameter(DefaultFormalParameter node) { _checkForInvalidAssignment(node.identifier, node.defaultValue); _checkForDefaultValueInFunctionTypedParameter(node); - return super.visitDefaultFormalParameter(node); + super.visitDefaultFormalParameter(node); } @override - Object visitDoStatement(DoStatement node) { + void visitDoStatement(DoStatement node) { _checkForNonBoolCondition(node.condition); - return super.visitDoStatement(node); + super.visitDoStatement(node); } @override - Object visitEnumDeclaration(EnumDeclaration node) { + void visitEnumDeclaration(EnumDeclaration node) { ClassElement outerEnum = _enclosingEnum; try { _enclosingEnum = node.declaredElement; _checkDuplicateEnumMembers(node); - return super.visitEnumDeclaration(node); + super.visitEnumDeclaration(node); } finally { _enclosingEnum = outerEnum; } } @override - Object visitExportDirective(ExportDirective node) { + void visitExportDirective(ExportDirective node) { ExportElement exportElement = node.element; if (exportElement != null) { LibraryElement exportedLibrary = exportElement.exportedLibrary; @@ -635,11 +632,11 @@ _checkForExportDuplicateLibraryName(node, exportElement, exportedLibrary); _checkForExportInternalLibrary(node, exportElement); } - return super.visitExportDirective(node); + super.visitExportDirective(node); } @override - Object visitExpressionFunctionBody(ExpressionFunctionBody node) { + void visitExpressionFunctionBody(ExpressionFunctionBody node) { bool wasInAsync = _inAsync; bool wasInGenerator = _inGenerator; try { @@ -657,7 +654,7 @@ _checkForReturnOfInvalidType(node.expression, expectedReturnType, isArrowFunction: true); } - return super.visitExpressionFunctionBody(node); + super.visitExpressionFunctionBody(node); } finally { _inAsync = wasInAsync; _inGenerator = wasInGenerator; @@ -665,7 +662,7 @@ } @override - Object visitFieldDeclaration(FieldDeclaration node) { + void visitFieldDeclaration(FieldDeclaration node) { _isInStaticVariableDeclaration = node.isStatic; _isInInstanceVariableDeclaration = !_isInStaticVariableDeclaration; if (_isInInstanceVariableDeclaration) { @@ -676,7 +673,7 @@ } } try { - return super.visitFieldDeclaration(node); + super.visitFieldDeclaration(node); } finally { _isInStaticVariableDeclaration = false; _isInInstanceVariableDeclaration = false; @@ -684,41 +681,41 @@ } @override - Object visitFieldFormalParameter(FieldFormalParameter node) { + void visitFieldFormalParameter(FieldFormalParameter node) { _checkForValidField(node); _checkForConstFormalParameter(node); _checkForPrivateOptionalParameter(node); _checkForFieldInitializingFormalRedirectingConstructor(node); _checkForTypeAnnotationDeferredClass(node.type); - return super.visitFieldFormalParameter(node); + super.visitFieldFormalParameter(node); } @override - Object visitForEachStatement(ForEachStatement node) { + void visitForEachStatement(ForEachStatement node) { _checkForInIterable(node); - return super.visitForEachStatement(node); + super.visitForEachStatement(node); } @override - Object visitFormalParameterList(FormalParameterList node) { + void visitFormalParameterList(FormalParameterList node) { _checkDuplicateDefinitionInParameterList(node); _checkUseOfCovariantInParameters(node); - return super.visitFormalParameterList(node); + super.visitFormalParameterList(node); } @override - Object visitForStatement(ForStatement node) { + void visitForStatement(ForStatement node) { if (node.condition != null) { _checkForNonBoolCondition(node.condition); } if (node.variables != null) { _checkDuplicateVariables(node.variables); } - return super.visitForStatement(node); + super.visitForStatement(node); } @override - Object visitFunctionDeclaration(FunctionDeclaration node) { + void visitFunctionDeclaration(FunctionDeclaration node) { ExecutableElement functionElement = node.declaredElement; if (functionElement != null && functionElement.enclosingElement is! CompilationUnitElement) { @@ -751,31 +748,31 @@ _checkForTypeAnnotationDeferredClass(returnType); _checkForIllegalReturnType(returnType); _checkForImplicitDynamicReturn(node.name, node.declaredElement); - return super.visitFunctionDeclaration(node); + super.visitFunctionDeclaration(node); } finally { _enclosingFunction = outerFunction; } } @override - Object visitFunctionExpression(FunctionExpression node) { + void visitFunctionExpression(FunctionExpression node) { // If this function expression is wrapped in a function declaration, don't // change the enclosingFunction field. if (node.parent is! FunctionDeclaration) { ExecutableElement outerFunction = _enclosingFunction; try { _enclosingFunction = node.declaredElement; - return super.visitFunctionExpression(node); + super.visitFunctionExpression(node); } finally { _enclosingFunction = outerFunction; } } else { - return super.visitFunctionExpression(node); + super.visitFunctionExpression(node); } } @override - Object visitFunctionExpressionInvocation(FunctionExpressionInvocation node) { + void visitFunctionExpressionInvocation(FunctionExpressionInvocation node) { Expression functionExpression = node.function; DartType expressionType = functionExpression.staticType; if (!_checkForUseOfVoidResult(functionExpression) && @@ -787,20 +784,20 @@ _checkTypeArguments(node); } _checkForImplicitDynamicInvoke(node); - return super.visitFunctionExpressionInvocation(node); + super.visitFunctionExpressionInvocation(node); } @override - Object visitFunctionTypeAlias(FunctionTypeAlias node) { + void visitFunctionTypeAlias(FunctionTypeAlias node) { _checkForBuiltInIdentifierAsName( node.name, CompileTimeErrorCode.BUILT_IN_IDENTIFIER_AS_TYPEDEF_NAME); _checkForDefaultValueInFunctionTypeAlias(node); _checkForTypeAliasCannotReferenceItself_function(node); - return super.visitFunctionTypeAlias(node); + super.visitFunctionTypeAlias(node); } @override - Object visitFunctionTypedFormalParameter(FunctionTypedFormalParameter node) { + void visitFunctionTypedFormalParameter(FunctionTypedFormalParameter node) { bool old = _isInFunctionTypedFormalParameter; _isInFunctionTypedFormalParameter = true; try { @@ -828,35 +825,35 @@ node); } - return super.visitFunctionTypedFormalParameter(node); + super.visitFunctionTypedFormalParameter(node); } finally { _isInFunctionTypedFormalParameter = old; } } @override - Object visitGenericTypeAlias(GenericTypeAlias node) { + void visitGenericTypeAlias(GenericTypeAlias node) { if (_hasTypedefSelfReference(node.declaredElement)) { _errorReporter.reportErrorForNode( CompileTimeErrorCode.TYPE_ALIAS_CANNOT_REFERENCE_ITSELF, node); } - return super.visitGenericTypeAlias(node); + super.visitGenericTypeAlias(node); } @override - Object visitIfStatement(IfStatement node) { + void visitIfStatement(IfStatement node) { _checkForNonBoolCondition(node.condition); - return super.visitIfStatement(node); + super.visitIfStatement(node); } @override - Object visitImplementsClause(ImplementsClause node) { + void visitImplementsClause(ImplementsClause node) { node.interfaces.forEach(_checkForImplicitDynamicType); - return super.visitImplementsClause(node); + super.visitImplementsClause(node); } @override - Object visitImportDirective(ImportDirective node) { + void visitImportDirective(ImportDirective node) { ImportElement importElement = node.element; if (node.prefix != null) { _checkForBuiltInIdentifierAsName( @@ -866,17 +863,17 @@ _checkForImportDuplicateLibraryName(node, importElement); _checkForImportInternalLibrary(node, importElement); } - return super.visitImportDirective(node); + super.visitImportDirective(node); } @override - Object visitIndexExpression(IndexExpression node) { + void visitIndexExpression(IndexExpression node) { _checkForArgumentTypeNotAssignableForArgument(node.index); - return super.visitIndexExpression(node); + super.visitIndexExpression(node); } @override - Object visitInstanceCreationExpression(InstanceCreationExpression node) { + void visitInstanceCreationExpression(InstanceCreationExpression node) { bool wasInConstInstanceCreation = _isInConstInstanceCreation; _isInConstInstanceCreation = node.isConst; try { @@ -897,33 +894,33 @@ } } _checkForImplicitDynamicType(typeName); - return super.visitInstanceCreationExpression(node); + super.visitInstanceCreationExpression(node); } finally { _isInConstInstanceCreation = wasInConstInstanceCreation; } } @override - Object visitIntegerLiteral(IntegerLiteral node) { + void visitIntegerLiteral(IntegerLiteral node) { _checkForOutOfRange(node); - return super.visitIntegerLiteral(node); + super.visitIntegerLiteral(node); } @override - Object visitInterpolationExpression(InterpolationExpression node) { + void visitInterpolationExpression(InterpolationExpression node) { _checkForUseOfVoidResult(node.expression); - return super.visitInterpolationExpression(node); + super.visitInterpolationExpression(node); } @override - Object visitIsExpression(IsExpression node) { + void visitIsExpression(IsExpression node) { _checkForTypeAnnotationDeferredClass(node.type); _checkForUseOfVoidResult(node.expression); - return super.visitIsExpression(node); + super.visitIsExpression(node); } @override - Object visitListLiteral(ListLiteral node) { + void visitListLiteral(ListLiteral node) { TypeArgumentList typeArguments = node.typeArguments; if (typeArguments != null) { if (node.isConst) { @@ -938,11 +935,11 @@ _checkForImplicitDynamicTypedLiteral(node); _checkForListElementTypeNotAssignable(node); - return super.visitListLiteral(node); + super.visitListLiteral(node); } @override - Object visitMapLiteral(MapLiteral node) { + void visitMapLiteral(MapLiteral node) { TypeArgumentList typeArguments = node.typeArguments; if (typeArguments != null) { NodeList<TypeAnnotation> arguments = typeArguments.arguments; @@ -957,11 +954,11 @@ _checkForImplicitDynamicTypedLiteral(node); _checkForMapTypeNotAssignable(node); _checkForNonConstMapAsExpressionStatement(node); - return super.visitMapLiteral(node); + super.visitMapLiteral(node); } @override - Object visitMethodDeclaration(MethodDeclaration node) { + void visitMethodDeclaration(MethodDeclaration node) { ExecutableElement previousFunction = _enclosingFunction; try { _isInStaticMethod = node.isStatic; @@ -981,7 +978,7 @@ _checkForIllegalReturnType(returnType); _checkForImplicitDynamicReturn(node, node.declaredElement); _checkForMustCallSuper(node); - return super.visitMethodDeclaration(node); + super.visitMethodDeclaration(node); } finally { _enclosingFunction = previousFunction; _isInStaticMethod = false; @@ -989,7 +986,7 @@ } @override - Object visitMethodInvocation(MethodInvocation node) { + void visitMethodInvocation(MethodInvocation node) { Expression target = node.realTarget; SimpleIdentifier methodName = node.methodName; if (target != null) { @@ -1001,11 +998,11 @@ } _checkTypeArguments(node); _checkForImplicitDynamicInvoke(node); - return super.visitMethodInvocation(node); + super.visitMethodInvocation(node); } @override - Object visitMixinDeclaration(MixinDeclaration node) { + void visitMixinDeclaration(MixinDeclaration node) { // TODO(scheglov) Verify for all mixin errors. ClassElementImpl outerClass = _enclosingClass; try { @@ -1029,7 +1026,7 @@ _initializeInitialFieldElementsMap(_enclosingClass.fields); _checkForFinalNotInitializedInClass(members); // _checkForBadFunctionUse(node); - return super.visitMixinDeclaration(node); + super.visitMixinDeclaration(node); } finally { _initialFieldElementsMap = null; _enclosingClass = outerClass; @@ -1037,31 +1034,31 @@ } @override - Object visitNativeClause(NativeClause node) { + void visitNativeClause(NativeClause node) { // TODO(brianwilkerson) Figure out the right rule for when 'native' is // allowed. if (!_isInSystemLibrary) { _errorReporter.reportErrorForNode( ParserErrorCode.NATIVE_CLAUSE_IN_NON_SDK_CODE, node); } - return super.visitNativeClause(node); + super.visitNativeClause(node); } @override - Object visitNativeFunctionBody(NativeFunctionBody node) { + void visitNativeFunctionBody(NativeFunctionBody node) { _checkForNativeFunctionBodyInNonSdkCode(node); - return super.visitNativeFunctionBody(node); + super.visitNativeFunctionBody(node); } @override - Object visitPostfixExpression(PostfixExpression node) { + void visitPostfixExpression(PostfixExpression node) { _checkForAssignmentToFinal(node.operand); _checkForIntNotAssignable(node.operand); - return super.visitPostfixExpression(node); + super.visitPostfixExpression(node); } @override - Object visitPrefixedIdentifier(PrefixedIdentifier node) { + void visitPrefixedIdentifier(PrefixedIdentifier node) { if (node.parent is! Annotation) { ClassElement typeReference = ElementResolver.getTypeReference(node.prefix); @@ -1069,11 +1066,11 @@ _checkForStaticAccessToInstanceMember(typeReference, name); _checkForInstanceAccessToStaticMember(typeReference, name); } - return super.visitPrefixedIdentifier(node); + super.visitPrefixedIdentifier(node); } @override - Object visitPrefixExpression(PrefixExpression node) { + void visitPrefixExpression(PrefixExpression node) { TokenType operatorType = node.operator.type; Expression operand = node.operand; if (operatorType == TokenType.BANG) { @@ -1083,49 +1080,68 @@ } _checkForIntNotAssignable(operand); _checkForUseOfVoidResult(operand); - return super.visitPrefixExpression(node); + super.visitPrefixExpression(node); } @override - Object visitPropertyAccess(PropertyAccess node) { + void visitPropertyAccess(PropertyAccess node) { ClassElement typeReference = ElementResolver.getTypeReference(node.realTarget); SimpleIdentifier propertyName = node.propertyName; _checkForStaticAccessToInstanceMember(typeReference, propertyName); _checkForInstanceAccessToStaticMember(typeReference, propertyName); - return super.visitPropertyAccess(node); + super.visitPropertyAccess(node); } @override - Object visitRedirectingConstructorInvocation( + void visitRedirectingConstructorInvocation( RedirectingConstructorInvocation node) { _isInConstructorInitializer = true; try { - return super.visitRedirectingConstructorInvocation(node); + super.visitRedirectingConstructorInvocation(node); } finally { _isInConstructorInitializer = false; } } @override - Object visitRethrowExpression(RethrowExpression node) { + void visitRethrowExpression(RethrowExpression node) { _checkForRethrowOutsideCatch(node); - return super.visitRethrowExpression(node); + super.visitRethrowExpression(node); } @override - Object visitReturnStatement(ReturnStatement node) { + void visitReturnStatement(ReturnStatement node) { if (node.expression == null) { _returnsWithout.add(node); } else { _returnsWith.add(node); } _checkForAllReturnStatementErrorCodes(node); - return super.visitReturnStatement(node); + super.visitReturnStatement(node); } @override - Object visitSimpleFormalParameter(SimpleFormalParameter node) { + void visitSetLiteral(SetLiteral node) { + TypeArgumentList typeArguments = node.typeArguments; + if (typeArguments != null) { + if (node.isConst) { + NodeList<TypeAnnotation> arguments = typeArguments.arguments; + if (arguments.isNotEmpty) { + _checkForInvalidTypeArgumentInConstTypedLiteral(arguments, + CompileTimeErrorCode.INVALID_TYPE_ARGUMENT_IN_CONST_SET); + } + } + _checkForExpectedOneSetTypeArgument(node, typeArguments); + } + _checkForImplicitDynamicTypedLiteral(node); + _checkForSetElementTypeNotAssignable(node); + + super.visitSetLiteral(node); + } + + @override + void visitSimpleFormalParameter(SimpleFormalParameter node) { _checkForConstFormalParameter(node); _checkForPrivateOptionalParameter(node); _checkForTypeAnnotationDeferredClass(node.type); @@ -1138,88 +1154,87 @@ // - FunctionTypedFormalParameter is a function type, not dynamic. _checkForImplicitDynamicIdentifier(node, node.identifier); - return super.visitSimpleFormalParameter(node); + super.visitSimpleFormalParameter(node); } @override - Object visitSimpleIdentifier(SimpleIdentifier node) { + void visitSimpleIdentifier(SimpleIdentifier node) { _checkForAmbiguousImport(node); _checkForReferenceBeforeDeclaration(node); _checkForImplicitThisReferenceInInitializer(node); - _checkForTypeParameterIdentifierReferencedByStatic(node); + _checkForTypeParameterReferencedByStatic(node); if (!_isUnqualifiedReferenceToNonLocalStaticMemberAllowed(node)) { _checkForUnqualifiedReferenceToNonLocalStaticMember(node); } - return super.visitSimpleIdentifier(node); + super.visitSimpleIdentifier(node); } @override - Object visitSuperConstructorInvocation(SuperConstructorInvocation node) { + void visitSuperConstructorInvocation(SuperConstructorInvocation node) { _isInConstructorInitializer = true; try { - return super.visitSuperConstructorInvocation(node); + super.visitSuperConstructorInvocation(node); } finally { _isInConstructorInitializer = false; } } @override - Object visitSwitchCase(SwitchCase node) { + void visitSwitchCase(SwitchCase node) { _checkDuplicateDeclarationInStatements(node.statements); - return super.visitSwitchCase(node); + super.visitSwitchCase(node); } @override - Object visitSwitchDefault(SwitchDefault node) { + void visitSwitchDefault(SwitchDefault node) { _checkDuplicateDeclarationInStatements(node.statements); - return super.visitSwitchDefault(node); + super.visitSwitchDefault(node); } @override - Object visitSwitchStatement(SwitchStatement node) { + void visitSwitchStatement(SwitchStatement node) { _checkForSwitchExpressionNotAssignable(node); _checkForCaseBlocksNotTerminated(node); _checkForMissingEnumConstantInSwitch(node); - return super.visitSwitchStatement(node); + super.visitSwitchStatement(node); } @override - Object visitThisExpression(ThisExpression node) { + void visitThisExpression(ThisExpression node) { _checkForInvalidReferenceToThis(node); - return super.visitThisExpression(node); + super.visitThisExpression(node); } @override - Object visitThrowExpression(ThrowExpression node) { + void visitThrowExpression(ThrowExpression node) { _checkForConstEvalThrowsException(node); _checkForUseOfVoidResult(node.expression); - return super.visitThrowExpression(node); + super.visitThrowExpression(node); } @override - Object visitTopLevelVariableDeclaration(TopLevelVariableDeclaration node) { + void visitTopLevelVariableDeclaration(TopLevelVariableDeclaration node) { _checkForFinalNotInitialized(node.variables); - return super.visitTopLevelVariableDeclaration(node); + super.visitTopLevelVariableDeclaration(node); } @override - Object visitTypeArgumentList(TypeArgumentList node) { + void visitTypeArgumentList(TypeArgumentList node) { NodeList<TypeAnnotation> list = node.arguments; for (TypeAnnotation type in list) { _checkForTypeAnnotationDeferredClass(type); } - return super.visitTypeArgumentList(node); + super.visitTypeArgumentList(node); } @override - Object visitTypeName(TypeName node) { + void visitTypeName(TypeName node) { _checkForTypeArgumentNotMatchingBounds(node); - _checkForTypeParameterReferencedByStatic(node); - return super.visitTypeName(node); + super.visitTypeName(node); } @override - Object visitTypeParameter(TypeParameter node) { + void visitTypeParameter(TypeParameter node) { _checkForBuiltInIdentifierAsName(node.name, CompileTimeErrorCode.BUILT_IN_IDENTIFIER_AS_TYPE_PARAMETER_NAME); _checkForTypeParameterSupertypeOfItsBound(node); @@ -1227,22 +1242,21 @@ _checkForImplicitDynamicType(node.bound); _checkForGenericFunctionType(node.bound); node.bound?.accept(_uninstantiatedBoundChecker); - return super.visitTypeParameter(node); + super.visitTypeParameter(node); } @override - Object visitTypeParameterList(TypeParameterList node) { + void visitTypeParameterList(TypeParameterList node) { _checkDuplicateDefinitionInTypeParameterList(node); - return super.visitTypeParameterList(node); + super.visitTypeParameterList(node); } @override - Object visitVariableDeclaration(VariableDeclaration node) { + void visitVariableDeclaration(VariableDeclaration node) { SimpleIdentifier nameNode = node.name; Expression initializerNode = node.initializer; // do checks - _checkForInvalidAssignment(nameNode, initializerNode, - isDeclarationCast: true); + _checkForInvalidAssignment(nameNode, initializerNode); _checkForImplicitDynamicIdentifier(node, nameNode); // visit name nameNode.accept(this); @@ -1268,36 +1282,34 @@ _hiddenElements.declare(element); } } - // done - return null; } @override - Object visitVariableDeclarationList(VariableDeclarationList node) { + void visitVariableDeclarationList(VariableDeclarationList node) { _checkForTypeAnnotationDeferredClass(node.type); - return super.visitVariableDeclarationList(node); + super.visitVariableDeclarationList(node); } @override - Object visitVariableDeclarationStatement(VariableDeclarationStatement node) { + void visitVariableDeclarationStatement(VariableDeclarationStatement node) { _checkForFinalNotInitialized(node.variables); - return super.visitVariableDeclarationStatement(node); + super.visitVariableDeclarationStatement(node); } @override - Object visitWhileStatement(WhileStatement node) { + void visitWhileStatement(WhileStatement node) { _checkForNonBoolCondition(node.condition); - return super.visitWhileStatement(node); + super.visitWhileStatement(node); } @override - Object visitWithClause(WithClause node) { + void visitWithClause(WithClause node) { node.mixinTypes.forEach(_checkForImplicitDynamicType); - return super.visitWithClause(node); + super.visitWithClause(node); } @override - Object visitYieldStatement(YieldStatement node) { + void visitYieldStatement(YieldStatement node) { if (_inGenerator) { _checkForYieldOfInvalidType(node.expression, node.star != null); } else { @@ -1310,7 +1322,7 @@ _errorReporter.reportErrorForNode(errorCode, node); } _checkForUseOfVoidResult(node.expression); - return super.visitYieldStatement(node); + super.visitYieldStatement(node); } /** @@ -1911,8 +1923,7 @@ if (_checkForMixinSuperclassConstraints( mixinNameIndex, mixinName)) { problemReported = true; - } - if (_checkForMixinSuperInvokedMembers( + } else if (_checkForMixinSuperInvokedMembers( mixinTypeIndex, mixinName, mixinElement, mixinType)) { problemReported = true; } @@ -2218,24 +2229,20 @@ } bool _checkForAssignableExpression( - Expression expression, DartType expectedStaticType, ErrorCode errorCode, - {bool isDeclarationCast = false}) { + Expression expression, DartType expectedStaticType, ErrorCode errorCode) { DartType actualStaticType = getStaticType(expression); return actualStaticType != null && _checkForAssignableExpressionAtType( - expression, actualStaticType, expectedStaticType, errorCode, - isDeclarationCast: isDeclarationCast); + expression, actualStaticType, expectedStaticType, errorCode); } bool _checkForAssignableExpressionAtType( Expression expression, DartType actualStaticType, DartType expectedStaticType, - ErrorCode errorCode, - {bool isDeclarationCast = false}) { + ErrorCode errorCode) { if (!_expressionIsAssignableAtType( - expression, actualStaticType, expectedStaticType, - isDeclarationCast: isDeclarationCast)) { + expression, actualStaticType, expectedStaticType)) { _errorReporter.reportTypeErrorForNode( errorCode, expression, [actualStaticType, expectedStaticType]); return false; @@ -2895,6 +2902,24 @@ } /** + * Verify that if the given set [literal] has type arguments then there is + * exactly one. The [typeArguments] are the type arguments. + * + * See [StaticTypeWarningCode.EXPECTED_ONE_SET_TYPE_ARGUMENTS]. + */ + void _checkForExpectedOneSetTypeArgument( + SetLiteral literal, TypeArgumentList typeArguments) { + // check number of type arguments + int count = typeArguments.arguments.length; + if (count != 1) { + _errorReporter.reportErrorForNode( + StaticTypeWarningCode.EXPECTED_ONE_SET_TYPE_ARGUMENTS, + typeArguments, + [count]); + } + } + + /** * Verify that the given export [directive] has a unique name among other * exported libraries. The [exportElement] is the [ExportElement] retrieved * from the node, if the element in the node was `null`, then this method is @@ -3609,8 +3634,7 @@ StaticTypeWarningCode.FOR_IN_OF_INVALID_TYPE, node.iterable, [iterableType, loopTypeName]); - } else if (!_typeSystem.isAssignableTo(bestIterableType, variableType, - isDeclarationCast: true)) { + } else if (!_typeSystem.isAssignableTo(bestIterableType, variableType)) { _errorReporter.reportTypeErrorForNode( StaticTypeWarningCode.FOR_IN_OF_INVALID_ELEMENT_TYPE, node.iterable, @@ -3689,8 +3713,7 @@ * * See [StaticTypeWarningCode.INVALID_ASSIGNMENT]. */ - void _checkForInvalidAssignment(Expression lhs, Expression rhs, - {bool isDeclarationCast = false}) { + void _checkForInvalidAssignment(Expression lhs, Expression rhs) { if (lhs == null || rhs == null) { return; } @@ -3704,8 +3727,7 @@ } _checkForAssignableExpression( - rhs, leftType, StaticTypeWarningCode.INVALID_ASSIGNMENT, - isDeclarationCast: isDeclarationCast); + rhs, leftType, StaticTypeWarningCode.INVALID_ASSIGNMENT); } /** @@ -4147,6 +4169,11 @@ return false; } + ClassElementImpl nominalSuperClass = + AbstractClassElementImpl.getImpl(_enclosingClass.supertype?.element); + bool nominalSuperClassHasNoSuchMethodForwarders = + nominalSuperClass != null && !nominalSuperClass.isAbstract; + InterfaceTypeImpl enclosingType = _enclosingClass.type; Uri mixinLibraryUri = mixinElement.librarySource.uri; for (var name in mixinElementImpl.superInvokedNames) { @@ -4154,9 +4181,12 @@ var superMemberType = _inheritanceManager.getMember( enclosingType, nameObject, - forMixinIndex: mixinIndex, forSuper: true); + forMixinIndex: mixinIndex, concrete: true, forSuper: true); if (superMemberType == null) { + if (nominalSuperClassHasNoSuchMethodForwarders) { + continue; + } _errorReporter.reportErrorForNode( CompileTimeErrorCode .MIXIN_APPLICATION_NO_CONCRETE_SUPER_INVOKED_MEMBER, @@ -4321,7 +4351,7 @@ DartType type = typeName.type; if (type is InterfaceType) { ClassElement element = type.element; - if (element != null && element.isEnum) { + if (element.isEnum || element.isMixin) { // We have already reported the error. return; } @@ -4453,8 +4483,7 @@ return; } // prepare statement - Statement statement = - literal.getAncestor((node) => node is ExpressionStatement); + Statement statement = literal.thisOrAncestorOfType<ExpressionStatement>(); if (statement == null) { return; } @@ -5032,6 +5061,41 @@ } /** + * Verify that the elements in the given set [literal] are subtypes of the + * set's static type. + * + * See [CompileTimeErrorCode.SET_ELEMENT_TYPE_NOT_ASSIGNABLE], and + * [StaticWarningCode.SET_ELEMENT_TYPE_NOT_ASSIGNABLE]. + */ + void _checkForSetElementTypeNotAssignable(SetLiteral literal) { + // Determine the list's element type. We base this on the static type and + // not the literal's type arguments because in strong mode, the type + // arguments may be inferred. + DartType setType = literal.staticType; + assert(setType is InterfaceTypeImpl); + + List<DartType> typeArguments = (setType as InterfaceTypeImpl).typeArguments; + assert(typeArguments.length == 1); + + DartType setElementType = typeArguments[0]; + + // Check every list element. + bool isConst = literal.isConst; + for (Expression element in literal.elements) { + if (isConst) { + // TODO(paulberry): this error should be based on the actual type of the + // element, not the static type. See dartbug.com/21119. + _checkForArgumentTypeNotAssignableWithExpectedTypes( + element, + setElementType, + CheckedModeCompileTimeErrorCode.SET_ELEMENT_TYPE_NOT_ASSIGNABLE); + } + _checkForArgumentTypeNotAssignableWithExpectedTypes(element, + setElementType, StaticWarningCode.SET_ELEMENT_TYPE_NOT_ASSIGNABLE); + } + } + + /** * Check the given [typeReference] and that the [name] is not a reference to * an instance member. * @@ -5175,10 +5239,10 @@ ? argumentNodes[i] : typeName; if (argType is FunctionType && argType.typeFormals.isNotEmpty) { - _errorReporter.reportTypeErrorForNode( - CompileTimeErrorCode.GENERIC_FUNCTION_CANNOT_BE_TYPE_ARGUMENT, - argumentNode, - [argType.typeFormals.join(', ')]); + _errorReporter.reportErrorForNode( + CompileTimeErrorCode.GENERIC_FUNCTION_TYPE_CANNOT_BE_TYPE_ARGUMENT, + argumentNode, + ); continue; } DartType boundType = parameterElements[i].bound; @@ -5213,12 +5277,11 @@ } } - void _checkForTypeParameterIdentifierReferencedByStatic( - SimpleIdentifier identifier) { - var element = identifier.staticElement; - if (element is TypeParameterElement && - element.enclosingElement is ClassElement) { - if (_isInStaticMethod || _isInStaticVariableDeclaration) { + void _checkForTypeParameterReferencedByStatic(SimpleIdentifier identifier) { + if (_isInStaticMethod || _isInStaticVariableDeclaration) { + var element = identifier.staticElement; + if (element is TypeParameterElement && + element.enclosingElement is ClassElement) { // The class's type parameters are not in scope for static methods. // However all other type parameters are legal (e.g. the static method's // type parameters, or a local function's type parameters). @@ -5229,26 +5292,6 @@ } /** - * Check whether the given type [name] is a type parameter being used to - * define a static member. - * - * See [StaticWarningCode.TYPE_PARAMETER_REFERENCED_BY_STATIC]. - */ - void _checkForTypeParameterReferencedByStatic(TypeName name) { - if (_isInStaticMethod || _isInStaticVariableDeclaration) { - DartType type = name.type; - // The class's type parameters are not in scope for static methods. - // However all other type parameters are legal (e.g. the static method's - // type parameters, or a local function's type parameters). - if (type is TypeParameterType && - type.element.enclosingElement is ClassElement) { - _errorReporter.reportErrorForNode( - StaticWarningCode.TYPE_PARAMETER_REFERENCED_BY_STATIC, name); - } - } - } - - /** * Check whether the given type [parameter] is a supertype of its bound. * * See [StaticTypeWarningCode.TYPE_PARAMETER_SUPERTYPE_OF_ITS_BOUND]. @@ -5720,10 +5763,10 @@ DartType argType = typeArgs[i]; if (argType is FunctionType && argType.typeFormals.isNotEmpty) { - _errorReporter.reportTypeErrorForNode( - CompileTimeErrorCode.GENERIC_FUNCTION_CANNOT_BE_TYPE_ARGUMENT, - typeArgumentList[i], - [argType.typeFormals.join(', ')]); + _errorReporter.reportErrorForNode( + CompileTimeErrorCode.GENERIC_FUNCTION_TYPE_CANNOT_BE_TYPE_ARGUMENT, + typeArgumentList[i], + ); continue; } @@ -5757,10 +5800,8 @@ } bool _expressionIsAssignableAtType(Expression expression, - DartType actualStaticType, DartType expectedStaticType, - {isDeclarationCast: false}) { - return _typeSystem.isAssignableTo(actualStaticType, expectedStaticType, - isDeclarationCast: isDeclarationCast); + DartType actualStaticType, DartType expectedStaticType) { + return _typeSystem.isAssignableTo(actualStaticType, expectedStaticType); } InterfaceType _findInterfaceTypeForMixin(TypeName mixin, @@ -5953,14 +5994,7 @@ } ExecutableElement _getOverriddenMember(Element member) { - if (member == null) { - return null; - } - ClassElement classElement = - member.getAncestor((element) => element is ClassElement); - if (classElement == null) { - return null; - } + ClassElement classElement = member.enclosingElement; String name = member.name; ClassElement superclass = classElement.supertype?.element; Set<ClassElement> visitedClasses = new Set<ClassElement>(); @@ -6082,7 +6116,7 @@ return identical(parent.constructorName, identifier); } if (parent is CommentReference) { - return parent.newKeyword != null; + return true; } if (parent is ConstructorName) { return identical(parent.name, identifier); @@ -6349,47 +6383,45 @@ .firstWhere((ElementAnnotation e) => e.isRequired, orElse: () => null); } -class _HasTypedefSelfReferenceVisitor - extends GeneralizingElementVisitor<Object> { +class _HasTypedefSelfReferenceVisitor extends GeneralizingElementVisitor<void> { final GenericFunctionTypeElement element; bool hasSelfReference = false; _HasTypedefSelfReferenceVisitor(this.element); @override - Object visitClassElement(ClassElement element) { + void visitClassElement(ClassElement element) { // Typedefs are allowed to reference themselves via classes. - return null; } @override - Object visitFunctionElement(FunctionElement element) { + void visitFunctionElement(FunctionElement element) { _addTypeToCheck(element.returnType); - return super.visitFunctionElement(element); + super.visitFunctionElement(element); } @override - Object visitFunctionTypeAliasElement(FunctionTypeAliasElement element) { + void visitFunctionTypeAliasElement(FunctionTypeAliasElement element) { _addTypeToCheck(element.returnType); - return super.visitFunctionTypeAliasElement(element); + super.visitFunctionTypeAliasElement(element); } @override - Object visitGenericFunctionTypeElement(GenericFunctionTypeElement element) { + void visitGenericFunctionTypeElement(GenericFunctionTypeElement element) { _addTypeToCheck(element.returnType); - return super.visitGenericFunctionTypeElement(element); + super.visitGenericFunctionTypeElement(element); } @override - Object visitParameterElement(ParameterElement element) { + void visitParameterElement(ParameterElement element) { _addTypeToCheck(element.type); - return super.visitParameterElement(element); + super.visitParameterElement(element); } @override - Object visitTypeParameterElement(TypeParameterElement element) { + void visitTypeParameterElement(TypeParameterElement element) { _addTypeToCheck(element.bound); - return super.visitTypeParameterElement(element); + super.visitTypeParameterElement(element); } void _addTypeToCheck(DartType type) {
diff --git a/pkg/analyzer/lib/src/generated/package.dart b/pkg/analyzer/lib/src/generated/package.dart deleted file mode 100644 index fba626f..0000000 --- a/pkg/analyzer/lib/src/generated/package.dart +++ /dev/null
@@ -1,241 +0,0 @@ -// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file -// for details. All rights reserved. Use of this source code is governed by a -// BSD-style license that can be found in the LICENSE file. - -import 'dart:collection'; - -import 'package:analyzer/exception/exception.dart'; -import 'package:analyzer/file_system/file_system.dart'; -import 'package:analyzer/src/context/builder.dart'; -import 'package:analyzer/src/file_system/file_system.dart'; -import 'package:analyzer/src/generated/engine.dart'; -import 'package:analyzer/src/generated/sdk.dart'; -import 'package:analyzer/src/generated/source.dart'; -import 'package:analyzer/src/generated/utilities_general.dart'; -import 'package:analyzer/src/source/package_map_resolver.dart'; -import 'package:package_config/packages.dart'; -import 'package:yaml/yaml.dart'; - -/** - * Traverses the package structure to determine the transitive dependencies for - * a given package. - */ -class DependencyFinder { - /** - * The name of the pubspec.yaml file. - */ - static const String pubspecName = 'pubspec.yaml'; - - /** - * The resource provider used to access the file system. - */ - final ResourceProvider resourceProvider; - - /** - * A table mapping the absolute paths of packages to a list of the names of - * the packages on which those packages depend. - */ - final Map<String, List<String>> dependencyMap = - new HashMap<String, List<String>>(); - - /** - * Initialize a newly created dependency finder to use the given - * [resourceProvider] to access the file system. - */ - DependencyFinder(this.resourceProvider); - - /** - * Return a sorted list of the directories containing all of the packages on - * which the package at the given [packagePath] depends. The [packageMap] - * maps the names of packages to the directories in which they are contained. - * - * Throws an [AnalysisException] if any of the packages are missing their - * 'pubspec.yaml' file. - */ - List<String> transitiveDependenciesFor( - Map<String, List<Folder>> packageMap, String packagePath) { - Set<String> processedPackages = new HashSet<String>(); - Set<String> processedPaths = new HashSet<String>(); - void process(String packageName) { - if (processedPackages.add(packageName)) { - List<Folder> folderList = packageMap[packageName]; - if (folderList == null || folderList.isEmpty) { - throw new StateError('No mapping for package "$packageName"'); - } - String packagePath = folderList[0].path; - processedPaths.add(packagePath); - List<String> dependencies = _dependenciesFor(packagePath); - for (String dependency in dependencies) { - process(dependency); - } - } - } - - List<String> dependencies = _dependenciesFor(packagePath); - dependencies.forEach(process); - processedPaths.remove(packagePath); - List<String> transitiveDependencies = processedPaths.toList(); - transitiveDependencies.sort(); - return transitiveDependencies; - } - - /** - * Add to the given set of [dependecies] all of the package names used as keys - * in the given [yamlMap]. - */ - void _collectDependencies(HashSet<String> dependencies, YamlMap yamlMap) { - if (yamlMap is Map) { - for (var key in yamlMap.keys) { - if (key is String) { - dependencies.add(key); - } - } - } - } - - /** - * Return a list of the names of the packages on which the package at the - * [packagePath] depends. - */ - List<String> _dependenciesFor(String packagePath) { - return dependencyMap.putIfAbsent(packagePath, () { - Set<String> dependencies = new HashSet<String>(); - YamlNode yamlNode = _readPubspec(packagePath); - if (yamlNode is YamlMap) { - _collectDependencies(dependencies, yamlNode['dependencies']); - } - return dependencies.toList(); - }); - } - - /** - * Read the content of the pubspec file in the directory at the given - * [directoryPath]. Return `null` if the file does not exist, cannot be read, - * or has content that is not valid YAML. - */ - YamlNode _readPubspec(String directoryPath) { - try { - File yamlFile = resourceProvider - .getFolder(directoryPath) - .getChildAssumingFile(pubspecName); - String yamlContent = yamlFile.readAsStringSync(); - return loadYamlNode(yamlContent); - } catch (exception, stackTrace) { - throw new AnalysisException('Missing $pubspecName in $directoryPath', - new CaughtException(exception, stackTrace)); - } - } -} - -/** - * A description of the context in which a package will be analyzed. - */ -class PackageDescription { - /** - * The id of the package being described. The id encodes the actual locations - * of the package itself and all of the packages on which it depends. - */ - final String id; - - /** - * The SDK against which the package will be analyzed. - */ - final DartSdk sdk; - - /** - * The analysis options that will be used when analyzing the package. - */ - final AnalysisOptions options; - - /** - * Initialize a newly create package description to describe the package with - * the given [id] that is being analyzed against the given [sdk] using the - * given [options]. - */ - PackageDescription(this.id, this.sdk, this.options); - - @override - int get hashCode { - int hashCode = 0; - for (int value in options.signature) { - hashCode = JenkinsSmiHash.combine(hashCode, value); - } - hashCode = JenkinsSmiHash.combine(hashCode, id.hashCode); - hashCode = JenkinsSmiHash.combine(hashCode, sdk.hashCode); - return JenkinsSmiHash.finish(hashCode); - } - - @override - bool operator ==(Object other) { - return other is PackageDescription && - other.sdk == sdk && - AnalysisOptions.signaturesEqual( - other.options.signature, options.signature) && - other.id == id; - } -} - -/** - * Manages the contexts in which each package is analyzed. - */ -class PackageManager { - /** - * The resource provider used to access the file system. - */ - final ResourceProvider resourceProvider; - - /** - * A table mapping the id's of packages to the context in which the package is - * analyzed. - */ - final Map<PackageDescription, AnalysisContext> contextMap = - new HashMap<PackageDescription, AnalysisContext>(); - - /** - * Initialize a newly created package manager. - */ - PackageManager(this.resourceProvider); - - /** - * Return the context in which the package at the given [packagePath] should - * be analyzed when the given [packages] object is used to resolve package - * names, the given [resolver] will be used to resolve 'dart:' URI's, and the - * given [options] will control the analysis. - */ - AnalysisContext getContext(String packagePath, Packages packages, - DartUriResolver resolver, AnalysisOptions options) { - DartSdk sdk = resolver.dartSdk; - Map<String, List<Folder>> packageMap = - new ContextBuilder(resourceProvider, null, null) - .convertPackagesToMap(packages); - PackageDescription description = - new PackageDescription(_buildId(packagePath, packageMap), sdk, options); - return contextMap.putIfAbsent(description, () { - AnalysisContext context = AnalysisEngine.instance.createAnalysisContext(); - context.sourceFactory = new SourceFactory(<UriResolver>[ - resolver, - new PackageMapUriResolver(resourceProvider, packageMap), - new ResourceUriResolver(resourceProvider) - ], packages, resourceProvider); - context.analysisOptions = options; - return context; - }); - } - - /** - * Return the id associated with the package at the given [packagePath] when - * the given [packageMap] is used to resolve package names. - */ - String _buildId(String packagePath, Map<String, List<Folder>> packageMap) { - DependencyFinder finder = new DependencyFinder(resourceProvider); - List<String> dependencies = - finder.transitiveDependenciesFor(packageMap, packagePath); - StringBuffer buffer = new StringBuffer(); - buffer.write(packagePath); - for (String dependency in dependencies) { - buffer.write(';'); - buffer.write(dependency); - } - return buffer.toString(); - } -}
diff --git a/pkg/analyzer/lib/src/generated/parser.dart b/pkg/analyzer/lib/src/generated/parser.dart index dcaf2a5..4598bdf 100644 --- a/pkg/analyzer/lib/src/generated/parser.dart +++ b/pkg/analyzer/lib/src/generated/parser.dart
@@ -35,101 +35,71 @@ part 'parser_fasta.dart'; -/** - * A simple data-holder for a method that needs to return multiple values. - */ +/// Whether set literal parsing is currently enabled by default. +/// TODO(paulberry): once we have a shared source of truth about this +/// information, hook this constant up to it. (See phase 0 of +/// https://github.com/dart-lang/language/issues/60) +const bool enableSetLiteralsDefault = false; + +/// A simple data-holder for a method that needs to return multiple values. class CommentAndMetadata { - /** - * The documentation comment that was parsed, or `null` if none was given. - */ + /// The documentation comment that was parsed, or `null` if none was given. final Comment comment; - /** - * The metadata that was parsed, or `null` if none was given. - */ + /// The metadata that was parsed, or `null` if none was given. final List<Annotation> metadata; - /** - * Initialize a newly created holder with the given [comment] and [metadata]. - */ + /// Initialize a newly created holder with the given [comment] and [metadata]. CommentAndMetadata(this.comment, this.metadata); - /** - * Return `true` if some metadata was parsed. - */ + /// Return `true` if some metadata was parsed. bool get hasMetadata => metadata != null && metadata.isNotEmpty; } -/** - * A simple data-holder for a method that needs to return multiple values. - */ +/// A simple data-holder for a method that needs to return multiple values. class FinalConstVarOrType { - /** - * The 'final', 'const' or 'var' keyword, or `null` if none was given. - */ + /// The 'final', 'const' or 'var' keyword, or `null` if none was given. final Token keyword; - /** - * The type, or `null` if no type was specified. - */ + /// The type, or `null` if no type was specified. final TypeAnnotation type; - /** - * Initialize a newly created holder with the given [keyword] and [type]. - */ + /// Initialize a newly created holder with the given [keyword] and [type]. FinalConstVarOrType(this.keyword, this.type); } -/** - * A simple data-holder for a method that needs to return multiple values. - */ +/// A simple data-holder for a method that needs to return multiple values. class Modifiers { - /** - * The token representing the keyword 'abstract', or `null` if the keyword was - * not found. - */ + /// The token representing the keyword 'abstract', or `null` if the keyword + /// was not found. Token abstractKeyword; - /** - * The token representing the keyword 'const', or `null` if the keyword was - * not found. - */ + /// The token representing the keyword 'const', or `null` if the keyword was + /// not found. Token constKeyword; - /** - * The token representing the keyword 'covariant', or `null` if the keyword - * was not found. - */ + /// The token representing the keyword 'covariant', or `null` if the keyword + /// was not found. Token covariantKeyword; - /** - * The token representing the keyword 'external', or `null` if the keyword was - * not found. - */ + /// The token representing the keyword 'external', or `null` if the keyword + /// was not found. Token externalKeyword; - /** - * The token representing the keyword 'factory', or `null` if the keyword was - * not found. - */ + /// The token representing the keyword 'factory', or `null` if the keyword was + /// not found. Token factoryKeyword; - /** - * The token representing the keyword 'final', or `null` if the keyword was - * not found. - */ + /// The token representing the keyword 'final', or `null` if the keyword was + /// not found. Token finalKeyword; - /** - * The token representing the keyword 'static', or `null` if the keyword was - * not found. - */ + /// The token representing the keyword 'static', or `null` if the keyword was + /// not found. Token staticKeyword; - /** - * The token representing the keyword 'var', or `null` if the keyword was not - * found. - */ + /// The token representing the keyword 'var', or `null` if the keyword was not + /// found. Token varKeyword; @override @@ -145,11 +115,9 @@ return buffer.toString(); } - /** - * If the given [keyword] is not `null`, append it to the given [builder], - * prefixing it with a space if [needsSpace] is `true`. Return `true` if - * subsequent keywords need to be prefixed with a space. - */ + /// If the given [keyword] is not `null`, append it to the given [builder], + /// prefixing it with a space if [needsSpace] is `true`. Return `true` if + /// subsequent keywords need to be prefixed with a space. bool _appendKeyword(StringBuffer buffer, bool needsSpace, Token keyword) { if (keyword != null) { if (needsSpace) { @@ -162,9 +130,7 @@ } } -/** - * A parser used to parse tokens into an AST structure. - */ +/// A parser used to parse tokens into an AST structure. class Parser { static String ASYNC = Keyword.ASYNC.lexeme; @@ -180,91 +146,61 @@ static const int _MAX_TREE_DEPTH = 300; - /** - * A flag indicating whether the analyzer [Parser] factory method - * will return a fasta based parser or an analyzer based parser. - */ + /// A flag indicating whether the analyzer [Parser] factory method + /// will return a fasta based parser or an analyzer based parser. static const bool useFasta = const bool.fromEnvironment("useFastaParser", defaultValue: true); - /** - * The source being parsed. - */ + /// The source being parsed. final Source _source; - /** - * The error listener that will be informed of any errors that are found - * during the parse. - */ + /// The error listener that will be informed of any errors that are found + /// during the parse. final AnalysisErrorListener _errorListener; - /** - * An [_errorListener] lock, if more than `0`, then errors are not reported. - */ + /// An [_errorListener] lock, if more than `0`, then errors are not reported. int _errorListenerLock = 0; - /** - * A flag indicating whether the parser should parse instance creation - * expressions that lack either the `new` or `const` keyword. - */ + /// A flag indicating whether the parser should parse instance creation + /// expressions that lack either the `new` or `const` keyword. bool _enableOptionalNewAndConst = true; - /** - * A flag indicating whether parser is to parse function bodies. - */ + /// A flag indicating whether parser is to parse function bodies. bool _parseFunctionBodies = true; - /** - * The next token to be parsed. - */ + /// The next token to be parsed. Token _currentToken; - /** - * The depth of the current AST. When this depth is too high, so we're at the - * risk of overflowing the stack, we stop parsing and report an error. - */ + /// The depth of the current AST. When this depth is too high, so we're at the + /// risk of overflowing the stack, we stop parsing and report an error. int _treeDepth = 0; - /** - * A flag indicating whether the parser is currently in a function body marked - * as being 'async'. - */ + /// A flag indicating whether the parser is currently in a function body + /// marked as being 'async'. bool _inAsync = false; - /** - * A flag indicating whether the parser is currently in a function body marked - * (by a star) as being a generator. - */ + /// A flag indicating whether the parser is currently in a function body + /// marked(by a star) as being a generator. bool _inGenerator = false; - /** - * A flag indicating whether the parser is currently in the body of a loop. - */ + /// A flag indicating whether the parser is currently in the body of a loop. bool _inLoop = false; - /** - * A flag indicating whether the parser is currently in a switch statement. - */ + /// A flag indicating whether the parser is currently in a switch statement. bool _inSwitch = false; - /** - * A flag indicating whether the parser is currently in a constructor field - * initializer, with no intervening parentheses, braces, or brackets. - */ + /// A flag indicating whether the parser is currently in a constructor field + /// initializer, with no intervening parentheses, braces, or brackets. bool _inInitializer = false; - /** - * A flag indicating whether the parser is to parse generic method syntax. - */ + /// A flag indicating whether the parser is to parse generic method syntax. @deprecated bool parseGenericMethods = false; bool allowNativeClause; - /** - * Initialize a newly created parser to parse tokens in the given [_source] - * and to report any errors that are found to the given [_errorListener]. - */ + /// Initialize a newly created parser to parse tokens in the given [_source] + /// and to report any errors that are found to the given [_errorListener]. factory Parser(Source source, AnalysisErrorListener errorListener, {bool useFasta}) { if (useFasta ?? Parser.useFasta) { @@ -276,65 +212,55 @@ Parser.withoutFasta(this._source, this._errorListener); - /** - * Return the current token. - */ + /// Return the current token. Token get currentToken => _currentToken; - /** - * Set the token with which the parse is to begin to the given [token]. - */ + /// Set the token with which the parse is to begin to the given [token]. void set currentToken(Token token) { this._currentToken = token; } - /** - * Return `true` if the parser is to parse asserts in the initializer list of - * a constructor. - */ + /// Return `true` if the parser is to parse asserts in the initializer list of + /// a constructor. @deprecated bool get enableAssertInitializer => true; - /** - * Set whether the parser is to parse asserts in the initializer list of a - * constructor to match the given [enable] flag. - */ + /// Set whether the parser is to parse asserts in the initializer list of a + /// constructor to match the given [enable] flag. @deprecated void set enableAssertInitializer(bool enable) {} - /** - * Return `true` if the parser should parse instance creation expressions that - * lack either the `new` or `const` keyword. - */ + /// Return `true` if the parser should parse instance creation expressions + /// that lack either the `new` or `const` keyword. bool get enableOptionalNewAndConst => _enableOptionalNewAndConst; - /** - * Set whether the parser should parse instance creation expressions that lack - * either the `new` or `const` keyword. - */ + /// Set whether the parser should parse instance creation expressions that + /// lack either the `new` or `const` keyword. void set enableOptionalNewAndConst(bool enable) { _enableOptionalNewAndConst = enable; } - /** - * Return `true` if the parser is to allow URI's in part-of directives. - */ + /// Enables or disables parsing of set literals. + void set enableSetLiterals(bool value) { + if (value) { + throw new UnimplementedError( + 'set-literal experiment not supported by analyzer parser'); + } + } + + /// Return `true` if the parser is to allow URI's in part-of directives. @deprecated bool get enableUriInPartOf => true; - /** - * Set whether the parser is to allow URI's in part-of directives to the given - * [enable] flag. - */ + /// Set whether the parser is to allow URI's in part-of directives to the + /// given [enable] flag. @deprecated void set enableUriInPartOf(bool enable) {} - /** - * Return `true` if the current token is the first token of a return type that - * is followed by an identifier, possibly followed by a list of type - * parameters, followed by a left-parenthesis. This is used by - * [parseTypeAlias] to determine whether or not to parse a return type. - */ + /// Return `true` if the current token is the first token of a return type + /// that is followed by an identifier, possibly followed by a list of type + /// parameters, followed by a left-parenthesis. This is used by + /// [parseTypeAlias] to determine whether or not to parse a return type. bool get hasReturnTypeInTypeAlias { // TODO(brianwilkerson) This is too expensive as implemented and needs to be // re-implemented or removed. @@ -345,11 +271,9 @@ return _tokenMatchesIdentifier(next); } - /** - * Set whether the parser is to parse the async support. - * - * Support for removing the 'async' library has been removed. - */ + /// Set whether the parser is to parse the async support. + /// + /// Support for removing the 'async' library has been removed. @deprecated void set parseAsync(bool parseAsync) {} @@ -359,19 +283,15 @@ @deprecated void set parseConditionalDirectives(bool value) {} - /** - * Set whether parser is to parse function bodies. - */ + /// Set whether parser is to parse function bodies. void set parseFunctionBodies(bool parseFunctionBodies) { this._parseFunctionBodies = parseFunctionBodies; } - /** - * Return the content of a string with the given literal representation. The - * [lexeme] is the literal representation of the string. The flag [isFirst] is - * `true` if this is the first token in a string literal. The flag [isLast] is - * `true` if this is the last token in a string literal. - */ + /// Return the content of a string with the given literal representation. The + /// [lexeme] is the literal representation of the string. The flag [isFirst] + /// is `true` if this is the first token in a string literal. The flag + /// [isLast] is `true` if this is the last token in a string literal. String computeStringValue(String lexeme, bool isFirst, bool isLast) { StringLexemeHelper helper = new StringLexemeHelper(lexeme, isFirst, isLast); int start = helper.start; @@ -394,9 +314,7 @@ return buffer.toString(); } - /** - * Return a synthetic identifier. - */ + /// Return a synthetic identifier. SimpleIdentifier createSyntheticIdentifier({bool isDeclaration: false}) { Token syntheticToken; if (_currentToken.type.isKeyword) { @@ -414,26 +332,21 @@ isDeclaration: isDeclaration); } - /** - * Return a synthetic string literal. - */ + /// Return a synthetic string literal. SimpleStringLiteral createSyntheticStringLiteral() => astFactory .simpleStringLiteral(_createSyntheticToken(TokenType.STRING), ""); - /** - * Advance to the next token in the token stream, making it the new current - * token and return the token that was current before this method was invoked. - */ + /// Advance to the next token in the token stream, making it the new current + /// token and return the token that was current before this method was + /// invoked. Token getAndAdvance() { Token token = _currentToken; _currentToken = _currentToken.next; return token; } - /** - * Return `true` if the current token appears to be the beginning of a - * function declaration. - */ + /// Return `true` if the current token appears to be the beginning of a + /// function declaration. bool isFunctionDeclaration() { Keyword keyword = _currentToken.keyword; Token afterReturnType = skipTypeWithoutFunction(_currentToken); @@ -478,10 +391,8 @@ return false; } - /** - * Return `true` if the given [token] appears to be the beginning of a - * function expression. - */ + /// Return `true` if the given [token] appears to be the beginning of a + /// function expression. bool isFunctionExpression(Token token) { // Function expressions aren't allowed in initializer lists. if (_inInitializer) { @@ -503,30 +414,28 @@ return lexeme == ASYNC || lexeme == SYNC; } - /** - * Return `true` if the current token is the first token in an initialized - * variable declaration rather than an expression. This method assumes that we - * have already skipped past any metadata that might be associated with the - * declaration. - * - * initializedVariableDeclaration ::= - * declaredIdentifier ('=' expression)? (',' initializedIdentifier)* - * - * declaredIdentifier ::= - * metadata finalConstVarOrType identifier - * - * finalConstVarOrType ::= - * 'final' type? - * | 'const' type? - * | 'var' - * | type - * - * type ::= - * qualified typeArguments? - * - * initializedIdentifier ::= - * identifier ('=' expression)? - */ + /// Return `true` if the current token is the first token in an initialized + /// variable declaration rather than an expression. This method assumes that + /// we have already skipped past any metadata that might be associated with + /// the declaration. + /// + /// initializedVariableDeclaration ::= + /// declaredIdentifier ('=' expression)? (',' initializedIdentifier)* + /// + /// declaredIdentifier ::= + /// metadata finalConstVarOrType identifier + /// + /// finalConstVarOrType ::= + /// 'final' type? + /// | 'const' type? + /// | 'var' + /// | type + /// + /// type ::= + /// qualified typeArguments? + /// + /// initializedIdentifier ::= + /// identifier ('=' expression)? bool isInitializedVariableDeclaration() { Keyword keyword = _currentToken.keyword; if (keyword == Keyword.FINAL || @@ -601,10 +510,8 @@ return false; } - /** - * Return `true` if the current token appears to be the beginning of a switch - * member. - */ + /// Return `true` if the current token appears to be the beginning of a switch + /// member. bool isSwitchMember() { Token token = _currentToken; while (_tokenMatches(token, TokenType.IDENTIFIER) && @@ -615,14 +522,12 @@ return keyword == Keyword.CASE || keyword == Keyword.DEFAULT; } - /** - * Parse an additive expression. Return the additive expression that was - * parsed. - * - * additiveExpression ::= - * multiplicativeExpression (additiveOperator multiplicativeExpression)* - * | 'super' (additiveOperator multiplicativeExpression)+ - */ + /// Parse an additive expression. Return the additive expression that was + /// parsed. + /// + /// additiveExpression ::= + /// multiplicativeExpression (additiveOperator multiplicativeExpression)* + /// | 'super' (additiveOperator multiplicativeExpression)+ Expression parseAdditiveExpression() { Expression expression; if (_currentToken.keyword == Keyword.SUPER && @@ -638,14 +543,12 @@ return expression; } - /** - * Parse an annotation. Return the annotation that was parsed. - * - * This method assumes that the current token matches [TokenType.AT]. - * - * annotation ::= - * '@' qualified ('.' identifier)? arguments? - */ + /// Parse an annotation. Return the annotation that was parsed. + /// + /// This method assumes that the current token matches [TokenType.AT]. + /// + /// annotation ::= + /// '@' qualified ('.' identifier)? arguments? Annotation parseAnnotation() { Token atSign = getAndAdvance(); Identifier name = parsePrefixedIdentifier(); @@ -663,16 +566,14 @@ atSign, name, period, constructorName, arguments); } - /** - * Parse an argument. Return the argument that was parsed. - * - * argument ::= - * namedArgument - * | expression - * - * namedArgument ::= - * label expression - */ + /// Parse an argument. Return the argument that was parsed. + /// + /// argument ::= + /// namedArgument + /// | expression + /// + /// namedArgument ::= + /// label expression Expression parseArgument() { // TODO(brianwilkerson) Consider returning a wrapper indicating whether the // expression is a named expression in order to remove the 'is' check in @@ -688,29 +589,25 @@ } } - /** - * Parse a list of arguments. Return the argument list that was parsed. - * - * This method assumes that the current token matches [TokenType.OPEN_PAREN]. - * - * arguments ::= - * '(' argumentList? ')' - * - * argumentList ::= - * namedArgument (',' namedArgument)* - * | expressionList (',' namedArgument)* - */ + /// Parse a list of arguments. Return the argument list that was parsed. + /// + /// This method assumes that the current token matches [TokenType.OPEN_PAREN]. + /// + /// arguments ::= + /// '(' argumentList? ')' + /// + /// argumentList ::= + /// namedArgument (',' namedArgument)* + /// | expressionList (',' namedArgument)* ArgumentList parseArgumentList() { Token leftParenthesis = getAndAdvance(); if (_matches(TokenType.CLOSE_PAREN)) { return astFactory.argumentList(leftParenthesis, null, getAndAdvance()); } - /** - * Return `true` if the parser appears to be at the beginning of an argument - * even though there was no comma. This is a special case of the more - * general recovery technique described below. - */ + /// Return `true` if the parser appears to be at the beginning of an + /// argument even though there was no comma. This is a special case of the + /// more general recovery technique described below. bool isLikelyMissingComma() { if (_matchesIdentifier() && _tokenMatches(_currentToken.next, TokenType.COLON) && @@ -770,14 +667,12 @@ } } - /** - * Parse an assert statement. Return the assert statement. - * - * This method assumes that the current token matches `Keyword.ASSERT`. - * - * assertStatement ::= - * 'assert' '(' expression [',' expression] ')' ';' - */ + /// Parse an assert statement. Return the assert statement. + /// + /// This method assumes that the current token matches `Keyword.ASSERT`. + /// + /// assertStatement ::= + /// 'assert' '(' expression [',' expression] ')' ';' AssertStatement parseAssertStatement() { Token keyword = getAndAdvance(); Token leftParen = _expect(TokenType.OPEN_PAREN); @@ -803,16 +698,14 @@ keyword, leftParen, expression, comma, message, rightParen, semicolon); } - /** - * Parse an assignable expression. The [primaryAllowed] is `true` if the - * expression is allowed to be a primary without any assignable selector. - * Return the assignable expression that was parsed. - * - * assignableExpression ::= - * primary (arguments* assignableSelector)+ - * | 'super' unconditionalAssignableSelector - * | identifier - */ + /// Parse an assignable expression. The [primaryAllowed] is `true` if the + /// expression is allowed to be a primary without any assignable selector. + /// Return the assignable expression that was parsed. + /// + /// assignableExpression ::= + /// primary (arguments* assignableSelector)+ + /// | 'super' unconditionalAssignableSelector + /// | identifier Expression parseAssignableExpression(bool primaryAllowed) { // // A primary expression can start with an identifier. We resolve the @@ -862,21 +755,19 @@ } } - /** - * Parse an assignable selector. The [prefix] is the expression preceding the - * selector. The [optional] is `true` if the selector is optional. Return the - * assignable selector that was parsed, or the original prefix if there was no - * assignable selector. If [allowConditional] is false, then the '?.' - * operator will still be parsed, but a parse error will be generated. - * - * unconditionalAssignableSelector ::= - * '[' expression ']' - * | '.' identifier - * - * assignableSelector ::= - * unconditionalAssignableSelector - * | '?.' identifier - */ + /// Parse an assignable selector. The [prefix] is the expression preceding the + /// selector. The [optional] is `true` if the selector is optional. Return the + /// assignable selector that was parsed, or the original prefix if there was + /// no assignable selector. If [allowConditional] is false, then the '?.' + /// operator will still be parsed, but a parse error will be generated. + /// + /// unconditionalAssignableSelector ::= + /// '[' expression ']' + /// | '.' identifier + /// + /// assignableSelector ::= + /// unconditionalAssignableSelector + /// | '?.' identifier Expression parseAssignableSelector(Expression prefix, bool optional, {bool allowConditional: true}) { TokenType type = _currentToken.type; @@ -921,28 +812,24 @@ } } - /** - * Parse a await expression. Return the await expression that was parsed. - * - * This method assumes that the current token matches `_AWAIT`. - * - * awaitExpression ::= - * 'await' unaryExpression - */ + /// Parse a await expression. Return the await expression that was parsed. + /// + /// This method assumes that the current token matches `_AWAIT`. + /// + /// awaitExpression ::= + /// 'await' unaryExpression AwaitExpression parseAwaitExpression() { Token awaitToken = getAndAdvance(); Expression expression = parseUnaryExpression(); return astFactory.awaitExpression(awaitToken, expression); } - /** - * Parse a bitwise and expression. Return the bitwise and expression that was - * parsed. - * - * bitwiseAndExpression ::= - * shiftExpression ('&' shiftExpression)* - * | 'super' ('&' shiftExpression)+ - */ + /// Parse a bitwise and expression. Return the bitwise and expression that was + /// parsed. + /// + /// bitwiseAndExpression ::= + /// shiftExpression ('&' shiftExpression)* + /// | 'super' ('&' shiftExpression)+ Expression parseBitwiseAndExpression() { Expression expression; if (_currentToken.keyword == Keyword.SUPER && @@ -958,14 +845,12 @@ return expression; } - /** - * Parse a bitwise or expression. Return the bitwise or expression that was - * parsed. - * - * bitwiseOrExpression ::= - * bitwiseXorExpression ('|' bitwiseXorExpression)* - * | 'super' ('|' bitwiseXorExpression)+ - */ + /// Parse a bitwise or expression. Return the bitwise or expression that was + /// parsed. + /// + /// bitwiseOrExpression ::= + /// bitwiseXorExpression ('|' bitwiseXorExpression)* + /// | 'super' ('|' bitwiseXorExpression)+ Expression parseBitwiseOrExpression() { Expression expression; if (_currentToken.keyword == Keyword.SUPER && @@ -981,14 +866,12 @@ return expression; } - /** - * Parse a bitwise exclusive-or expression. Return the bitwise exclusive-or - * expression that was parsed. - * - * bitwiseXorExpression ::= - * bitwiseAndExpression ('^' bitwiseAndExpression)* - * | 'super' ('^' bitwiseAndExpression)+ - */ + /// Parse a bitwise exclusive-or expression. Return the bitwise exclusive-or + /// expression that was parsed. + /// + /// bitwiseXorExpression ::= + /// bitwiseAndExpression ('^' bitwiseAndExpression)* + /// | 'super' ('^' bitwiseAndExpression)+ Expression parseBitwiseXorExpression() { Expression expression; if (_currentToken.keyword == Keyword.SUPER && @@ -1004,15 +887,13 @@ return expression; } - /** - * Parse a block. Return the block that was parsed. - * - * This method assumes that the current token matches - * [TokenType.OPEN_CURLY_BRACKET]. - * - * block ::= - * '{' statements '}' - */ + /// Parse a block. Return the block that was parsed. + /// + /// This method assumes that the current token matches + /// [TokenType.OPEN_CURLY_BRACKET]. + /// + /// block ::= + /// '{' statements '}' Block parseBlock() { bool isEndOfBlock() { TokenType type = _currentToken.type; @@ -1042,14 +923,12 @@ return astFactory.block(leftBracket, statements, rightBracket); } - /** - * Parse a break statement. Return the break statement that was parsed. - * - * This method assumes that the current token matches `Keyword.BREAK`. - * - * breakStatement ::= - * 'break' identifier? ';' - */ + /// Parse a break statement. Return the break statement that was parsed. + /// + /// This method assumes that the current token matches `Keyword.BREAK`. + /// + /// breakStatement ::= + /// 'break' identifier? ';' Statement parseBreakStatement() { Token breakKeyword = getAndAdvance(); SimpleIdentifier label = null; @@ -1063,24 +942,22 @@ return astFactory.breakStatement(breakKeyword, label, semicolon); } - /** - * Parse a cascade section. Return the expression representing the cascaded - * method invocation. - * - * This method assumes that the current token matches - * `TokenType.PERIOD_PERIOD`. - * - * cascadeSection ::= - * '..' (cascadeSelector typeArguments? arguments*) - * (assignableSelector typeArguments? arguments*)* cascadeAssignment? - * - * cascadeSelector ::= - * '[' expression ']' - * | identifier - * - * cascadeAssignment ::= - * assignmentOperator expressionWithoutCascade - */ + /// Parse a cascade section. Return the expression representing the cascaded + /// method invocation. + /// + /// This method assumes that the current token matches + /// `TokenType.PERIOD_PERIOD`. + /// + /// cascadeSection ::= + /// '..' (cascadeSelector typeArguments? arguments*) + /// (assignableSelector typeArguments? arguments*)* cascadeAssignment? + /// + /// cascadeSelector ::= + /// '[' expression ']' + /// | identifier + /// + /// cascadeAssignment ::= + /// assignmentOperator expressionWithoutCascade Expression parseCascadeSection() { Token period = getAndAdvance(); Expression expression = null; @@ -1162,18 +1039,16 @@ return expression; } - /** - * Parse a class declaration. The [commentAndMetadata] is the metadata to be - * associated with the member. The [abstractKeyword] is the token for the - * keyword 'abstract', or `null` if the keyword was not given. Return the - * class declaration that was parsed. - * - * This method assumes that the current token matches `Keyword.CLASS`. - * - * classDeclaration ::= - * metadata 'abstract'? 'class' name typeParameterList? (extendsClause withClause?)? implementsClause? '{' classMembers '}' | - * metadata 'abstract'? 'class' mixinApplicationClass - */ + /// Parse a class declaration. The [commentAndMetadata] is the metadata to be + /// associated with the member. The [abstractKeyword] is the token for the + /// keyword 'abstract', or `null` if the keyword was not given. Return the + /// class declaration that was parsed. + /// + /// This method assumes that the current token matches `Keyword.CLASS`. + /// + /// classDeclaration ::= + /// metadata 'abstract'? 'class' name typeParameterList? (extendsClause withClause?)? implementsClause? '{' classMembers '}' | + /// metadata 'abstract'? 'class' mixinApplicationClass CompilationUnitMember parseClassDeclaration( CommentAndMetadata commentAndMetadata, Token abstractKeyword) { // @@ -1292,15 +1167,13 @@ return classDeclaration; } - /** - * Parse a class member. The [className] is the name of the class containing - * the member being parsed. Return the class member that was parsed, or `null` - * if what was found was not a valid class member. - * - * classMemberDefinition ::= - * declaration ';' - * | methodSignature functionBody - */ + /// Parse a class member. The [className] is the name of the class containing + /// the member being parsed. Return the class member that was parsed, or + /// `null` if what was found was not a valid class member. + /// + /// classMemberDefinition ::= + /// declaration ';' + /// | methodSignature functionBody ClassMember parseClassMember(String className) { CommentAndMetadata commentAndMetadata = parseCommentAndMetadata(); Modifiers modifiers = parseModifiers(); @@ -1648,14 +1521,12 @@ type); } - /** - * Parse a single combinator. Return the combinator that was parsed, or `null` - * if no combinator is found. - * - * combinator ::= - * 'show' identifier (',' identifier)* - * | 'hide' identifier (',' identifier)* - */ + /// Parse a single combinator. Return the combinator that was parsed, or + /// `null` if no combinator is found. + /// + /// combinator ::= + /// 'show' identifier (',' identifier)* + /// | 'hide' identifier (',' identifier)* Combinator parseCombinator() { if (_matchesKeyword(Keyword.SHOW)) { return astFactory.showCombinator(getAndAdvance(), parseIdentifierList()); @@ -1665,14 +1536,12 @@ return null; } - /** - * Parse a list of combinators in a directive. Return the combinators that - * were parsed, or `null` if there are no combinators. - * - * combinator ::= - * 'show' identifier (',' identifier)* - * | 'hide' identifier (',' identifier)* - */ + /// Parse a list of combinators in a directive. Return the combinators that + /// were parsed, or `null` if there are no combinators. + /// + /// combinator ::= + /// 'show' identifier (',' identifier)* + /// | 'hide' identifier (',' identifier)* List<Combinator> parseCombinators() { List<Combinator> combinators = null; while (true) { @@ -1686,16 +1555,14 @@ return combinators; } - /** - * Parse the documentation comment and metadata preceding a declaration. This - * method allows any number of documentation comments to occur before, after - * or between the metadata, but only returns the last (right-most) - * documentation comment that is found. Return the documentation comment and - * metadata that were parsed. - * - * metadata ::= - * annotation* - */ + /// Parse the documentation comment and metadata preceding a declaration. This + /// method allows any number of documentation comments to occur before, after + /// or between the metadata, but only returns the last (right-most) + /// documentation comment that is found. Return the documentation comment and + /// metadata that were parsed. + /// + /// metadata ::= + /// annotation* CommentAndMetadata parseCommentAndMetadata() { // TODO(brianwilkerson) Consider making the creation of documentation // comments be lazy. @@ -1713,16 +1580,14 @@ return new CommentAndMetadata(parseDocumentationComment(tokens), metadata); } - /** - * Parse a comment reference from the source between square brackets. The - * [referenceSource] is the source occurring between the square brackets - * within a documentation comment. The [sourceOffset] is the offset of the - * first character of the reference source. Return the comment reference that - * was parsed, or `null` if no reference could be found. - * - * commentReference ::= - * 'new'? prefixedIdentifier - */ + /// Parse a comment reference from the source between square brackets. The + /// [referenceSource] is the source occurring between the square brackets + /// within a documentation comment. The [sourceOffset] is the offset of the + /// first character of the reference source. Return the comment reference that + /// was parsed, or `null` if no reference could be found. + /// + /// commentReference ::= + /// 'new'? prefixedIdentifier CommentReference parseCommentReference( String referenceSource, int sourceOffset) { // TODO(brianwilkerson) The errors are not getting the right offset/length @@ -1822,18 +1687,16 @@ return null; } - /** - * Parse all of the comment references occurring in the given array of - * documentation comments. The [tokens] are the comment tokens representing - * the documentation comments to be parsed. Return the comment references that - * were parsed. - * - * commentReference ::= - * '[' 'new'? qualified ']' libraryReference? - * - * libraryReference ::= - * '(' stringLiteral ')' - */ + /// Parse all of the comment references occurring in the given array of + /// documentation comments. The [tokens] are the comment tokens representing + /// the documentation comments to be parsed. Return the comment references + /// that were parsed. + /// + /// commentReference ::= + /// '[' 'new'? qualified ']' libraryReference? + /// + /// libraryReference ::= + /// '(' stringLiteral ')' List<CommentReference> parseCommentReferences( List<DocumentationCommentToken> tokens) { List<CommentReference> references = <CommentReference>[]; @@ -1904,32 +1767,28 @@ return references; } - /** - * Parse a compilation unit, starting with the given [token]. Return the - * compilation unit that was parsed. - */ + /// Parse a compilation unit, starting with the given [token]. Return the + /// compilation unit that was parsed. CompilationUnit parseCompilationUnit(Token token) { _currentToken = token; return parseCompilationUnit2(); } - /** - * Parse a compilation unit. Return the compilation unit that was parsed. - * - * Specified: - * - * compilationUnit ::= - * scriptTag? directive* topLevelDeclaration* - * - * Actual: - * - * compilationUnit ::= - * scriptTag? topLevelElement* - * - * topLevelElement ::= - * directive - * | topLevelDeclaration - */ + /// Parse a compilation unit. Return the compilation unit that was parsed. + /// + /// Specified: + /// + /// compilationUnit ::= + /// scriptTag? directive* topLevelDeclaration* + /// + /// Actual: + /// + /// compilationUnit ::= + /// scriptTag? topLevelElement* + /// + /// topLevelElement ::= + /// directive + /// | topLevelDeclaration CompilationUnit parseCompilationUnit2() { Token firstToken = _currentToken; ScriptTag scriptTag = null; @@ -2075,23 +1934,21 @@ firstToken, scriptTag, directives, declarations, _currentToken); } - /** - * Parse a compilation unit member. The [commentAndMetadata] is the metadata - * to be associated with the member. Return the compilation unit member that - * was parsed, or `null` if what was parsed could not be represented as a - * compilation unit member. - * - * compilationUnitMember ::= - * classDefinition - * | functionTypeAlias - * | external functionSignature - * | external getterSignature - * | external setterSignature - * | functionSignature functionBody - * | returnType? getOrSet identifier formalParameterList functionBody - * | (final | const) type? staticFinalDeclarationList ';' - * | variableDeclaration ';' - */ + /// Parse a compilation unit member. The [commentAndMetadata] is the metadata + /// to be associated with the member. Return the compilation unit member that + /// was parsed, or `null` if what was parsed could not be represented as a + /// compilation unit member. + /// + /// compilationUnitMember ::= + /// classDefinition + /// | functionTypeAlias + /// | external functionSignature + /// | external getterSignature + /// | external setterSignature + /// | functionSignature functionBody + /// | returnType? getOrSet identifier formalParameterList functionBody + /// | (final | const) type? staticFinalDeclarationList ';' + /// | variableDeclaration ';' CompilationUnitMember parseCompilationUnitMember( CommentAndMetadata commentAndMetadata) { Modifiers modifiers = parseModifiers(); @@ -2290,13 +2147,11 @@ _expect(TokenType.SEMICOLON)); } - /** - * Parse a conditional expression. Return the conditional expression that was - * parsed. - * - * conditionalExpression ::= - * ifNullExpression ('?' expressionWithoutCascade ':' expressionWithoutCascade)? - */ + /// Parse a conditional expression. Return the conditional expression that was + /// parsed. + /// + /// conditionalExpression ::= + /// ifNullExpression ('?' expressionWithoutCascade ':' expressionWithoutCascade)? Expression parseConditionalExpression() { Expression condition = parseIfNullExpression(); if (_currentToken.type != TokenType.QUESTION) { @@ -2310,20 +2165,18 @@ condition, question, thenExpression, colon, elseExpression); } - /** - * Parse a configuration in either an import or export directive. - * - * This method assumes that the current token matches `Keyword.IF`. - * - * configuration ::= - * 'if' '(' test ')' uri - * - * test ::= - * dottedName ('==' stringLiteral)? - * - * dottedName ::= - * identifier ('.' identifier)* - */ + /// Parse a configuration in either an import or export directive. + /// + /// This method assumes that the current token matches `Keyword.IF`. + /// + /// configuration ::= + /// 'if' '(' test ')' uri + /// + /// test ::= + /// dottedName ('==' stringLiteral)? + /// + /// dottedName ::= + /// identifier ('.' identifier)* Configuration parseConfiguration() { Token ifKeyword = getAndAdvance(); Token leftParenthesis = _expect(TokenType.OPEN_PAREN); @@ -2344,16 +2197,14 @@ equalToken, value, rightParenthesis, libraryUri); } - /** - * Parse a const expression. Return the const expression that was parsed. - * - * This method assumes that the current token matches `Keyword.CONST`. - * - * constExpression ::= - * instanceCreationExpression - * | listLiteral - * | mapLiteral - */ + /// Parse a const expression. Return the const expression that was parsed. + /// + /// This method assumes that the current token matches `Keyword.CONST`. + /// + /// constExpression ::= + /// instanceCreationExpression + /// | listLiteral + /// | mapLiteral Expression parseConstExpression() { Token keyword = getAndAdvance(); TokenType type = _currentToken.type; @@ -2368,14 +2219,12 @@ return parseInstanceCreationExpression(keyword); } - /** - * Parse a field initializer within a constructor. The flag [hasThis] should - * be true if the current token is `this`. Return the field initializer that - * was parsed. - * - * fieldInitializer: - * ('this' '.')? identifier '=' conditionalExpression cascadeSection* - */ + /// Parse a field initializer within a constructor. The flag [hasThis] should + /// be true if the current token is `this`. Return the field initializer that + /// was parsed. + /// + /// fieldInitializer: + /// ('this' '.')? identifier '=' conditionalExpression cascadeSection* ConstructorFieldInitializer parseConstructorFieldInitializer(bool hasThis) { Token keywordToken = null; Token period = null; @@ -2427,13 +2276,11 @@ } } - /** - * Parse the name of a constructor. Return the constructor name that was - * parsed. - * - * constructorName: - * type ('.' identifier)? - */ + /// Parse the name of a constructor. Return the constructor name that was + /// parsed. + /// + /// constructorName: + /// type ('.' identifier)? ConstructorName parseConstructorName() { TypeName type = parseTypeName(false); Token period = null; @@ -2445,14 +2292,12 @@ return astFactory.constructorName(type, period, name); } - /** - * Parse a continue statement. Return the continue statement that was parsed. - * - * This method assumes that the current token matches `Keyword.CONTINUE`. - * - * continueStatement ::= - * 'continue' identifier? ';' - */ + /// Parse a continue statement. Return the continue statement that was parsed. + /// + /// This method assumes that the current token matches `Keyword.CONTINUE`. + /// + /// continueStatement ::= + /// 'continue' identifier? ';' Statement parseContinueStatement() { Token continueKeyword = getAndAdvance(); if (!_inLoop && !_inSwitch) { @@ -2471,16 +2316,14 @@ return astFactory.continueStatement(continueKeyword, label, semicolon); } - /** - * Parse a directive. The [commentAndMetadata] is the metadata to be - * associated with the directive. Return the directive that was parsed. - * - * directive ::= - * exportDirective - * | libraryDirective - * | importDirective - * | partDirective - */ + /// Parse a directive. The [commentAndMetadata] is the metadata to be + /// associated with the directive. Return the directive that was parsed. + /// + /// directive ::= + /// exportDirective + /// | libraryDirective + /// | importDirective + /// | partDirective Directive parseDirective(CommentAndMetadata commentAndMetadata) { if (_matchesKeyword(Keyword.IMPORT)) { return parseImportDirective(commentAndMetadata); @@ -2498,25 +2341,21 @@ } } - /** - * Parse the script tag and directives in a compilation unit, starting with - * the given [token], until the first non-directive is encountered. The - * remainder of the compilation unit will not be parsed. Specifically, if - * there are directives later in the file, they will not be parsed. Return the - * compilation unit that was parsed. - */ + /// Parse the script tag and directives in a compilation unit, starting with + /// the given [token], until the first non-directive is encountered. The + /// remainder of the compilation unit will not be parsed. Specifically, if + /// there are directives later in the file, they will not be parsed. Return + /// the compilation unit that was parsed. CompilationUnit parseDirectives(Token token) { _currentToken = token; return parseDirectives2(); } - /** - * Parse the script tag and directives in a compilation unit until the first - * non-directive is encountered. Return the compilation unit that was parsed. - * - * compilationUnit ::= - * scriptTag? directive* - */ + /// Parse the script tag and directives in a compilation unit until the first + /// non-directive is encountered. Return the compilation unit that was parsed. + /// + /// compilationUnit ::= + /// scriptTag? directive* CompilationUnit parseDirectives2() { Token firstToken = _currentToken; ScriptTag scriptTag = null; @@ -2550,15 +2389,13 @@ firstToken, scriptTag, directives, null, _currentToken); } - /** - * Parse a documentation comment based on the given list of documentation - * comment tokens. Return the documentation comment that was parsed, or `null` - * if there was no comment. - * - * documentationComment ::= - * multiLineComment? - * | singleLineComment* - */ + /// Parse a documentation comment based on the given list of documentation + /// comment tokens. Return the documentation comment that was parsed, or + /// `null` if there was no comment. + /// + /// documentationComment ::= + /// multiLineComment? + /// | singleLineComment* Comment parseDocumentationComment(List<DocumentationCommentToken> tokens) { if (tokens == null) { return null; @@ -2567,14 +2404,12 @@ return astFactory.documentationComment(tokens, references); } - /** - * Parse a documentation comment. Return the documentation comment that was - * parsed, or `null` if there was no comment. - * - * documentationComment ::= - * multiLineComment? - * | singleLineComment* - */ + /// Parse a documentation comment. Return the documentation comment that was + /// parsed, or `null` if there was no comment. + /// + /// documentationComment ::= + /// multiLineComment? + /// | singleLineComment* List<DocumentationCommentToken> parseDocumentationCommentTokens() { List<DocumentationCommentToken> tokens = <DocumentationCommentToken>[]; CommentToken commentToken = _currentToken.precedingComments; @@ -2596,14 +2431,12 @@ return tokens.isEmpty ? null : tokens; } - /** - * Parse a do statement. Return the do statement that was parsed. - * - * This method assumes that the current token matches `Keyword.DO`. - * - * doStatement ::= - * 'do' statement 'while' '(' expression ')' ';' - */ + /// Parse a do statement. Return the do statement that was parsed. + /// + /// This method assumes that the current token matches `Keyword.DO`. + /// + /// doStatement ::= + /// 'do' statement 'while' '(' expression ')' ';' Statement parseDoStatement() { bool wasInLoop = _inLoop; _inLoop = true; @@ -2622,12 +2455,10 @@ } } - /** - * Parse a dotted name. Return the dotted name that was parsed. - * - * dottedName ::= - * identifier ('.' identifier)* - */ + /// Parse a dotted name. Return the dotted name that was parsed. + /// + /// dottedName ::= + /// identifier ('.' identifier)* DottedName parseDottedName() { List<SimpleIdentifier> components = <SimpleIdentifier>[ parseSimpleIdentifier() @@ -2638,25 +2469,21 @@ return astFactory.dottedName(components); } - /** - * Parse an empty statement. Return the empty statement that was parsed. - * - * This method assumes that the current token matches `TokenType.SEMICOLON`. - * - * emptyStatement ::= - * ';' - */ + /// Parse an empty statement. Return the empty statement that was parsed. + /// + /// This method assumes that the current token matches `TokenType.SEMICOLON`. + /// + /// emptyStatement ::= + /// ';' Statement parseEmptyStatement() => astFactory.emptyStatement(getAndAdvance()); - /** - * Parse an enum declaration. The [commentAndMetadata] is the metadata to be - * associated with the member. Return the enum declaration that was parsed. - * - * This method assumes that the current token matches `Keyword.ENUM`. - * - * enumType ::= - * metadata 'enum' id '{' id (',' id)* (',')? '}' - */ + /// Parse an enum declaration. The [commentAndMetadata] is the metadata to be + /// associated with the member. Return the enum declaration that was parsed. + /// + /// This method assumes that the current token matches `Keyword.ENUM`. + /// + /// enumType ::= + /// metadata 'enum' id '{' id (',' id)* (',')? '}' EnumDeclaration parseEnumDeclaration(CommentAndMetadata commentAndMetadata) { Token keyword = getAndAdvance(); SimpleIdentifier name = parseSimpleIdentifier(isDeclaration: true); @@ -2697,14 +2524,12 @@ rightBracket); } - /** - * Parse an equality expression. Return the equality expression that was - * parsed. - * - * equalityExpression ::= - * relationalExpression (equalityOperator relationalExpression)? - * | 'super' equalityOperator relationalExpression - */ + /// Parse an equality expression. Return the equality expression that was + /// parsed. + /// + /// equalityExpression ::= + /// relationalExpression (equalityOperator relationalExpression)? + /// | 'super' equalityOperator relationalExpression Expression parseEqualityExpression() { Expression expression; if (_currentToken.keyword == Keyword.SUPER && @@ -2726,15 +2551,14 @@ return expression; } - /** - * Parse an export directive. The [commentAndMetadata] is the metadata to be - * associated with the directive. Return the export directive that was parsed. - * - * This method assumes that the current token matches `Keyword.EXPORT`. - * - * exportDirective ::= - * metadata 'export' stringLiteral configuration* combinator*';' - */ + /// Parse an export directive. The [commentAndMetadata] is the metadata to be + /// associated with the directive. Return the export directive that was + /// parsed. + /// + /// This method assumes that the current token matches `Keyword.EXPORT`. + /// + /// exportDirective ::= + /// metadata 'export' stringLiteral configuration* combinator*';' ExportDirective parseExportDirective(CommentAndMetadata commentAndMetadata) { Token exportKeyword = getAndAdvance(); StringLiteral libraryUri = _parseUri(); @@ -2751,25 +2575,21 @@ semicolon); } - /** - * Parse an expression, starting with the given [token]. Return the expression - * that was parsed, or `null` if the tokens do not represent a recognizable - * expression. - */ + /// Parse an expression, starting with the given [token]. Return the + /// expression that was parsed, or `null` if the tokens do not represent a + /// recognizable expression. Expression parseExpression(Token token) { _currentToken = token; return parseExpression2(); } - /** - * Parse an expression that might contain a cascade. Return the expression - * that was parsed. - * - * expression ::= - * assignableExpression assignmentOperator expression - * | conditionalExpression cascadeSection* - * | throwExpression - */ + /// Parse an expression that might contain a cascade. Return the expression + /// that was parsed. + /// + /// expression ::= + /// assignableExpression assignmentOperator expression + /// | conditionalExpression cascadeSection* + /// | throwExpression Expression parseExpression2() { if (_treeDepth > _MAX_TREE_DEPTH) { throw new _TooDeepTreeError(); @@ -2812,12 +2632,10 @@ } } - /** - * Parse a list of expressions. Return the expression that was parsed. - * - * expressionList ::= - * expression (',' expression)* - */ + /// Parse a list of expressions. Return the expression that was parsed. + /// + /// expressionList ::= + /// expression (',' expression)* List<Expression> parseExpressionList() { List<Expression> expressions = <Expression>[parseExpression2()]; while (_optional(TokenType.COMMA)) { @@ -2826,15 +2644,13 @@ return expressions; } - /** - * Parse an expression that does not contain any cascades. Return the - * expression that was parsed. - * - * expressionWithoutCascade ::= - * assignableExpression assignmentOperator expressionWithoutCascade - * | conditionalExpression - * | throwExpressionWithoutCascade - */ + /// Parse an expression that does not contain any cascades. Return the + /// expression that was parsed. + /// + /// expressionWithoutCascade ::= + /// assignableExpression assignmentOperator expressionWithoutCascade + /// | conditionalExpression + /// | throwExpressionWithoutCascade Expression parseExpressionWithoutCascade() { if (_matchesKeyword(Keyword.THROW)) { return parseThrowExpressionWithoutCascade(); @@ -2857,32 +2673,28 @@ return expression; } - /** - * Parse a class extends clause. Return the class extends clause that was - * parsed. - * - * This method assumes that the current token matches `Keyword.EXTENDS`. - * - * classExtendsClause ::= - * 'extends' type - */ + /// Parse a class extends clause. Return the class extends clause that was + /// parsed. + /// + /// This method assumes that the current token matches `Keyword.EXTENDS`. + /// + /// classExtendsClause ::= + /// 'extends' type ExtendsClause parseExtendsClause() { Token keyword = getAndAdvance(); TypeName superclass = parseTypeName(false); return astFactory.extendsClause(keyword, superclass); } - /** - * Parse the 'final', 'const', 'var' or type preceding a variable declaration. - * The [optional] is `true` if the keyword and type are optional. Return the - * 'final', 'const', 'var' or type that was parsed. - * - * finalConstVarOrType ::= - * 'final' type? - * | 'const' type? - * | 'var' - * | type - */ + /// Parse the 'final', 'const', 'var' or type preceding a variable + /// declaration. The [optional] is `true` if the keyword and type are + /// optional. Return the 'final', 'const', 'var' or type that was parsed. + /// + /// finalConstVarOrType ::= + /// 'final' type? + /// | 'const' type? + /// | 'var' + /// | type FinalConstVarOrType parseFinalConstVarOrType(bool optional, {bool inFunctionType: false}) { Token keywordToken = null; @@ -2925,19 +2737,17 @@ return new FinalConstVarOrType(keywordToken, type); } - /** - * Parse a formal parameter. At most one of `isOptional` and `isNamed` can be - * `true`. The [kind] is the kind of parameter being expected based on the - * presence or absence of group delimiters. Return the formal parameter that - * was parsed. - * - * defaultFormalParameter ::= - * normalFormalParameter ('=' expression)? - * - * defaultNamedParameter ::= - * normalFormalParameter ('=' expression)? - * normalFormalParameter (':' expression)? - */ + /// Parse a formal parameter. At most one of `isOptional` and `isNamed` can be + /// `true`. The [kind] is the kind of parameter being expected based on the + /// presence or absence of group delimiters. Return the formal parameter that + /// was parsed. + /// + /// defaultFormalParameter ::= + /// normalFormalParameter ('=' expression)? + /// + /// defaultNamedParameter ::= + /// normalFormalParameter ('=' expression)? + /// normalFormalParameter (':' expression)? FormalParameter parseFormalParameter(ParameterKind kind, {bool inFunctionType: false}) { NormalFormalParameter parameter = @@ -3000,28 +2810,26 @@ return parameter; } - /** - * Parse a list of formal parameters. Return the formal parameters that were - * parsed. - * - * formalParameterList ::= - * '(' ')' - * | '(' normalFormalParameters (',' optionalFormalParameters)? ')' - * | '(' optionalFormalParameters ')' - * - * normalFormalParameters ::= - * normalFormalParameter (',' normalFormalParameter)* - * - * optionalFormalParameters ::= - * optionalPositionalFormalParameters - * | namedFormalParameters - * - * optionalPositionalFormalParameters ::= - * '[' defaultFormalParameter (',' defaultFormalParameter)* ']' - * - * namedFormalParameters ::= - * '{' defaultNamedParameter (',' defaultNamedParameter)* '}' - */ + /// Parse a list of formal parameters. Return the formal parameters that were + /// parsed. + /// + /// formalParameterList ::= + /// '(' ')' + /// | '(' normalFormalParameters (',' optionalFormalParameters)? ')' + /// | '(' optionalFormalParameters ')' + /// + /// normalFormalParameters ::= + /// normalFormalParameter (',' normalFormalParameter)* + /// + /// optionalFormalParameters ::= + /// optionalPositionalFormalParameters + /// | namedFormalParameters + /// + /// optionalPositionalFormalParameters ::= + /// '[' defaultFormalParameter (',' defaultFormalParameter)* ']' + /// + /// namedFormalParameters ::= + /// '{' defaultNamedParameter (',' defaultNamedParameter)* '}' FormalParameterList parseFormalParameterList({bool inFunctionType: false}) { if (_matches(TokenType.OPEN_PAREN)) { return _parseFormalParameterListUnchecked(inFunctionType: inFunctionType); @@ -3035,21 +2843,19 @@ _createSyntheticToken(TokenType.OPEN_PAREN)); } - /** - * Parse a for statement. Return the for statement that was parsed. - * - * forStatement ::= - * 'for' '(' forLoopParts ')' statement - * - * forLoopParts ::= - * forInitializerStatement expression? ';' expressionList? - * | declaredIdentifier 'in' expression - * | identifier 'in' expression - * - * forInitializerStatement ::= - * localVariableDeclaration ';' - * | expression? ';' - */ + /// Parse a for statement. Return the for statement that was parsed. + /// + /// forStatement ::= + /// 'for' '(' forLoopParts ')' statement + /// + /// forLoopParts ::= + /// forInitializerStatement expression? ';' expressionList? + /// | declaredIdentifier 'in' expression + /// | identifier 'in' expression + /// + /// forInitializerStatement ::= + /// localVariableDeclaration ';' + /// | expression? ';' Statement parseForStatement() { bool wasInLoop = _inLoop; _inLoop = true; @@ -3181,21 +2987,20 @@ } } - /** - * Parse a function body. The [mayBeEmpty] is `true` if the function body is - * allowed to be empty. The [emptyErrorCode] is the error code to report if - * function body expected, but not found. The [inExpression] is `true` if the - * function body is being parsed as part of an expression and therefore does - * not have a terminating semicolon. Return the function body that was parsed. - * - * functionBody ::= - * '=>' expression ';' - * | block - * - * functionExpressionBody ::= - * '=>' expression - * | block - */ + /// Parse a function body. The [mayBeEmpty] is `true` if the function body is + /// allowed to be empty. The [emptyErrorCode] is the error code to report if + /// function body expected, but not found. The [inExpression] is `true` if the + /// function body is being parsed as part of an expression and therefore does + /// not have a terminating semicolon. Return the function body that was + /// parsed. + /// + /// functionBody ::= + /// '=>' expression ';' + /// | block + /// + /// functionExpressionBody ::= + /// '=>' expression + /// | block FunctionBody parseFunctionBody( bool mayBeEmpty, ParserErrorCode emptyErrorCode, bool inExpression) { bool wasInAsync = _inAsync; @@ -3301,19 +3106,17 @@ } } - /** - * Parse a function declaration. The [commentAndMetadata] is the documentation - * comment and metadata to be associated with the declaration. The - * [externalKeyword] is the 'external' keyword, or `null` if the function is - * not external. The [returnType] is the return type, or `null` if there is no - * return type. The [isStatement] is `true` if the function declaration is - * being parsed as a statement. Return the function declaration that was - * parsed. - * - * functionDeclaration ::= - * functionSignature functionBody - * | returnType? getOrSet identifier formalParameterList functionBody - */ + /// Parse a function declaration. The [commentAndMetadata] is the + /// documentation comment and metadata to be associated with the declaration. + /// The [externalKeyword] is the 'external' keyword, or `null` if the + /// function is not external. The [returnType] is the return type, or `null` + /// if there is no return type. The [isStatement] is `true` if the function + /// declaration is being parsed as a statement. Return the function + /// declaration that was parsed. + /// + /// functionDeclaration ::= + /// functionSignature functionBody + /// | returnType? getOrSet identifier formalParameterList functionBody FunctionDeclaration parseFunctionDeclaration( CommentAndMetadata commentAndMetadata, Token externalKeyword, @@ -3377,13 +3180,11 @@ astFactory.functionExpression(typeParameters, parameters, body)); } - /** - * Parse a function declaration statement. Return the function declaration - * statement that was parsed. - * - * functionDeclarationStatement ::= - * functionSignature functionBody - */ + /// Parse a function declaration statement. Return the function declaration + /// statement that was parsed. + /// + /// functionDeclarationStatement ::= + /// functionSignature functionBody Statement parseFunctionDeclarationStatement() { Modifiers modifiers = parseModifiers(); _validateModifiersForFunctionDeclarationStatement(modifiers); @@ -3391,13 +3192,11 @@ parseCommentAndMetadata(), _parseOptionalReturnType()); } - /** - * Parse a function expression. Return the function expression that was - * parsed. - * - * functionExpression ::= - * typeParameters? formalParameterList functionExpressionBody - */ + /// Parse a function expression. Return the function expression that was + /// parsed. + /// + /// functionExpression ::= + /// typeParameters? formalParameterList functionExpressionBody FunctionExpression parseFunctionExpression() { TypeParameterList typeParameters = _parseGenericMethodTypeParameters(); FormalParameterList parameters = parseFormalParameterList(); @@ -3407,29 +3206,27 @@ return astFactory.functionExpression(typeParameters, parameters, body); } - /** - * Parse the portion of a generic function type following the [returnType]. - * - * functionType ::= - * returnType? 'Function' typeParameters? parameterTypeList - * parameterTypeList ::= - * '(' ')' | - * | '(' normalParameterTypes ','? ')' | - * | '(' normalParameterTypes ',' optionalParameterTypes ')' | - * | '(' optionalParameterTypes ')' - * normalParameterTypes ::= - * normalParameterType (',' normalParameterType)* - * normalParameterType ::= - * type | typedIdentifier - * optionalParameterTypes ::= - * optionalPositionalParameterTypes | namedParameterTypes - * optionalPositionalParameterTypes ::= - * '[' normalParameterTypes ','? ']' - * namedParameterTypes ::= - * '{' typedIdentifier (',' typedIdentifier)* ','? '}' - * typedIdentifier ::= - * type identifier - */ + /// Parse the portion of a generic function type following the [returnType]. + /// + /// functionType ::= + /// returnType? 'Function' typeParameters? parameterTypeList + /// parameterTypeList ::= + /// '(' ')' | + /// | '(' normalParameterTypes ','? ')' | + /// | '(' normalParameterTypes ',' optionalParameterTypes ')' | + /// | '(' optionalParameterTypes ')' + /// normalParameterTypes ::= + /// normalParameterType (',' normalParameterType)* + /// normalParameterType ::= + /// type | typedIdentifier + /// optionalParameterTypes ::= + /// optionalPositionalParameterTypes | namedParameterTypes + /// optionalPositionalParameterTypes ::= + /// '[' normalParameterTypes ','? ']' + /// namedParameterTypes ::= + /// '{' typedIdentifier (',' typedIdentifier)* ','? '}' + /// typedIdentifier ::= + /// type identifier GenericFunctionType parseGenericFunctionTypeAfterReturnType( TypeAnnotation returnType) { Token functionKeyword = null; @@ -3450,14 +3247,12 @@ returnType, functionKeyword, typeParameters, parameters); } - /** - * Parse a generic function type alias. - * - * This method assumes that the current token is an identifier. - * - * genericTypeAlias ::= - * 'typedef' identifier typeParameterList? '=' functionType ';' - */ + /// Parse a generic function type alias. + /// + /// This method assumes that the current token is an identifier. + /// + /// genericTypeAlias ::= + /// 'typedef' identifier typeParameterList? '=' functionType ';' GenericTypeAlias parseGenericTypeAlias( CommentAndMetadata commentAndMetadata, Token keyword) { Identifier name = _parseSimpleIdentifierUnchecked(isDeclaration: true); @@ -3494,22 +3289,20 @@ semicolon); } - /** - * Parse a getter. The [commentAndMetadata] is the documentation comment and - * metadata to be associated with the declaration. The externalKeyword] is the - * 'external' token. The staticKeyword] is the static keyword, or `null` if - * the getter is not static. The [returnType] the return type that has already - * been parsed, or `null` if there was no return type. Return the getter that - * was parsed. - * - * This method assumes that the current token matches `Keyword.GET`. - * - * getter ::= - * getterSignature functionBody? - * - * getterSignature ::= - * 'external'? 'static'? returnType? 'get' identifier - */ + /// Parse a getter. The [commentAndMetadata] is the documentation comment and + /// metadata to be associated with the declaration. The externalKeyword] is + /// the 'external' token. The staticKeyword] is the static keyword, or `null` + /// if the getter is not static. The [returnType] the return type that has + /// already been parsed, or `null` if there was no return type. Return the + /// getter that was parsed. + /// + /// This method assumes that the current token matches `Keyword.GET`. + /// + /// getter ::= + /// getterSignature functionBody? + /// + /// getterSignature ::= + /// 'external'? 'static'? returnType? 'get' identifier MethodDeclaration parseGetter(CommentAndMetadata commentAndMetadata, Token externalKeyword, Token staticKeyword, TypeAnnotation returnType) { Token propertyKeyword = getAndAdvance(); @@ -3541,13 +3334,11 @@ body); } - /** - * Parse a list of identifiers. Return the list of identifiers that were - * parsed. - * - * identifierList ::= - * identifier (',' identifier)* - */ + /// Parse a list of identifiers. Return the list of identifiers that were + /// parsed. + /// + /// identifierList ::= + /// identifier (',' identifier)* List<SimpleIdentifier> parseIdentifierList() { List<SimpleIdentifier> identifiers = <SimpleIdentifier>[ parseSimpleIdentifier() @@ -3558,12 +3349,10 @@ return identifiers; } - /** - * Parse an if-null expression. Return the if-null expression that was - * parsed. - * - * ifNullExpression ::= logicalOrExpression ('??' logicalOrExpression)* - */ + /// Parse an if-null expression. Return the if-null expression that was + /// parsed. + /// + /// ifNullExpression ::= logicalOrExpression ('??' logicalOrExpression)* Expression parseIfNullExpression() { Expression expression = parseLogicalOrExpression(); while (_currentToken.type == TokenType.QUESTION_QUESTION) { @@ -3573,14 +3362,12 @@ return expression; } - /** - * Parse an if statement. Return the if statement that was parsed. - * - * This method assumes that the current token matches `Keyword.IF`. - * - * ifStatement ::= - * 'if' '(' expression ')' statement ('else' statement)? - */ + /// Parse an if statement. Return the if statement that was parsed. + /// + /// This method assumes that the current token matches `Keyword.IF`. + /// + /// ifStatement ::= + /// 'if' '(' expression ')' statement ('else' statement)? Statement parseIfStatement() { Token ifKeyword = getAndAdvance(); Token leftParenthesis = _expect(TokenType.OPEN_PAREN); @@ -3597,14 +3384,12 @@ rightParenthesis, thenStatement, elseKeyword, elseStatement); } - /** - * Parse an implements clause. Return the implements clause that was parsed. - * - * This method assumes that the current token matches `Keyword.IMPLEMENTS`. - * - * implementsClause ::= - * 'implements' type (',' type)* - */ + /// Parse an implements clause. Return the implements clause that was parsed. + /// + /// This method assumes that the current token matches `Keyword.IMPLEMENTS`. + /// + /// implementsClause ::= + /// 'implements' type (',' type)* ImplementsClause parseImplementsClause() { Token keyword = getAndAdvance(); List<TypeName> interfaces = <TypeName>[]; @@ -3615,15 +3400,14 @@ return astFactory.implementsClause(keyword, interfaces); } - /** - * Parse an import directive. The [commentAndMetadata] is the metadata to be - * associated with the directive. Return the import directive that was parsed. - * - * This method assumes that the current token matches `Keyword.IMPORT`. - * - * importDirective ::= - * metadata 'import' stringLiteral configuration* (deferred)? ('as' identifier)? combinator*';' - */ + /// Parse an import directive. The [commentAndMetadata] is the metadata to be + /// associated with the directive. Return the import directive that was + /// parsed. + /// + /// This method assumes that the current token matches `Keyword.IMPORT`. + /// + /// importDirective ::= + /// metadata 'import' stringLiteral configuration* (deferred)? ('as' identifier)? combinator*';' ImportDirective parseImportDirective(CommentAndMetadata commentAndMetadata) { Token importKeyword = getAndAdvance(); StringLiteral libraryUri = _parseUri(); @@ -3671,25 +3455,23 @@ semicolon); } - /** - * Parse a list of initialized identifiers. The [commentAndMetadata] is the - * documentation comment and metadata to be associated with the declaration. - * The [staticKeyword] is the static keyword, or `null` if the getter is not - * static. The [keyword] is the token representing the 'final', 'const' or - * 'var' keyword, or `null` if there is no keyword. The [type] is the type - * that has already been parsed, or `null` if 'var' was provided. Return the - * getter that was parsed. - * - * declaration ::= - * ('static' | 'covariant')? ('var' | type) initializedIdentifierList ';' - * | 'final' type? initializedIdentifierList ';' - * - * initializedIdentifierList ::= - * initializedIdentifier (',' initializedIdentifier)* - * - * initializedIdentifier ::= - * identifier ('=' expression)? - */ + /// Parse a list of initialized identifiers. The [commentAndMetadata] is the + /// documentation comment and metadata to be associated with the declaration. + /// The [staticKeyword] is the static keyword, or `null` if the getter is not + /// static. The [keyword] is the token representing the 'final', 'const' or + /// 'var' keyword, or `null` if there is no keyword. The [type] is the type + /// that has already been parsed, or `null` if 'var' was provided. Return the + /// getter that was parsed. + /// + /// declaration ::= + /// ('static' | 'covariant')? ('var' | type) initializedIdentifierList ';' + /// | 'final' type? initializedIdentifierList ';' + /// + /// initializedIdentifierList ::= + /// initializedIdentifier (',' initializedIdentifier)* + /// + /// initializedIdentifier ::= + /// identifier ('=' expression)? FieldDeclaration parseInitializedIdentifierList( CommentAndMetadata commentAndMetadata, Token staticKeyword, @@ -3707,14 +3489,12 @@ semicolon: _expect(TokenType.SEMICOLON)); } - /** - * Parse an instance creation expression. The [keyword] is the 'new' or - * 'const' keyword that introduces the expression. Return the instance - * creation expression that was parsed. - * - * instanceCreationExpression ::= - * ('new' | 'const') type ('.' identifier)? argumentList - */ + /// Parse an instance creation expression. The [keyword] is the 'new' or + /// 'const' keyword that introduces the expression. Return the instance + /// creation expression that was parsed. + /// + /// instanceCreationExpression ::= + /// ('new' | 'const') type ('.' identifier)? argumentList InstanceCreationExpression parseInstanceCreationExpression(Token keyword) { ConstructorName constructorName = parseConstructorName(); ArgumentList argumentList = _parseArgumentListChecked(); @@ -3722,15 +3502,13 @@ keyword, constructorName, argumentList); } - /** - * Parse a label. Return the label that was parsed. - * - * This method assumes that the current token matches an identifier and that - * the following token matches `TokenType.COLON`. - * - * label ::= - * identifier ':' - */ + /// Parse a label. Return the label that was parsed. + /// + /// This method assumes that the current token matches an identifier and that + /// the following token matches `TokenType.COLON`. + /// + /// label ::= + /// identifier ':' Label parseLabel({bool isDeclaration: false}) { SimpleIdentifier label = _parseSimpleIdentifierUnchecked(isDeclaration: isDeclaration); @@ -3738,16 +3516,14 @@ return astFactory.label(label, colon); } - /** - * Parse a library directive. The [commentAndMetadata] is the metadata to be - * associated with the directive. Return the library directive that was - * parsed. - * - * This method assumes that the current token matches `Keyword.LIBRARY`. - * - * libraryDirective ::= - * metadata 'library' identifier ';' - */ + /// Parse a library directive. The [commentAndMetadata] is the metadata to be + /// associated with the directive. Return the library directive that was + /// parsed. + /// + /// This method assumes that the current token matches `Keyword.LIBRARY`. + /// + /// libraryDirective ::= + /// metadata 'library' identifier ';' LibraryDirective parseLibraryDirective( CommentAndMetadata commentAndMetadata) { Token keyword = getAndAdvance(); @@ -3758,12 +3534,10 @@ commentAndMetadata.metadata, keyword, libraryName, semicolon); } - /** - * Parse a library identifier. Return the library identifier that was parsed. - * - * libraryIdentifier ::= - * identifier ('.' identifier)* - */ + /// Parse a library identifier. Return the library identifier that was parsed. + /// + /// libraryIdentifier ::= + /// identifier ('.' identifier)* LibraryIdentifier parseLibraryIdentifier() { List<SimpleIdentifier> components = <SimpleIdentifier>[]; components.add(parseSimpleIdentifier()); @@ -3773,18 +3547,16 @@ return astFactory.libraryIdentifier(components); } - /** - * Parse a list literal. The [modifier] is the 'const' modifier appearing - * before the literal, or `null` if there is no modifier. The [typeArguments] - * is the type arguments appearing before the literal, or `null` if there are - * no type arguments. Return the list literal that was parsed. - * - * This method assumes that the current token matches either - * `TokenType.OPEN_SQUARE_BRACKET` or `TokenType.INDEX`. - * - * listLiteral ::= - * 'const'? typeArguments? '[' (expressionList ','?)? ']' - */ + /// Parse a list literal. The [modifier] is the 'const' modifier appearing + /// before the literal, or `null` if there is no modifier. The [typeArguments] + /// is the type arguments appearing before the literal, or `null` if there are + /// no type arguments. Return the list literal that was parsed. + /// + /// This method assumes that the current token matches either + /// `TokenType.OPEN_SQUARE_BRACKET` or `TokenType.INDEX`. + /// + /// listLiteral ::= + /// 'const'? typeArguments? '[' (expressionList ','?)? ']' ListLiteral parseListLiteral(Token modifier, TypeArgumentList typeArguments) { if (_matches(TokenType.INDEX)) { _splitIndex(); @@ -3815,15 +3587,13 @@ } } - /** - * Parse a list or map literal. The [modifier] is the 'const' modifier - * appearing before the literal, or `null` if there is no modifier. Return the - * list or map literal that was parsed. - * - * listOrMapLiteral ::= - * listLiteral - * | mapLiteral - */ + /// Parse a list or map literal. The [modifier] is the 'const' modifier + /// appearing before the literal, or `null` if there is no modifier. Return + /// the list or map literal that was parsed. + /// + /// listOrMapLiteral ::= + /// listLiteral + /// | mapLiteral TypedLiteral parseListOrMapLiteral(Token modifier) { TypeArgumentList typeArguments = _parseOptionalTypeArguments(); if (_matches(TokenType.OPEN_CURLY_BRACKET)) { @@ -3841,13 +3611,11 @@ _createSyntheticToken(TokenType.CLOSE_SQUARE_BRACKET)); } - /** - * Parse a logical and expression. Return the logical and expression that was - * parsed. - * - * logicalAndExpression ::= - * equalityExpression ('&&' equalityExpression)* - */ + /// Parse a logical and expression. Return the logical and expression that was + /// parsed. + /// + /// logicalAndExpression ::= + /// equalityExpression ('&&' equalityExpression)* Expression parseLogicalAndExpression() { Expression expression = parseEqualityExpression(); while (_currentToken.type == TokenType.AMPERSAND_AMPERSAND) { @@ -3857,13 +3625,11 @@ return expression; } - /** - * Parse a logical or expression. Return the logical or expression that was - * parsed. - * - * logicalOrExpression ::= - * logicalAndExpression ('||' logicalAndExpression)* - */ + /// Parse a logical or expression. Return the logical or expression that was + /// parsed. + /// + /// logicalOrExpression ::= + /// logicalAndExpression ('||' logicalAndExpression)* Expression parseLogicalOrExpression() { Expression expression = parseLogicalAndExpression(); while (_currentToken.type == TokenType.BAR_BAR) { @@ -3873,18 +3639,16 @@ return expression; } - /** - * Parse a map literal. The [modifier] is the 'const' modifier appearing - * before the literal, or `null` if there is no modifier. The [typeArguments] - * is the type arguments that were declared, or `null` if there are no type - * arguments. Return the map literal that was parsed. - * - * This method assumes that the current token matches - * `TokenType.OPEN_CURLY_BRACKET`. - * - * mapLiteral ::= - * 'const'? typeArguments? '{' (mapLiteralEntry (',' mapLiteralEntry)* ','?)? '}' - */ + /// Parse a map literal. The [modifier] is the 'const' modifier appearing + /// before the literal, or `null` if there is no modifier. The [typeArguments] + /// is the type arguments that were declared, or `null` if there are no type + /// arguments. Return the map literal that was parsed. + /// + /// This method assumes that the current token matches + /// `TokenType.OPEN_CURLY_BRACKET`. + /// + /// mapLiteral ::= + /// 'const'? typeArguments? '{' (mapLiteralEntry (',' mapLiteralEntry)* ','?)? '}' MapLiteral parseMapLiteral(Token modifier, TypeArgumentList typeArguments) { Token leftBracket = getAndAdvance(); if (_matches(TokenType.CLOSE_CURLY_BRACKET)) { @@ -3910,12 +3674,10 @@ } } - /** - * Parse a map literal entry. Return the map literal entry that was parsed. - * - * mapLiteralEntry ::= - * expression ':' expression - */ + /// Parse a map literal entry. Return the map literal entry that was parsed. + /// + /// mapLiteralEntry ::= + /// expression ':' expression MapLiteralEntry parseMapLiteralEntry() { Expression key = parseExpression2(); Token separator = _expect(TokenType.COLON); @@ -3923,17 +3685,15 @@ return astFactory.mapLiteralEntry(key, separator, value); } - /** - * Parse the modifiers preceding a declaration. This method allows the - * modifiers to appear in any order but does generate errors for duplicated - * modifiers. Checks for other problems, such as having the modifiers appear - * in the wrong order or specifying both 'const' and 'final', are reported in - * one of the methods whose name is prefixed with `validateModifiersFor`. - * Return the modifiers that were parsed. - * - * modifiers ::= - * ('abstract' | 'const' | 'external' | 'factory' | 'final' | 'static' | 'var')* - */ + /// Parse the modifiers preceding a declaration. This method allows the + /// modifiers to appear in any order but does generate errors for duplicated + /// modifiers. Checks for other problems, such as having the modifiers appear + /// in the wrong order or specifying both 'const' and 'final', are reported in + /// one of the methods whose name is prefixed with `validateModifiersFor`. + /// Return the modifiers that were parsed. + /// + /// modifiers ::= + /// ('abstract' | 'const' | 'external' | 'factory' | 'final' | 'static' | 'var')* Modifiers parseModifiers() { Modifiers modifiers = new Modifiers(); bool progress = true; @@ -4016,14 +3776,12 @@ return modifiers; } - /** - * Parse a multiplicative expression. Return the multiplicative expression - * that was parsed. - * - * multiplicativeExpression ::= - * unaryExpression (multiplicativeOperator unaryExpression)* - * | 'super' (multiplicativeOperator unaryExpression)+ - */ + /// Parse a multiplicative expression. Return the multiplicative expression + /// that was parsed. + /// + /// multiplicativeExpression ::= + /// unaryExpression (multiplicativeOperator unaryExpression)* + /// | 'super' (multiplicativeOperator unaryExpression)+ Expression parseMultiplicativeExpression() { Expression expression; if (_currentToken.keyword == Keyword.SUPER && @@ -4039,37 +3797,33 @@ return expression; } - /** - * Parse a new expression. Return the new expression that was parsed. - * - * This method assumes that the current token matches `Keyword.NEW`. - * - * newExpression ::= - * instanceCreationExpression - */ + /// Parse a new expression. Return the new expression that was parsed. + /// + /// This method assumes that the current token matches `Keyword.NEW`. + /// + /// newExpression ::= + /// instanceCreationExpression InstanceCreationExpression parseNewExpression() => parseInstanceCreationExpression(getAndAdvance()); - /** - * Parse a non-labeled statement. Return the non-labeled statement that was - * parsed. - * - * nonLabeledStatement ::= - * block - * | assertStatement - * | breakStatement - * | continueStatement - * | doStatement - * | forStatement - * | ifStatement - * | returnStatement - * | switchStatement - * | tryStatement - * | whileStatement - * | variableDeclarationList ';' - * | expressionStatement - * | functionSignature functionBody - */ + /// Parse a non-labeled statement. Return the non-labeled statement that was + /// parsed. + /// + /// nonLabeledStatement ::= + /// block + /// | assertStatement + /// | breakStatement + /// | continueStatement + /// | doStatement + /// | forStatement + /// | ifStatement + /// | returnStatement + /// | switchStatement + /// | tryStatement + /// | whileStatement + /// | variableDeclarationList ';' + /// | expressionStatement + /// | functionSignature functionBody Statement parseNonLabeledStatement() { // TODO(brianwilkerson) Pass the comment and metadata on where appropriate. CommentAndMetadata commentAndMetadata = parseCommentAndMetadata(); @@ -4269,25 +4023,23 @@ } } - /** - * Parse a normal formal parameter. Return the normal formal parameter that - * was parsed. - * - * normalFormalParameter ::= - * functionSignature - * | fieldFormalParameter - * | simpleFormalParameter - * - * functionSignature: - * metadata returnType? identifier typeParameters? formalParameterList - * - * fieldFormalParameter ::= - * metadata finalConstVarOrType? 'this' '.' identifier - * - * simpleFormalParameter ::= - * declaredIdentifier - * | metadata identifier - */ + /// Parse a normal formal parameter. Return the normal formal parameter that + /// was parsed. + /// + /// normalFormalParameter ::= + /// functionSignature + /// | fieldFormalParameter + /// | simpleFormalParameter + /// + /// functionSignature: + /// metadata returnType? identifier typeParameters? formalParameterList + /// + /// fieldFormalParameter ::= + /// metadata finalConstVarOrType? 'this' '.' identifier + /// + /// simpleFormalParameter ::= + /// declaredIdentifier + /// | metadata identifier NormalFormalParameter parseNormalFormalParameter( {bool inFunctionType: false}) { Token covariantKeyword; @@ -4387,19 +4139,17 @@ astFactory.simpleIdentifier(identifier.token, isDeclaration: true)); } - /** - * Parse an operator declaration. The [commentAndMetadata] is the - * documentation comment and metadata to be associated with the declaration. - * The [externalKeyword] is the 'external' token. The [returnType] is the - * return type that has already been parsed, or `null` if there was no return - * type. Return the operator declaration that was parsed. - * - * operatorDeclaration ::= - * operatorSignature (';' | functionBody) - * - * operatorSignature ::= - * 'external'? returnType? 'operator' operator formalParameterList - */ + /// Parse an operator declaration. The [commentAndMetadata] is the + /// documentation comment and metadata to be associated with the declaration. + /// The [externalKeyword] is the 'external' token. The [returnType] is the + /// return type that has already been parsed, or `null` if there was no return + /// type. Return the operator declaration that was parsed. + /// + /// operatorDeclaration ::= + /// operatorSignature (';' | functionBody) + /// + /// operatorSignature ::= + /// 'external'? returnType? 'operator' operator formalParameterList MethodDeclaration parseOperator(CommentAndMetadata commentAndMetadata, Token externalKeyword, TypeName returnType) { Token operatorKeyword; @@ -4414,19 +4164,17 @@ commentAndMetadata, externalKeyword, returnType, operatorKeyword); } - /** - * Parse a part or part-of directive. The [commentAndMetadata] is the metadata - * to be associated with the directive. Return the part or part-of directive - * that was parsed. - * - * This method assumes that the current token matches `Keyword.PART`. - * - * partDirective ::= - * metadata 'part' stringLiteral ';' - * - * partOfDirective ::= - * metadata 'part' 'of' identifier ';' - */ + /// Parse a part or part-of directive. The [commentAndMetadata] is the + /// metadata to be associated with the directive. Return the part or part-of + /// directive that was parsed. + /// + /// This method assumes that the current token matches `Keyword.PART`. + /// + /// partDirective ::= + /// metadata 'part' stringLiteral ';' + /// + /// partOfDirective ::= + /// metadata 'part' 'of' identifier ';' Directive parsePartOrPartOfDirective(CommentAndMetadata commentAndMetadata) { if (_tokenMatchesKeyword(_peek(), Keyword.OF)) { return _parsePartOfDirective(commentAndMetadata); @@ -4434,17 +4182,15 @@ return _parsePartDirective(commentAndMetadata); } - /** - * Parse a postfix expression. Return the postfix expression that was parsed. - * - * postfixExpression ::= - * assignableExpression postfixOperator - * | primary selector* - * - * selector ::= - * assignableSelector - * | argumentPart - */ + /// Parse a postfix expression. Return the postfix expression that was parsed. + /// + /// postfixExpression ::= + /// assignableExpression postfixOperator + /// | primary selector* + /// + /// selector ::= + /// assignableSelector + /// | argumentPart Expression parsePostfixExpression() { Expression operand = parseAssignableExpression(true); TokenType type = _currentToken.type; @@ -4499,40 +4245,36 @@ return astFactory.postfixExpression(operand, operator); } - /** - * Parse a prefixed identifier. Return the prefixed identifier that was - * parsed. - * - * prefixedIdentifier ::= - * identifier ('.' identifier)? - */ + /// Parse a prefixed identifier. Return the prefixed identifier that was + /// parsed. + /// + /// prefixedIdentifier ::= + /// identifier ('.' identifier)? Identifier parsePrefixedIdentifier() { return _parsePrefixedIdentifierAfterIdentifier(parseSimpleIdentifier()); } - /** - * Parse a primary expression. Return the primary expression that was parsed. - * - * primary ::= - * thisExpression - * | 'super' unconditionalAssignableSelector - * | functionExpression - * | literal - * | identifier - * | newExpression - * | constObjectExpression - * | '(' expression ')' - * | argumentDefinitionTest - * - * literal ::= - * nullLiteral - * | booleanLiteral - * | numericLiteral - * | stringLiteral - * | symbolLiteral - * | mapLiteral - * | listLiteral - */ + /// Parse a primary expression. Return the primary expression that was parsed. + /// + /// primary ::= + /// thisExpression + /// | 'super' unconditionalAssignableSelector + /// | functionExpression + /// | literal + /// | identifier + /// | newExpression + /// | constObjectExpression + /// | '(' expression ')' + /// | argumentDefinitionTest + /// + /// literal ::= + /// nullLiteral + /// | booleanLiteral + /// | numericLiteral + /// | stringLiteral + /// | symbolLiteral + /// | mapLiteral + /// | listLiteral Expression parsePrimaryExpression() { if (_matchesIdentifier()) { // TODO(brianwilkerson) The code below was an attempt to recover from an @@ -4646,16 +4388,14 @@ } } - /** - * Parse a redirecting constructor invocation. The flag [hasPeriod] should be - * `true` if the `this` is followed by a period. Return the redirecting - * constructor invocation that was parsed. - * - * This method assumes that the current token matches `Keyword.THIS`. - * - * redirectingConstructorInvocation ::= - * 'this' ('.' identifier)? arguments - */ + /// Parse a redirecting constructor invocation. The flag [hasPeriod] should be + /// `true` if the `this` is followed by a period. Return the redirecting + /// constructor invocation that was parsed. + /// + /// This method assumes that the current token matches `Keyword.THIS`. + /// + /// redirectingConstructorInvocation ::= + /// 'this' ('.' identifier)? arguments RedirectingConstructorInvocation parseRedirectingConstructorInvocation( bool hasPeriod) { Token keyword = getAndAdvance(); @@ -4676,14 +4416,12 @@ keyword, period, constructorName, argumentList); } - /** - * Parse a relational expression. Return the relational expression that was - * parsed. - * - * relationalExpression ::= - * bitwiseOrExpression ('is' '!'? type | 'as' type | relationalOperator bitwiseOrExpression)? - * | 'super' relationalOperator bitwiseOrExpression - */ + /// Parse a relational expression. Return the relational expression that was + /// parsed. + /// + /// relationalExpression ::= + /// bitwiseOrExpression ('is' '!'? type | 'as' type | relationalOperator bitwiseOrExpression)? + /// | 'super' relationalOperator bitwiseOrExpression Expression parseRelationalExpression() { if (_currentToken.keyword == Keyword.SUPER && _currentToken.next.type.isRelationalOperator) { @@ -4714,25 +4452,21 @@ return expression; } - /** - * Parse a rethrow expression. Return the rethrow expression that was parsed. - * - * This method assumes that the current token matches `Keyword.RETHROW`. - * - * rethrowExpression ::= - * 'rethrow' - */ + /// Parse a rethrow expression. Return the rethrow expression that was parsed. + /// + /// This method assumes that the current token matches `Keyword.RETHROW`. + /// + /// rethrowExpression ::= + /// 'rethrow' Expression parseRethrowExpression() => astFactory.rethrowExpression(getAndAdvance()); - /** - * Parse a return statement. Return the return statement that was parsed. - * - * This method assumes that the current token matches `Keyword.RETURN`. - * - * returnStatement ::= - * 'return' expression? ';' - */ + /// Parse a return statement. Return the return statement that was parsed. + /// + /// This method assumes that the current token matches `Keyword.RETURN`. + /// + /// returnStatement ::= + /// 'return' expression? ';' Statement parseReturnStatement() { Token returnKeyword = getAndAdvance(); if (_matches(TokenType.SEMICOLON)) { @@ -4743,22 +4477,20 @@ return astFactory.returnStatement(returnKeyword, expression, semicolon); } - /** - * Parse a setter. The [commentAndMetadata] is the documentation comment and - * metadata to be associated with the declaration. The [externalKeyword] is - * the 'external' token. The [staticKeyword] is the static keyword, or `null` - * if the setter is not static. The [returnType] is the return type that has - * already been parsed, or `null` if there was no return type. Return the - * setter that was parsed. - * - * This method assumes that the current token matches `Keyword.SET`. - * - * setter ::= - * setterSignature functionBody? - * - * setterSignature ::= - * 'external'? 'static'? returnType? 'set' identifier formalParameterList - */ + /// Parse a setter. The [commentAndMetadata] is the documentation comment and + /// metadata to be associated with the declaration. The [externalKeyword] is + /// the 'external' token. The [staticKeyword] is the static keyword, or `null` + /// if the setter is not static. The [returnType] is the return type that has + /// already been parsed, or `null` if there was no return type. Return the + /// setter that was parsed. + /// + /// This method assumes that the current token matches `Keyword.SET`. + /// + /// setter ::= + /// setterSignature functionBody? + /// + /// setterSignature ::= + /// 'external'? 'static'? returnType? 'set' identifier formalParameterList MethodDeclaration parseSetter(CommentAndMetadata commentAndMetadata, Token externalKeyword, Token staticKeyword, TypeAnnotation returnType) { Token propertyKeyword = getAndAdvance(); @@ -4786,13 +4518,11 @@ body); } - /** - * Parse a shift expression. Return the shift expression that was parsed. - * - * shiftExpression ::= - * additiveExpression (shiftOperator additiveExpression)* - * | 'super' (shiftOperator additiveExpression)+ - */ + /// Parse a shift expression. Return the shift expression that was parsed. + /// + /// shiftExpression ::= + /// additiveExpression (shiftOperator additiveExpression)* + /// | 'super' (shiftOperator additiveExpression)+ Expression parseShiftExpression() { Expression expression; if (_currentToken.keyword == Keyword.SUPER && @@ -4808,12 +4538,10 @@ return expression; } - /** - * Parse a simple identifier. Return the simple identifier that was parsed. - * - * identifier ::= - * IDENTIFIER - */ + /// Parse a simple identifier. Return the simple identifier that was parsed. + /// + /// identifier ::= + /// IDENTIFIER SimpleIdentifier parseSimpleIdentifier( {bool allowKeyword: false, bool isDeclaration: false}) { if (_matchesIdentifier() || @@ -4824,22 +4552,18 @@ return createSyntheticIdentifier(isDeclaration: isDeclaration); } - /** - * Parse a statement, starting with the given [token]. Return the statement - * that was parsed, or `null` if the tokens do not represent a recognizable - * statement. - */ + /// Parse a statement, starting with the given [token]. Return the statement + /// that was parsed, or `null` if the tokens do not represent a recognizable + /// statement. Statement parseStatement(Token token) { _currentToken = token; return parseStatement2(); } - /** - * Parse a statement. Return the statement that was parsed. - * - * statement ::= - * label* nonLabeledStatement - */ + /// Parse a statement. Return the statement that was parsed. + /// + /// statement ::= + /// label* nonLabeledStatement Statement parseStatement2() { if (_treeDepth > _MAX_TREE_DEPTH) { throw new _TooDeepTreeError(); @@ -4866,23 +4590,19 @@ } } - /** - * Parse a sequence of statements, starting with the given [token]. Return the - * statements that were parsed, or `null` if the tokens do not represent a - * recognizable sequence of statements. - */ + /// Parse a sequence of statements, starting with the given [token]. Return + /// the statements that were parsed, or `null` if the tokens do not represent + /// a recognizable sequence of statements. List<Statement> parseStatements(Token token) { _currentToken = token; return _parseStatementList(); } - /** - * Parse a string literal. Return the string literal that was parsed. - * - * stringLiteral ::= - * MULTI_LINE_STRING+ - * | SINGLE_LINE_STRING+ - */ + /// Parse a string literal. Return the string literal that was parsed. + /// + /// stringLiteral ::= + /// MULTI_LINE_STRING+ + /// | SINGLE_LINE_STRING+ StringLiteral parseStringLiteral() { if (_matches(TokenType.STRING)) { return _parseStringLiteralUnchecked(); @@ -4891,15 +4611,13 @@ return createSyntheticStringLiteral(); } - /** - * Parse a super constructor invocation. Return the super constructor - * invocation that was parsed. - * - * This method assumes that the current token matches [Keyword.SUPER]. - * - * superConstructorInvocation ::= - * 'super' ('.' identifier)? arguments - */ + /// Parse a super constructor invocation. Return the super constructor + /// invocation that was parsed. + /// + /// This method assumes that the current token matches [Keyword.SUPER]. + /// + /// superConstructorInvocation ::= + /// 'super' ('.' identifier)? arguments SuperConstructorInvocation parseSuperConstructorInvocation() { Token keyword = getAndAdvance(); Token period = null; @@ -4913,18 +4631,16 @@ keyword, period, constructorName, argumentList); } - /** - * Parse a switch statement. Return the switch statement that was parsed. - * - * switchStatement ::= - * 'switch' '(' expression ')' '{' switchCase* defaultCase? '}' - * - * switchCase ::= - * label* ('case' expression ':') statements - * - * defaultCase ::= - * label* 'default' ':' statements - */ + /// Parse a switch statement. Return the switch statement that was parsed. + /// + /// switchStatement ::= + /// 'switch' '(' expression ')' '{' switchCase* defaultCase? '}' + /// + /// switchCase ::= + /// label* ('case' expression ':') statements + /// + /// defaultCase ::= + /// label* 'default' ':' statements SwitchStatement parseSwitchStatement() { bool wasInSwitch = _inSwitch; _inSwitch = true; @@ -5005,14 +4721,12 @@ } } - /** - * Parse a symbol literal. Return the symbol literal that was parsed. - * - * This method assumes that the current token matches [TokenType.HASH]. - * - * symbolLiteral ::= - * '#' identifier ('.' identifier)* - */ + /// Parse a symbol literal. Return the symbol literal that was parsed. + /// + /// This method assumes that the current token matches [TokenType.HASH]. + /// + /// symbolLiteral ::= + /// '#' identifier ('.' identifier)* SymbolLiteral parseSymbolLiteral() { Token poundSign = getAndAdvance(); List<Token> components = <Token>[]; @@ -5038,14 +4752,12 @@ return astFactory.symbolLiteral(poundSign, components); } - /** - * Parse a throw expression. Return the throw expression that was parsed. - * - * This method assumes that the current token matches [Keyword.THROW]. - * - * throwExpression ::= - * 'throw' expression - */ + /// Parse a throw expression. Return the throw expression that was parsed. + /// + /// This method assumes that the current token matches [Keyword.THROW]. + /// + /// throwExpression ::= + /// 'throw' expression Expression parseThrowExpression() { Token keyword = getAndAdvance(); TokenType type = _currentToken.type; @@ -5058,14 +4770,12 @@ return astFactory.throwExpression(keyword, expression); } - /** - * Parse a throw expression. Return the throw expression that was parsed. - * - * This method assumes that the current token matches [Keyword.THROW]. - * - * throwExpressionWithoutCascade ::= - * 'throw' expressionWithoutCascade - */ + /// Parse a throw expression. Return the throw expression that was parsed. + /// + /// This method assumes that the current token matches [Keyword.THROW]. + /// + /// throwExpressionWithoutCascade ::= + /// 'throw' expressionWithoutCascade Expression parseThrowExpressionWithoutCascade() { Token keyword = getAndAdvance(); TokenType type = _currentToken.type; @@ -5078,24 +4788,22 @@ return astFactory.throwExpression(keyword, expression); } - /** - * Parse a try statement. Return the try statement that was parsed. - * - * This method assumes that the current token matches [Keyword.TRY]. - * - * tryStatement ::= - * 'try' block (onPart+ finallyPart? | finallyPart) - * - * onPart ::= - * catchPart block - * | 'on' type catchPart? block - * - * catchPart ::= - * 'catch' '(' identifier (',' identifier)? ')' - * - * finallyPart ::= - * 'finally' block - */ + /// Parse a try statement. Return the try statement that was parsed. + /// + /// This method assumes that the current token matches [Keyword.TRY]. + /// + /// tryStatement ::= + /// 'try' block (onPart+ finallyPart? | finallyPart) + /// + /// onPart ::= + /// catchPart block + /// | 'on' type catchPart? block + /// + /// catchPart ::= + /// 'catch' '(' identifier (',' identifier)? ')' + /// + /// finallyPart ::= + /// 'finally' block Statement parseTryStatement() { Token tryKeyword = getAndAdvance(); Block body = _parseBlockChecked(); @@ -5147,25 +4855,23 @@ tryKeyword, body, catchClauses, finallyKeyword, finallyClause); } - /** - * Parse a type alias. The [commentAndMetadata] is the metadata to be - * associated with the member. Return the type alias that was parsed. - * - * This method assumes that the current token matches [Keyword.TYPEDEF]. - * - * typeAlias ::= - * 'typedef' typeAliasBody - * | genericTypeAlias - * - * typeAliasBody ::= - * functionTypeAlias - * - * functionTypeAlias ::= - * functionPrefix typeParameterList? formalParameterList ';' - * - * functionPrefix ::= - * returnType? name - */ + /// Parse a type alias. The [commentAndMetadata] is the metadata to be + /// associated with the member. Return the type alias that was parsed. + /// + /// This method assumes that the current token matches [Keyword.TYPEDEF]. + /// + /// typeAlias ::= + /// 'typedef' typeAliasBody + /// | genericTypeAlias + /// + /// typeAliasBody ::= + /// functionTypeAlias + /// + /// functionTypeAlias ::= + /// functionPrefix typeParameterList? formalParameterList ';' + /// + /// functionPrefix ::= + /// returnType? name TypeAlias parseTypeAlias(CommentAndMetadata commentAndMetadata) { Token keyword = getAndAdvance(); if (_matchesIdentifier()) { @@ -5186,13 +4892,11 @@ return _parseFunctionTypeAlias(commentAndMetadata, keyword); } - /** - * Parse a type. - * - * type ::= - * typeWithoutFunction - * | functionType - */ + /// Parse a type. + /// + /// type ::= + /// typeWithoutFunction + /// | functionType TypeAnnotation parseTypeAnnotation(bool inExpression) { TypeAnnotation type = null; if (_atGenericFunctionTypeAfterReturnType(_currentToken)) { @@ -5207,18 +4911,16 @@ return type; } - /** - * Parse a list of type arguments. Return the type argument list that was - * parsed. - * - * This method assumes that the current token matches `TokenType.LT`. - * - * typeArguments ::= - * '<' typeList '>' - * - * typeList ::= - * type (',' type)* - */ + /// Parse a list of type arguments. Return the type argument list that was + /// parsed. + /// + /// This method assumes that the current token matches `TokenType.LT`. + /// + /// typeArguments ::= + /// '<' typeList '>' + /// + /// typeList ::= + /// type (',' type)* TypeArgumentList parseTypeArgumentList() { Token leftBracket = getAndAdvance(); List<TypeAnnotation> arguments = <TypeAnnotation>[ @@ -5231,26 +4933,22 @@ return astFactory.typeArgumentList(leftBracket, arguments, rightBracket); } - /** - * Parse a type which is not void and is not a function type. Return the type - * that was parsed. - * - * typeNotVoidWithoutFunction ::= - * qualified typeArguments? - */ + /// Parse a type which is not void and is not a function type. Return the type + /// that was parsed. + /// + /// typeNotVoidWithoutFunction ::= + /// qualified typeArguments? // TODO(eernst): Rename this to `parseTypeNotVoidWithoutFunction`? // Apparently, it was named `parseTypeName` before type arguments existed. TypeName parseTypeName(bool inExpression) { return _parseTypeName(inExpression); } - /** - * Parse a type which is not `void`. - * - * typeNotVoid ::= - * functionType - * | typeNotVoidWithoutFunction - */ + /// Parse a type which is not `void`. + /// + /// typeNotVoid ::= + /// functionType + /// | typeNotVoidWithoutFunction TypeAnnotation parseTypeNotVoid(bool inExpression) { TypeAnnotation type = null; if (_atGenericFunctionTypeAfterReturnType(_currentToken)) { @@ -5269,12 +4967,10 @@ return type; } - /** - * Parse a type parameter. Return the type parameter that was parsed. - * - * typeParameter ::= - * metadata name ('extends' bound)? - */ + /// Parse a type parameter. Return the type parameter that was parsed. + /// + /// typeParameter ::= + /// metadata name ('extends' bound)? TypeParameter parseTypeParameter() { CommentAndMetadata commentAndMetadata = parseCommentAndMetadata(); SimpleIdentifier name = parseSimpleIdentifier(isDeclaration: true); @@ -5288,15 +4984,13 @@ commentAndMetadata.metadata, name, null, null); } - /** - * Parse a list of type parameters. Return the list of type parameters that - * were parsed. - * - * This method assumes that the current token matches `TokenType.LT`. - * - * typeParameterList ::= - * '<' typeParameter (',' typeParameter)* '>' - */ + /// Parse a list of type parameters. Return the list of type parameters that + /// were parsed. + /// + /// This method assumes that the current token matches `TokenType.LT`. + /// + /// typeParameterList ::= + /// '<' typeParameter (',' typeParameter)* '>' TypeParameterList parseTypeParameterList() { Token leftBracket = getAndAdvance(); List<TypeParameter> typeParameters = <TypeParameter>[parseTypeParameter()]; @@ -5308,13 +5002,11 @@ leftBracket, typeParameters, rightBracket); } - /** - * Parse a type which is not a function type. - * - * typeWithoutFunction ::= - * `void` - * | typeNotVoidWithoutFunction - */ + /// Parse a type which is not a function type. + /// + /// typeWithoutFunction ::= + /// `void` + /// | typeNotVoidWithoutFunction TypeAnnotation parseTypeWithoutFunction(bool inExpression) { if (_currentToken.keyword == Keyword.VOID) { return astFactory.typeName( @@ -5324,17 +5016,15 @@ } } - /** - * Parse a unary expression. Return the unary expression that was parsed. - * - * unaryExpression ::= - * prefixOperator unaryExpression - * | awaitExpression - * | postfixExpression - * | unaryOperator 'super' - * | '-' 'super' - * | incrementOperator assignableExpression - */ + /// Parse a unary expression. Return the unary expression that was parsed. + /// + /// unaryExpression ::= + /// prefixOperator unaryExpression + /// | awaitExpression + /// | postfixExpression + /// | unaryOperator 'super' + /// | '-' 'super' + /// | incrementOperator assignableExpression Expression parseUnaryExpression() { TokenType type = _currentToken.type; if (type == TokenType.MINUS || @@ -5400,13 +5090,11 @@ return parsePostfixExpression(); } - /** - * Parse a variable declaration. Return the variable declaration that was - * parsed. - * - * variableDeclaration ::= - * identifier ('=' expression)? - */ + /// Parse a variable declaration. Return the variable declaration that was + /// parsed. + /// + /// variableDeclaration ::= + /// identifier ('=' expression)? VariableDeclaration parseVariableDeclaration() { // TODO(paulberry): prior to the fix for bug 23204, we permitted // annotations before variable declarations (e.g. "String @deprecated s;"). @@ -5427,14 +5115,12 @@ return astFactory.variableDeclaration(name, equals, initializer); } - /** - * Parse a variable declaration list. The [commentAndMetadata] is the metadata - * to be associated with the variable declaration list. Return the variable - * declaration list that was parsed. - * - * variableDeclarationList ::= - * finalConstVarOrType variableDeclaration (',' variableDeclaration)* - */ + /// Parse a variable declaration list. The [commentAndMetadata] is the + /// metadata to be associated with the variable declaration list. Return the + /// variable declaration list that was parsed. + /// + /// variableDeclarationList ::= + /// finalConstVarOrType variableDeclaration (',' variableDeclaration)* VariableDeclarationList parseVariableDeclarationListAfterMetadata( CommentAndMetadata commentAndMetadata) { FinalConstVarOrType holder = parseFinalConstVarOrType(false); @@ -5442,17 +5128,15 @@ commentAndMetadata, holder.keyword, holder.type); } - /** - * Parse a variable declaration list. The [commentAndMetadata] is the metadata - * to be associated with the variable declaration list, or `null` if there is - * no attempt at parsing the comment and metadata. The [keyword] is the token - * representing the 'final', 'const' or 'var' keyword, or `null` if there is - * no keyword. The [type] is the type of the variables in the list. Return the - * variable declaration list that was parsed. - * - * variableDeclarationList ::= - * finalConstVarOrType variableDeclaration (',' variableDeclaration)* - */ + /// Parse a variable declaration list. The [commentAndMetadata] is the + /// metadata to be associated with the variable declaration list, or `null` + /// if there is no attempt at parsing the comment and metadata. The [keyword] + /// is the token representing the 'final', 'const' or 'var' keyword, or + /// `null` if there is no keyword. The [type] is the type of the variables in + /// the list. Return the variable declaration list that was parsed. + /// + /// variableDeclarationList ::= + /// finalConstVarOrType variableDeclaration (',' variableDeclaration)* VariableDeclarationList parseVariableDeclarationListAfterType( CommentAndMetadata commentAndMetadata, Token keyword, @@ -5472,15 +5156,13 @@ commentAndMetadata?.metadata, keyword, type, variables); } - /** - * Parse a variable declaration statement. The [commentAndMetadata] is the - * metadata to be associated with the variable declaration statement, or - * `null` if there is no attempt at parsing the comment and metadata. Return - * the variable declaration statement that was parsed. - * - * variableDeclarationStatement ::= - * variableDeclarationList ';' - */ + /// Parse a variable declaration statement. The [commentAndMetadata] is the + /// metadata to be associated with the variable declaration statement, or + /// `null` if there is no attempt at parsing the comment and metadata. Return + /// the variable declaration statement that was parsed. + /// + /// variableDeclarationStatement ::= + /// variableDeclarationList ';' VariableDeclarationStatement parseVariableDeclarationStatementAfterMetadata( CommentAndMetadata commentAndMetadata) { // Token startToken = currentToken; @@ -5496,14 +5178,12 @@ return astFactory.variableDeclarationStatement(variableList, semicolon); } - /** - * Parse a while statement. Return the while statement that was parsed. - * - * This method assumes that the current token matches [Keyword.WHILE]. - * - * whileStatement ::= - * 'while' '(' expression ')' statement - */ + /// Parse a while statement. Return the while statement that was parsed. + /// + /// This method assumes that the current token matches [Keyword.WHILE]. + /// + /// whileStatement ::= + /// 'while' '(' expression ')' statement Statement parseWhileStatement() { bool wasInLoop = _inLoop; _inLoop = true; @@ -5520,14 +5200,12 @@ } } - /** - * Parse a with clause. Return the with clause that was parsed. - * - * This method assumes that the current token matches `Keyword.WITH`. - * - * withClause ::= - * 'with' typeName (',' typeName)* - */ + /// Parse a with clause. Return the with clause that was parsed. + /// + /// This method assumes that the current token matches `Keyword.WITH`. + /// + /// withClause ::= + /// 'with' typeName (',' typeName)* WithClause parseWithClause() { Token withKeyword = getAndAdvance(); List<TypeName> types = <TypeName>[]; @@ -5538,14 +5216,12 @@ return astFactory.withClause(withKeyword, types); } - /** - * Parse a yield statement. Return the yield statement that was parsed. - * - * This method assumes that the current token matches [Keyword.YIELD]. - * - * yieldStatement ::= - * 'yield' '*'? expression ';' - */ + /// Parse a yield statement. Return the yield statement that was parsed. + /// + /// This method assumes that the current token matches [Keyword.YIELD]. + /// + /// yieldStatement ::= + /// 'yield' '*'? expression ';' YieldStatement parseYieldStatement() { Token yieldToken = getAndAdvance(); Token star = null; @@ -5557,14 +5233,12 @@ return astFactory.yieldStatement(yieldToken, star, expression, semicolon); } - /** - * Parse a formal parameter list, starting at the [startToken], without - * actually creating a formal parameter list or changing the current token. - * Return the token following the parameter list that was parsed, or `null` - * if the given token is not the first token in a valid parameter list. - * - * This method must be kept in sync with [parseFormalParameterList]. - */ + /// Parse a formal parameter list, starting at the [startToken], without + /// actually creating a formal parameter list or changing the current token. + /// Return the token following the parameter list that was parsed, or `null` + /// if the given token is not the first token in a valid parameter list. + /// + /// This method must be kept in sync with [parseFormalParameterList]. Token skipFormalParameterList(Token startToken) { if (!_tokenMatches(startToken, TokenType.OPEN_PAREN)) { return null; @@ -5572,16 +5246,14 @@ return (startToken as BeginToken).endToken?.next; } - /** - * Parse the portion of a generic function type after the return type, - * starting at the [startToken], without actually creating a generic function - * type or changing the current token. Return the token following the generic - * function type that was parsed, or `null` if the given token is not the - * first token in a valid generic function type. - * - * This method must be kept in sync with - * [parseGenericFunctionTypeAfterReturnType]. - */ + /// Parse the portion of a generic function type after the return type, + /// starting at the [startToken], without actually creating a generic function + /// type or changing the current token. Return the token following the generic + /// function type that was parsed, or `null` if the given token is not the + /// first token in a valid generic function type. + /// + /// This method must be kept in sync with + /// [parseGenericFunctionTypeAfterReturnType]. Token skipGenericFunctionTypeAfterReturnType(Token startToken) { Token next = startToken.next; // Skip 'Function' if (_tokenMatches(next, TokenType.LT)) { @@ -5593,17 +5265,16 @@ return skipFormalParameterList(next); } - /** - * Parse a prefixed identifier, starting at the [startToken], without actually - * creating a prefixed identifier or changing the current token. Return the - * token following the prefixed identifier that was parsed, or `null` if the - * given token is not the first token in a valid prefixed identifier. - * - * This method must be kept in sync with [parsePrefixedIdentifier]. - * - * prefixedIdentifier ::= - * identifier ('.' identifier)? - */ + /// Parse a prefixed identifier, starting at the [startToken], without + /// actually creating a prefixed identifier or changing the current token. + /// Return the token following the prefixed identifier that was parsed, or + /// `null` if the given token is not the first token in a valid prefixed + /// identifier. + /// + /// This method must be kept in sync with [parsePrefixedIdentifier]. + /// + /// prefixedIdentifier ::= + /// identifier ('.' identifier)? Token skipPrefixedIdentifier(Token startToken) { Token token = skipSimpleIdentifier(startToken); if (token == null) { @@ -5625,17 +5296,15 @@ return null; } - /** - * Parse a simple identifier, starting at the [startToken], without actually - * creating a simple identifier or changing the current token. Return the - * token following the simple identifier that was parsed, or `null` if the - * given token is not the first token in a valid simple identifier. - * - * This method must be kept in sync with [parseSimpleIdentifier]. - * - * identifier ::= - * IDENTIFIER - */ + /// Parse a simple identifier, starting at the [startToken], without actually + /// creating a simple identifier or changing the current token. Return the + /// token following the simple identifier that was parsed, or `null` if the + /// given token is not the first token in a valid simple identifier. + /// + /// This method must be kept in sync with [parseSimpleIdentifier]. + /// + /// identifier ::= + /// IDENTIFIER Token skipSimpleIdentifier(Token startToken) { if (_tokenMatches(startToken, TokenType.IDENTIFIER) || _tokenMatchesPseudoKeyword(startToken)) { @@ -5644,18 +5313,16 @@ return null; } - /** - * Parse a string literal, starting at the [startToken], without actually - * creating a string literal or changing the current token. Return the token - * following the string literal that was parsed, or `null` if the given token - * is not the first token in a valid string literal. - * - * This method must be kept in sync with [parseStringLiteral]. - * - * stringLiteral ::= - * MULTI_LINE_STRING+ - * | SINGLE_LINE_STRING+ - */ + /// Parse a string literal, starting at the [startToken], without actually + /// creating a string literal or changing the current token. Return the token + /// following the string literal that was parsed, or `null` if the given token + /// is not the first token in a valid string literal. + /// + /// This method must be kept in sync with [parseStringLiteral]. + /// + /// stringLiteral ::= + /// MULTI_LINE_STRING+ + /// | SINGLE_LINE_STRING+ Token skipStringLiteral(Token startToken) { Token token = startToken; while (token != null && _tokenMatches(token, TokenType.STRING)) { @@ -5672,14 +5339,12 @@ return token; } - /** - * Parse a type annotation, starting at the [startToken], without actually - * creating a type annotation or changing the current token. Return the token - * following the type annotation that was parsed, or `null` if the given token - * is not the first token in a valid type annotation. - * - * This method must be kept in sync with [parseTypeAnnotation]. - */ + /// Parse a type annotation, starting at the [startToken], without actually + /// creating a type annotation or changing the current token. Return the token + /// following the type annotation that was parsed, or `null` if the given + /// token is not the first token in a valid type annotation. + /// + /// This method must be kept in sync with [parseTypeAnnotation]. Token skipTypeAnnotation(Token startToken) { Token next = null; if (_atGenericFunctionTypeAfterReturnType(startToken)) { @@ -5694,21 +5359,19 @@ return next; } - /** - * Parse a list of type arguments, starting at the [startToken], without - * actually creating a type argument list or changing the current token. - * Return the token following the type argument list that was parsed, or - * `null` if the given token is not the first token in a valid type argument - * list. - * - * This method must be kept in sync with [parseTypeArgumentList]. - * - * typeArguments ::= - * '<' typeList '>' - * - * typeList ::= - * type (',' type)* - */ + /// Parse a list of type arguments, starting at the [startToken], without + /// actually creating a type argument list or changing the current token. + /// Return the token following the type argument list that was parsed, or + /// `null` if the given token is not the first token in a valid type argument + /// list. + /// + /// This method must be kept in sync with [parseTypeArgumentList]. + /// + /// typeArguments ::= + /// '<' typeList '>' + /// + /// typeList ::= + /// type (',' type)* Token skipTypeArgumentList(Token startToken) { Token token = startToken; if (!_tokenMatches(token, TokenType.LT)) { @@ -5740,17 +5403,15 @@ return null; } - /** - * Parse a type name, starting at the [startToken], without actually creating - * a type name or changing the current token. Return the token following the - * type name that was parsed, or `null` if the given token is not the first - * token in a valid type name. - * - * This method must be kept in sync with [parseTypeName]. - * - * type ::= - * qualified typeArguments? - */ + /// Parse a type name, starting at the [startToken], without actually creating + /// a type name or changing the current token. Return the token following the + /// type name that was parsed, or `null` if the given token is not the first + /// token in a valid type name. + /// + /// This method must be kept in sync with [parseTypeName]. + /// + /// type ::= + /// qualified typeArguments? Token skipTypeName(Token startToken) { Token token = skipPrefixedIdentifier(startToken); if (token == null) { @@ -5762,14 +5423,13 @@ return token; } - /** - * Parse a type parameter list, starting at the [startToken], without actually - * creating a type parameter list or changing the current token. Return the - * token following the type parameter list that was parsed, or `null` if the - * given token is not the first token in a valid type parameter list. - * - * This method must be kept in sync with [parseTypeParameterList]. - */ + /// Parse a type parameter list, starting at the [startToken], without + /// actually creating a type parameter list or changing the current token. + /// Return the token following the type parameter list that was parsed, or + /// `null` if the given token is not the first token in a valid type parameter + /// list. + /// + /// This method must be kept in sync with [parseTypeParameterList]. Token skipTypeParameterList(Token startToken) { if (!_tokenMatches(startToken, TokenType.LT)) { return null; @@ -5792,14 +5452,12 @@ return null; } - /** - * Parse a typeWithoutFunction, starting at the [startToken], without actually - * creating a TypeAnnotation or changing the current token. Return the token - * following the typeWithoutFunction that was parsed, or `null` if the given - * token is not the first token in a valid typeWithoutFunction. - * - * This method must be kept in sync with [parseTypeWithoutFunction]. - */ + /// Parse a typeWithoutFunction, starting at the [startToken], without + /// actually creating a TypeAnnotation or changing the current token. Return + /// the token following the typeWithoutFunction that was parsed, or `null` if + /// the given token is not the first token in a valid typeWithoutFunction. + /// + /// This method must be kept in sync with [parseTypeWithoutFunction]. Token skipTypeWithoutFunction(Token startToken) { if (startToken.keyword == Keyword.VOID) { return startToken.next; @@ -5808,20 +5466,16 @@ } } - /** - * Advance to the next token in the token stream. - */ + /// Advance to the next token in the token stream. void _advance() { _currentToken = _currentToken.next; } - /** - * Append the character equivalent of the given [codePoint] to the given - * [builder]. Use the [startIndex] and [endIndex] to report an error, and - * don't append anything to the builder, if the code point is invalid. The - * [escapeSequence] is the escape sequence that was parsed to produce the - * code point (used for error reporting). - */ + /// Append the character equivalent of the given [codePoint] to the given + /// [builder]. Use the [startIndex] and [endIndex] to report an error, and + /// don't append anything to the builder, if the code point is invalid. The + /// [escapeSequence] is the escape sequence that was parsed to produce the + /// code point (used for error reporting). void _appendCodePoint(StringBuffer buffer, String source, int codePoint, int startIndex, int endIndex) { if (codePoint < 0 || codePoint > Character.MAX_CODE_POINT) { @@ -5837,10 +5491,8 @@ } } - /** - * Return `true` if we are positioned at the keyword 'Function' in a generic - * function type alias. - */ + /// Return `true` if we are positioned at the keyword 'Function' in a generic + /// function type alias. bool _atGenericFunctionTypeAfterReturnType(Token startToken) { if (_tokenMatchesKeyword(startToken, Keyword.FUNCTION)) { Token next = startToken.next; @@ -5853,11 +5505,9 @@ return false; } - /** - * Convert the given [method] declaration into the nearest valid top-level - * function declaration (that is, the function declaration that most closely - * captures the components of the given method declaration). - */ + /// Convert the given [method] declaration into the nearest valid top-level + /// function declaration (that is, the function declaration that most closely + /// captures the components of the given method declaration). FunctionDeclaration _convertToFunctionDeclaration(MethodDeclaration method) => astFactory.functionDeclaration( method.documentationComment, @@ -5869,12 +5519,10 @@ astFactory.functionExpression( method.typeParameters, method.parameters, method.body)); - /** - * Return `true` if the current token could be the start of a compilation unit - * member. This method is used for recovery purposes to decide when to stop - * skipping tokens after finding an error while parsing a compilation unit - * member. - */ + /// Return `true` if the current token could be the start of a compilation + /// unit member. This method is used for recovery purposes to decide when to + /// stop skipping tokens after finding an error while parsing a compilation + /// unit member. bool _couldBeStartOfCompilationUnitMember() { Keyword keyword = _currentToken.keyword; Token next = _currentToken.next; @@ -5921,23 +5569,17 @@ return false; } - /** - * Return a synthetic token representing the given [keyword]. - */ + /// Return a synthetic token representing the given [keyword]. Token _createSyntheticKeyword(Keyword keyword) => _injectToken(new SyntheticKeywordToken(keyword, _currentToken.offset)); - /** - * Return a synthetic token with the given [type]. - */ + /// Return a synthetic token with the given [type]. Token _createSyntheticToken(TokenType type) => _injectToken(new StringToken(type, "", _currentToken.offset)); - /** - * Create and return a new token with the given [type]. The token will replace - * the first portion of the given [token], so it will have the same offset and - * will have any comments that might have preceeded the token. - */ + /// Create and return a new token with the given [type]. The token will + /// replace the first portion of the given [token], so it will have the same + /// offset and will have any comments that might have preceeded the token. Token _createToken(Token token, TokenType type, {bool isBegin: false}) { CommentToken comments = token.precedingComments; if (comments == null) { @@ -5951,23 +5593,21 @@ return new Token(type, token.offset, comments); } - /** - * Check that the given [expression] is assignable and report an error if it - * isn't. - * - * assignableExpression ::= - * primary (arguments* assignableSelector)+ - * | 'super' unconditionalAssignableSelector - * | identifier - * - * unconditionalAssignableSelector ::= - * '[' expression ']' - * | '.' identifier - * - * assignableSelector ::= - * unconditionalAssignableSelector - * | '?.' identifier - */ + /// Check that the given [expression] is assignable and report an error if it + /// isn't. + /// + /// assignableExpression ::= + /// primary (arguments* assignableSelector)+ + /// | 'super' unconditionalAssignableSelector + /// | identifier + /// + /// unconditionalAssignableSelector ::= + /// '[' expression ']' + /// | '.' identifier + /// + /// assignableSelector ::= + /// unconditionalAssignableSelector + /// | '?.' identifier void _ensureAssignable(Expression expression) { if (expression != null && !expression.isAssignable) { _reportErrorForCurrentToken( @@ -5975,16 +5615,14 @@ } } - /** - * If the current token has the expected type, return it after advancing to - * the next token. Otherwise report an error and return the current token - * without advancing. - * - * Note that the method [_expectGt] should be used if the argument to this - * method would be [TokenType.GT]. - * - * The [type] is the type of token that is expected. - */ + /// If the current token has the expected type, return it after advancing to + /// the next token. Otherwise report an error and return the current token + /// without advancing. + /// + /// Note that the method [_expectGt] should be used if the argument to this + /// method would be [TokenType.GT]. + /// + /// The [type] is the type of token that is expected. Token _expect(TokenType type) { if (_matches(type)) { return getAndAdvance(); @@ -6006,10 +5644,9 @@ return _createSyntheticToken(type); } - /** - * If the current token has the type [TokenType.GT], return it after advancing - * to the next token. Otherwise report an error and create a synthetic token. - */ + /// If the current token has the type [TokenType.GT], return it after + /// advancing to the next token. Otherwise report an error and create a + /// synthetic token. Token _expectGt() { if (_matchesGt()) { return getAndAdvance(); @@ -6019,11 +5656,9 @@ return _createSyntheticToken(TokenType.GT); } - /** - * If the current token is a keyword matching the given [keyword], return it - * after advancing to the next token. Otherwise report an error and return the - * current token without advancing. - */ + /// If the current token is a keyword matching the given [keyword], return it + /// after advancing to the next token. Otherwise report an error and return + /// the current token without advancing. Token _expectKeyword(Keyword keyword) { if (_matchesKeyword(keyword)) { return getAndAdvance(); @@ -6035,11 +5670,9 @@ return _currentToken; } - /** - * Search the given list of [ranges] for a range that contains the given - * [index]. Return the range that was found, or `null` if none of the ranges - * contain the index. - */ + /// Search the given list of [ranges] for a range that contains the given + /// [index]. Return the range that was found, or `null` if none of the ranges + /// contain the index. List<int> _findRange(List<List<int>> ranges, int index) { int rangeCount = ranges.length; for (int i = 0; i < rangeCount; i++) { @@ -6053,10 +5686,8 @@ return null; } - /** - * Return a list of the ranges of characters in the given [comment] that - * should be treated as code blocks. - */ + /// Return a list of the ranges of characters in the given [comment] that + /// should be treated as code blocks. List<List<int>> _getCodeBlockRanges(String comment) { List<List<int>> ranges = <List<int>>[]; int length = comment.length; @@ -6118,11 +5749,9 @@ return ranges; } - /** - * Return the end token associated with the given [beginToken], or `null` if - * either the given token is not a begin token or it does not have an end - * token associated with it. - */ + /// Return the end token associated with the given [beginToken], or `null` if + /// either the given token is not a begin token or it does not have an end + /// token associated with it. Token _getEndToken(Token beginToken) { if (beginToken is BeginToken) { return beginToken.endToken; @@ -6130,10 +5759,8 @@ return null; } - /** - * Inject the given [token] into the token stream immediately before the - * current token. - */ + /// Inject the given [token] into the token stream immediately before the + /// current token. Token _injectToken(Token token) { Token previous = _currentToken.previous; token.setNext(_currentToken); @@ -6141,9 +5768,7 @@ return token; } - /** - * Return `true` if the given [character] is a valid hexadecimal digit. - */ + /// Return `true` if the given [character] is a valid hexadecimal digit. bool _isHexDigit(int character) => (0x30 <= character && character <= 0x39) || (0x41 <= character && character <= 0x46) || @@ -6159,13 +5784,11 @@ return token != null && _tokenMatches(token, TokenType.OPEN_PAREN); } - /** - * Return `true` if it looks like we have found the invocation of a named - * constructor following the name of the type: - * ``` - * typeArguments? '.' identifier '(' - * ``` - */ + /// Return `true` if it looks like we have found the invocation of a named + /// constructor following the name of the type: + /// ``` + /// typeArguments? '.' identifier '(' + /// ``` bool _isLikelyNamedInstanceCreation() { Token token = skipTypeArgumentList(_currentToken); if (token != null && _tokenMatches(token, TokenType.PERIOD)) { @@ -6177,17 +5800,16 @@ return false; } - /** - * Given that we have just found bracketed text within the given [comment], - * look to see whether that text is (a) followed by a parenthesized link - * address, (b) followed by a colon, or (c) followed by optional whitespace - * and another square bracket. The [rightIndex] is the index of the right - * bracket. Return `true` if the bracketed text is followed by a link address. - * - * This method uses the syntax described by the - * <a href="http://daringfireball.net/projects/markdown/syntax">markdown</a> - * project. - */ + /// Given that we have just found bracketed text within the given [comment], + /// look to see whether that text is (a) followed by a parenthesized link + /// address, (b) followed by a colon, or (c) followed by optional whitespace + /// and another square bracket. The [rightIndex] is the index of the right + /// bracket. Return `true` if the bracketed text is followed by a link + /// address. + /// + /// This method uses the syntax described by the + /// <a href="http://daringfireball.net/projects/markdown/syntax">markdown</a> + /// project. bool _isLinkText(String comment, int rightIndex) { int length = comment.length; int index = rightIndex + 1; @@ -6208,10 +5830,8 @@ return nextChar == 0x5B; } - /** - * Return `true` if the given [startToken] appears to be the beginning of an - * operator declaration. - */ + /// Return `true` if the given [startToken] appears to be the beginning of an + /// operator declaration. bool _isOperator(Token startToken) { // Accept any operator here, even if it is not user definable. if (!startToken.isOperator) { @@ -6235,10 +5855,8 @@ return token != null && _tokenMatches(token, TokenType.OPEN_PAREN); } - /** - * Return `true` if the [startToken] appears to be the first token of a type - * name that is followed by a variable or field formal parameter. - */ + /// Return `true` if the [startToken] appears to be the first token of a type + /// name that is followed by a variable or field formal parameter. bool _isTypedIdentifier(Token startToken) { Token token = skipTypeAnnotation(startToken); if (token == null) { @@ -6258,10 +5876,8 @@ return false; } - /** - * Return `true` if the given [expression] is a primary expression that is - * allowed to be an assignable expression without any assignable selector. - */ + /// Return `true` if the given [expression] is a primary expression that is + /// allowed to be an assignable expression without any assignable selector. bool _isValidAssignableExpression(Expression expression) { if (expression is SimpleIdentifier) { return true; @@ -6273,28 +5889,22 @@ return false; } - /** - * Increments the error reporting lock level. If level is more than `0`, then - * [reportError] wont report any error. - */ + /// Increments the error reporting lock level. If level is more than `0`, then + /// [reportError] wont report any error. void _lockErrorListener() { _errorListenerLock++; } - /** - * Return `true` if the current token has the given [type]. Note that the - * method [_matchesGt] should be used if the argument to this method would be - * [TokenType.GT]. - */ + /// Return `true` if the current token has the given [type]. Note that the + /// method [_matchesGt] should be used if the argument to this method would be + /// [TokenType.GT]. bool _matches(TokenType type) => _currentToken.type == type; - /** - * Return `true` if the current token has a type of [TokenType.GT]. Note that - * this method, unlike other variants, will modify the token stream if - * possible to match desired type. In particular, if the next token is either - * a '>>' or '>>>', the token stream will be re-written and `true` will be - * returned. - */ + /// Return `true` if the current token has a type of [TokenType.GT]. Note that + /// this method, unlike other variants, will modify the token stream if + /// possible to match desired type. In particular, if the next token is either + /// a '>>' or '>>>', the token stream will be re-written and `true` will be + /// returned. bool _matchesGt() { TokenType currentType = _currentToken.type; if (currentType == TokenType.GT) { @@ -6330,23 +5940,17 @@ return false; } - /** - * Return `true` if the current token is a valid identifier. Valid identifiers - * include built-in identifiers (pseudo-keywords). - */ + /// Return `true` if the current token is a valid identifier. Valid + /// identifiers include built-in identifiers (pseudo-keywords). bool _matchesIdentifier() => _tokenMatchesIdentifier(_currentToken); - /** - * Return `true` if the current token matches the given [keyword]. - */ + /// Return `true` if the current token matches the given [keyword]. bool _matchesKeyword(Keyword keyword) => _tokenMatchesKeyword(_currentToken, keyword); - /** - * If the current token has the given [type], then advance to the next token - * and return `true`. Otherwise, return `false` without advancing. This method - * should not be invoked with an argument value of [TokenType.GT]. - */ + /// If the current token has the given [type], then advance to the next token + /// and return `true`. Otherwise, return `false` without advancing. This + /// method should not be invoked with an argument value of [TokenType.GT]. bool _optional(TokenType type) { if (_currentToken.type == type) { _advance(); @@ -6355,10 +5959,8 @@ return false; } - /** - * Parse an argument list when we need to check for an open paren and recover - * when there isn't one. Return the argument list that was parsed. - */ + /// Parse an argument list when we need to check for an open paren and recover + /// when there isn't one. Return the argument list that was parsed. ArgumentList _parseArgumentListChecked() { if (_matches(TokenType.OPEN_PAREN)) { return parseArgumentList(); @@ -6371,14 +5973,13 @@ null, _createSyntheticToken(TokenType.CLOSE_PAREN)); } - /** - * Parse an assert within a constructor's initializer list. Return the assert. - * - * This method assumes that the current token matches `Keyword.ASSERT`. - * - * assertInitializer ::= - * 'assert' '(' expression [',' expression] ')' - */ + /// Parse an assert within a constructor's initializer list. Return the + /// assert. + /// + /// This method assumes that the current token matches `Keyword.ASSERT`. + /// + /// assertInitializer ::= + /// 'assert' '(' expression [',' expression] ')' AssertInitializer _parseAssertInitializer() { Token keyword = getAndAdvance(); Token leftParen = _expect(TokenType.OPEN_PAREN); @@ -6401,13 +6002,11 @@ keyword, leftParen, expression, comma, message, rightParen); } - /** - * Parse a block when we need to check for an open curly brace and recover - * when there isn't one. Return the block that was parsed. - * - * block ::= - * '{' statements '}' - */ + /// Parse a block when we need to check for an open curly brace and recover + /// when there isn't one. Return the block that was parsed. + /// + /// block ::= + /// '{' statements '}' Block _parseBlockChecked() { if (_matches(TokenType.OPEN_CURLY_BRACKET)) { return parseBlock(); @@ -6421,15 +6020,13 @@ null, _createSyntheticToken(TokenType.CLOSE_CURLY_BRACKET)); } - /** - * Parse a list of class members. The [className] is the name of the class - * whose members are being parsed. The [closingBracket] is the closing bracket - * for the class, or `null` if the closing bracket is missing. Return the list - * of class members that were parsed. - * - * classMembers ::= - * (metadata memberDefinition)* - */ + /// Parse a list of class members. The [className] is the name of the class + /// whose members are being parsed. The [closingBracket] is the closing + /// bracket for the class, or `null` if the closing bracket is missing. + /// Return the list of class members that were parsed. + /// + /// classMembers ::= + /// (metadata memberDefinition)* List<ClassMember> _parseClassMembers(String className, Token closingBracket) { List<ClassMember> members = <ClassMember>[]; Token memberStart = _currentToken; @@ -6461,20 +6058,18 @@ return members; } - /** - * Parse a class type alias. The [commentAndMetadata] is the metadata to be - * associated with the member. The [abstractKeyword] is the token representing - * the 'abstract' keyword. The [classKeyword] is the token representing the - * 'class' keyword. The [className] is the name of the alias, and the - * [typeParameters] are the type parameters following the name. Return the - * class type alias that was parsed. - * - * classTypeAlias ::= - * identifier typeParameters? '=' 'abstract'? mixinApplication - * - * mixinApplication ::= - * type withClause implementsClause? ';' - */ + /// Parse a class type alias. The [commentAndMetadata] is the metadata to be + /// associated with the member. The [abstractKeyword] is the token + /// representing the 'abstract' keyword. The [classKeyword] is the token + /// representing the 'class' keyword. The [className] is the name of the + /// alias, and the [typeParameters] are the type parameters following the + /// name. Return the class type alias that was parsed. + /// + /// classTypeAlias ::= + /// identifier typeParameters? '=' 'abstract'? mixinApplication + /// + /// mixinApplication ::= + /// type withClause implementsClause? ';' ClassTypeAlias _parseClassTypeAliasAfterName( CommentAndMetadata commentAndMetadata, Token abstractKeyword, @@ -6524,10 +6119,8 @@ semicolon); } - /** - * Parse a list of configurations. Return the configurations that were parsed, - * or `null` if there are no configurations. - */ + /// Parse a list of configurations. Return the configurations that were + /// parsed, or `null` if there are no configurations. List<Configuration> _parseConfigurations() { List<Configuration> configurations = null; while (_matchesKeyword(Keyword.IF)) { @@ -6637,20 +6230,18 @@ body); } - /** - * Parse an enum constant declaration. Return the enum constant declaration - * that was parsed. - * - * Specified: - * - * enumConstant ::= - * id - * - * Actual: - * - * enumConstant ::= - * metadata id - */ + /// Parse an enum constant declaration. Return the enum constant declaration + /// that was parsed. + /// + /// Specified: + /// + /// enumConstant ::= + /// id + /// + /// Actual: + /// + /// enumConstant ::= + /// metadata id EnumConstantDeclaration _parseEnumConstantDeclaration() { CommentAndMetadata commentAndMetadata = parseCommentAndMetadata(); SimpleIdentifier name; @@ -6663,10 +6254,8 @@ commentAndMetadata.comment, commentAndMetadata.metadata, name); } - /** - * Parse a list of formal parameters given that the list starts with the given - * [leftParenthesis]. Return the formal parameters that were parsed. - */ + /// Parse a list of formal parameters given that the list starts with the + /// given [leftParenthesis]. Return the formal parameters that were parsed. FormalParameterList _parseFormalParameterListAfterParen(Token leftParenthesis, {bool inFunctionType: false}) { if (_matches(TokenType.CLOSE_PAREN)) { @@ -6837,27 +6426,23 @@ leftSquareBracket, rightSquareBracket, rightParenthesis); } - /** - * Parse a list of formal parameters. Return the formal parameters that were - * parsed. - * - * This method assumes that the current token matches `TokenType.OPEN_PAREN`. - */ + /// Parse a list of formal parameters. Return the formal parameters that were + /// parsed. + /// + /// This method assumes that the current token matches `TokenType.OPEN_PAREN`. FormalParameterList _parseFormalParameterListUnchecked( {bool inFunctionType: false}) { return _parseFormalParameterListAfterParen(getAndAdvance(), inFunctionType: inFunctionType); } - /** - * Parse a function declaration statement. The [commentAndMetadata] is the - * documentation comment and metadata to be associated with the declaration. - * The [returnType] is the return type, or `null` if there is no return type. - * Return the function declaration statement that was parsed. - * - * functionDeclarationStatement ::= - * functionSignature functionBody - */ + /// Parse a function declaration statement. The [commentAndMetadata] is the + /// documentation comment and metadata to be associated with the declaration. + /// The [returnType] is the return type, or `null` if there is no return type. + /// Return the function declaration statement that was parsed. + /// + /// functionDeclarationStatement ::= + /// functionSignature functionBody Statement _parseFunctionDeclarationStatementAfterReturnType( CommentAndMetadata commentAndMetadata, TypeAnnotation returnType) { FunctionDeclaration declaration = @@ -6875,17 +6460,15 @@ return astFactory.functionDeclarationStatement(declaration); } - /** - * Parse a function type alias. The [commentAndMetadata] is the metadata to be - * associated with the member. The [keyword] is the token representing the - * 'typedef' keyword. Return the function type alias that was parsed. - * - * functionTypeAlias ::= - * functionPrefix typeParameterList? formalParameterList ';' - * - * functionPrefix ::= - * returnType? name - */ + /// Parse a function type alias. The [commentAndMetadata] is the metadata to + /// be associated with the member. The [keyword] is the token representing the + /// 'typedef' keyword. Return the function type alias that was parsed. + /// + /// functionTypeAlias ::= + /// functionPrefix typeParameterList? formalParameterList ';' + /// + /// functionPrefix ::= + /// returnType? name FunctionTypeAlias _parseFunctionTypeAlias( CommentAndMetadata commentAndMetadata, Token keyword) { TypeAnnotation returnType = null; @@ -6951,12 +6534,10 @@ } } - /** - * Parse the generic method or function's type parameters. - * - * For backwards compatibility this can optionally use comments. - * See [parseGenericMethodComments]. - */ + /// Parse the generic method or function's type parameters. + /// + /// For backwards compatibility this can optionally use comments. + /// See [parseGenericMethodComments]. TypeParameterList _parseGenericMethodTypeParameters() { if (_matches(TokenType.LT)) { return parseTypeParameterList(); @@ -6964,15 +6545,13 @@ return null; } - /** - * Parse a library name. The [missingNameError] is the error code to be used - * if the library name is missing. The [missingNameToken] is the token - * associated with the error produced if the library name is missing. Return - * the library name that was parsed. - * - * libraryName ::= - * libraryIdentifier - */ + /// Parse a library name. The [missingNameError] is the error code to be used + /// if the library name is missing. The [missingNameToken] is the token + /// associated with the error produced if the library name is missing. Return + /// the library name that was parsed. + /// + /// libraryName ::= + /// libraryIdentifier LibraryIdentifier _parseLibraryName( ParserErrorCode missingNameError, Token missingNameToken) { if (_matchesIdentifier()) { @@ -6989,19 +6568,17 @@ .libraryIdentifier(<SimpleIdentifier>[createSyntheticIdentifier()]); } - /** - * Parse a method declaration. The [commentAndMetadata] is the documentation - * comment and metadata to be associated with the declaration. The - * [externalKeyword] is the 'external' token. The [staticKeyword] is the - * static keyword, or `null` if the getter is not static. The [returnType] is - * the return type of the method. The [name] is the name of the method. The - * [parameters] is the parameters to the method. Return the method declaration - * that was parsed. - * - * functionDeclaration ::= - * ('external' 'static'?)? functionSignature functionBody - * | 'external'? functionSignature ';' - */ + /// Parse a method declaration. The [commentAndMetadata] is the documentation + /// comment and metadata to be associated with the declaration. The + /// [externalKeyword] is the 'external' token. The [staticKeyword] is the + /// static keyword, or `null` if the getter is not static. The [returnType] is + /// the return type of the method. The [name] is the name of the method. The + /// [parameters] is the parameters to the method. Return the method + /// declaration that was parsed. + /// + /// functionDeclaration ::= + /// ('external' 'static'?)? functionSignature functionBody + /// | 'external'? functionSignature ';' MethodDeclaration _parseMethodDeclarationAfterParameters( CommentAndMetadata commentAndMetadata, Token externalKeyword, @@ -7037,18 +6614,16 @@ body); } - /** - * Parse a method declaration. The [commentAndMetadata] is the documentation - * comment and metadata to be associated with the declaration. The - * [externalKeyword] is the 'external' token. The [staticKeyword] is the - * static keyword, or `null` if the getter is not static. The [returnType] is - * the return type of the method. Return the method declaration that was - * parsed. - * - * functionDeclaration ::= - * 'external'? 'static'? functionSignature functionBody - * | 'external'? functionSignature ';' - */ + /// Parse a method declaration. The [commentAndMetadata] is the documentation + /// comment and metadata to be associated with the declaration. The + /// [externalKeyword] is the 'external' token. The [staticKeyword] is the + /// static keyword, or `null` if the getter is not static. The [returnType] is + /// the return type of the method. Return the method declaration that was + /// parsed. + /// + /// functionDeclaration ::= + /// 'external'? 'static'? functionSignature functionBody + /// | 'external'? functionSignature ';' MethodDeclaration _parseMethodDeclarationAfterReturnType( CommentAndMetadata commentAndMetadata, Token externalKeyword, @@ -7084,34 +6659,30 @@ parameters); } - /** - * Parse a class native clause. Return the native clause that was parsed. - * - * This method assumes that the current token matches `_NATIVE`. - * - * classNativeClause ::= - * 'native' name - */ + /// Parse a class native clause. Return the native clause that was parsed. + /// + /// This method assumes that the current token matches `_NATIVE`. + /// + /// classNativeClause ::= + /// 'native' name NativeClause _parseNativeClause() { Token keyword = getAndAdvance(); StringLiteral name = parseStringLiteral(); return astFactory.nativeClause(keyword, name); } - /** - * Parse an operator declaration starting after the 'operator' keyword. The - * [commentAndMetadata] is the documentation comment and metadata to be - * associated with the declaration. The [externalKeyword] is the 'external' - * token. The [returnType] is the return type that has already been parsed, or - * `null` if there was no return type. The [operatorKeyword] is the 'operator' - * keyword. Return the operator declaration that was parsed. - * - * operatorDeclaration ::= - * operatorSignature (';' | functionBody) - * - * operatorSignature ::= - * 'external'? returnType? 'operator' operator formalParameterList - */ + /// Parse an operator declaration starting after the 'operator' keyword. The + /// [commentAndMetadata] is the documentation comment and metadata to be + /// associated with the declaration. The [externalKeyword] is the 'external' + /// token. The [returnType] is the return type that has already been parsed, + /// or `null` if there was no return type. The [operatorKeyword] is the + /// 'operator' keyword. Return the operator declaration that was parsed. + /// + /// operatorDeclaration ::= + /// operatorSignature (';' | functionBody) + /// + /// operatorSignature ::= + /// 'external'? returnType? 'operator' operator formalParameterList MethodDeclaration _parseOperatorAfterKeyword( CommentAndMetadata commentAndMetadata, Token externalKeyword, @@ -7157,10 +6728,8 @@ body); } - /** - * Parse a return type if one is given, otherwise return `null` without - * advancing. Return the return type that was parsed. - */ + /// Parse a return type if one is given, otherwise return `null` without + /// advancing. Return the return type that was parsed. TypeAnnotation _parseOptionalReturnType() { Keyword keyword = _currentToken.keyword; if (keyword == Keyword.VOID) { @@ -7198,10 +6767,8 @@ return null; } - /** - * Parse a [TypeArgumentList] if present, otherwise return null. - * This also supports the comment form, if enabled: `/*<T>*/` - */ + /// Parse a [TypeArgumentList] if present, otherwise return null. + /// This also supports the comment form, if enabled: `/*<T>*/` TypeArgumentList _parseOptionalTypeArguments() { if (_matches(TokenType.LT)) { return parseTypeArgumentList(); @@ -7209,16 +6776,14 @@ return null; } - /** - * Parse a part directive. The [commentAndMetadata] is the metadata to be - * associated with the directive. Return the part or part-of directive that - * was parsed. - * - * This method assumes that the current token matches `Keyword.PART`. - * - * partDirective ::= - * metadata 'part' stringLiteral ';' - */ + /// Parse a part directive. The [commentAndMetadata] is the metadata to be + /// associated with the directive. Return the part or part-of directive that + /// was parsed. + /// + /// This method assumes that the current token matches `Keyword.PART`. + /// + /// partDirective ::= + /// metadata 'part' stringLiteral ';' Directive _parsePartDirective(CommentAndMetadata commentAndMetadata) { Token partKeyword = getAndAdvance(); StringLiteral partUri = _parseUri(); @@ -7227,17 +6792,15 @@ commentAndMetadata.metadata, partKeyword, partUri, semicolon); } - /** - * Parse a part-of directive. The [commentAndMetadata] is the metadata to be - * associated with the directive. Return the part or part-of directive that - * was parsed. - * - * This method assumes that the current token matches [Keyword.PART] and that - * the following token matches the identifier 'of'. - * - * partOfDirective ::= - * metadata 'part' 'of' identifier ';' - */ + /// Parse a part-of directive. The [commentAndMetadata] is the metadata to be + /// associated with the directive. Return the part or part-of directive that + /// was parsed. + /// + /// This method assumes that the current token matches [Keyword.PART] and that + /// the following token matches the identifier 'of'. + /// + /// partOfDirective ::= + /// metadata 'part' 'of' identifier ';' Directive _parsePartOfDirective(CommentAndMetadata commentAndMetadata) { Token partKeyword = getAndAdvance(); Token ofKeyword = getAndAdvance(); @@ -7266,13 +6829,11 @@ semicolon); } - /** - * Parse a prefixed identifier given that the given [qualifier] was already - * parsed. Return the prefixed identifier that was parsed. - * - * prefixedIdentifier ::= - * identifier ('.' identifier)? - */ + /// Parse a prefixed identifier given that the given [qualifier] was already + /// parsed. Return the prefixed identifier that was parsed. + /// + /// prefixedIdentifier ::= + /// identifier ('.' identifier)? Identifier _parsePrefixedIdentifierAfterIdentifier( SimpleIdentifier qualifier) { if (!_matches(TokenType.PERIOD)) { @@ -7283,28 +6844,24 @@ return astFactory.prefixedIdentifier(qualifier, period, qualified); } - /** - * Parse a prefixed identifier. Return the prefixed identifier that was - * parsed. - * - * This method assumes that the current token matches an identifier. - * - * prefixedIdentifier ::= - * identifier ('.' identifier)? - */ + /// Parse a prefixed identifier. Return the prefixed identifier that was + /// parsed. + /// + /// This method assumes that the current token matches an identifier. + /// + /// prefixedIdentifier ::= + /// identifier ('.' identifier)? Identifier _parsePrefixedIdentifierUnchecked() { return _parsePrefixedIdentifierAfterIdentifier( _parseSimpleIdentifierUnchecked()); } - /** - * Parse a simple identifier. Return the simple identifier that was parsed. - * - * This method assumes that the current token matches an identifier. - * - * identifier ::= - * IDENTIFIER - */ + /// Parse a simple identifier. Return the simple identifier that was parsed. + /// + /// This method assumes that the current token matches an identifier. + /// + /// identifier ::= + /// IDENTIFIER SimpleIdentifier _parseSimpleIdentifierUnchecked( {bool isDeclaration: false}) { String lexeme = _currentToken.lexeme; @@ -7317,13 +6874,11 @@ isDeclaration: isDeclaration); } - /** - * Parse a list of statements within a switch statement. Return the statements - * that were parsed. - * - * statements ::= - * statement* - */ + /// Parse a list of statements within a switch statement. Return the + /// statements that were parsed. + /// + /// statements ::= + /// statement* List<Statement> _parseStatementList() { List<Statement> statements = <Statement>[]; Token statementStart = _currentToken; @@ -7343,14 +6898,12 @@ return statements; } - /** - * Parse a string literal that contains interpolations. Return the string - * literal that was parsed. - * - * This method assumes that the current token matches either - * [TokenType.STRING_INTERPOLATION_EXPRESSION] or - * [TokenType.STRING_INTERPOLATION_IDENTIFIER]. - */ + /// Parse a string literal that contains interpolations. Return the string + /// literal that was parsed. + /// + /// This method assumes that the current token matches either + /// [TokenType.STRING_INTERPOLATION_EXPRESSION] or + /// [TokenType.STRING_INTERPOLATION_IDENTIFIER]. StringInterpolation _parseStringInterpolation(Token string) { List<InterpolationElement> elements = <InterpolationElement>[ astFactory.interpolationString( @@ -7396,15 +6949,13 @@ return astFactory.stringInterpolation(elements); } - /** - * Parse a string literal. Return the string literal that was parsed. - * - * This method assumes that the current token matches `TokenType.STRING`. - * - * stringLiteral ::= - * MULTI_LINE_STRING+ - * | SINGLE_LINE_STRING+ - */ + /// Parse a string literal. Return the string literal that was parsed. + /// + /// This method assumes that the current token matches `TokenType.STRING`. + /// + /// stringLiteral ::= + /// MULTI_LINE_STRING+ + /// | SINGLE_LINE_STRING+ StringLiteral _parseStringLiteralUnchecked() { List<StringLiteral> strings = <StringLiteral>[]; do { @@ -7422,15 +6973,13 @@ : astFactory.adjacentStrings(strings); } - /** - * Parse a type annotation, possibly superseded by a type name in a comment. - * Return the type name that was parsed. - * - * This method assumes that the current token is an identifier. - * - * type ::= - * qualified typeArguments? - */ + /// Parse a type annotation, possibly superseded by a type name in a comment. + /// Return the type name that was parsed. + /// + /// This method assumes that the current token is an identifier. + /// + /// type ::= + /// qualified typeArguments? TypeAnnotation _parseTypeAnnotationAfterIdentifier() { return parseTypeAnnotation(false); } @@ -7450,10 +6999,8 @@ return astFactory.typeName(typeName, typeArguments); } - /** - * Parse a string literal representing a URI. Return the string literal that - * was parsed. - */ + /// Parse a string literal representing a URI. Return the string literal that + /// was parsed. StringLiteral _parseUri() { // TODO(brianwilkerson) Should this function also return true for valid // top-level keywords? @@ -7510,17 +7057,15 @@ return parseStringLiteral(); } - /** - * Parse a variable declaration statement. The [commentAndMetadata] is the - * metadata to be associated with the variable declaration statement, or - * `null` if there is no attempt at parsing the comment and metadata. The - * [keyword] is the token representing the 'final', 'const' or 'var' keyword, - * or `null` if there is no keyword. The [type] is the type of the variables - * in the list. Return the variable declaration statement that was parsed. - * - * variableDeclarationStatement ::= - * variableDeclarationList ';' - */ + /// Parse a variable declaration statement. The [commentAndMetadata] is the + /// metadata to be associated with the variable declaration statement, or + /// `null` if there is no attempt at parsing the comment and metadata. The + /// [keyword] is the token representing the 'final', 'const' or 'var' keyword, + /// or `null` if there is no keyword. The [type] is the type of the variables + /// in the list. Return the variable declaration statement that was parsed. + /// + /// variableDeclarationStatement ::= + /// variableDeclarationList ';' VariableDeclarationStatement _parseVariableDeclarationStatementAfterType( CommentAndMetadata commentAndMetadata, Token keyword, @@ -7532,17 +7077,13 @@ return astFactory.variableDeclarationStatement(variableList, semicolon); } - /** - * Return the token that is immediately after the current token. This is - * equivalent to [_peekAt](1). - */ + /// Return the token that is immediately after the current token. This is + /// equivalent to [_peekAt](1). Token _peek() => _currentToken.next; - /** - * Return the token that is the given [distance] after the current token, - * where the distance is the number of tokens to look ahead. A distance of `0` - * is the current token, `1` is the next token, etc. - */ + /// Return the token that is the given [distance] after the current token, + /// where the distance is the number of tokens to look ahead. A distance of + /// `0` is the current token, `1` is the next token, etc. Token _peekAt(int distance) { Token token = _currentToken; for (int i = 0; i < distance; i++) { @@ -7570,9 +7111,7 @@ return comment; } - /** - * Report the given [error]. - */ + /// Report the given [error]. void _reportError(AnalysisError error) { if (_errorListenerLock != 0) { return; @@ -7580,29 +7119,23 @@ _errorListener.onError(error); } - /** - * Report an error with the given [errorCode] and [arguments] associated with - * the current token. - */ + /// Report an error with the given [errorCode] and [arguments] associated with + /// the current token. void _reportErrorForCurrentToken(ParserErrorCode errorCode, [List<Object> arguments]) { _reportErrorForToken(errorCode, _currentToken, arguments); } - /** - * Report an error with the given [errorCode] and [arguments] associated with - * the given [node]. - */ + /// Report an error with the given [errorCode] and [arguments] associated with + /// the given [node]. void _reportErrorForNode(ParserErrorCode errorCode, AstNode node, [List<Object> arguments]) { _reportError(new AnalysisError( _source, node.offset, node.length, errorCode, arguments)); } - /** - * Report an error with the given [errorCode] and [arguments] associated with - * the given [token]. - */ + /// Report an error with the given [errorCode] and [arguments] associated with + /// the given [token]. void _reportErrorForToken(ErrorCode errorCode, Token token, [List<Object> arguments]) { if (token.type == TokenType.EOF) { @@ -7612,9 +7145,7 @@ math.max(token.length, 1), errorCode, arguments)); } - /** - * Skips a block with all containing blocks. - */ + /// Skips a block with all containing blocks. void _skipBlock() { Token endToken = (_currentToken as BeginToken).endToken; if (endToken == null) { @@ -7630,20 +7161,18 @@ } } - /** - * Parse the 'final', 'const', 'var' or type preceding a variable declaration, - * starting at the given token, without actually creating a type or changing - * the current token. Return the token following the type that was parsed, or - * `null` if the given token is not the first token in a valid type. The - * [startToken] is the token at which parsing is to begin. Return the token - * following the type that was parsed. - * - * finalConstVarOrType ::= - * | 'final' type? - * | 'const' type? - * | 'var' - * | type - */ + /// Parse the 'final', 'const', 'var' or type preceding a variable + /// declaration, starting at the given token, without actually creating a + /// type or changing the current token. Return the token following the type + /// that was parsed, or `null` if the given token is not the first token in a + /// valid type. The [startToken] is the token at which parsing is to begin. + /// Return the token following the type that was parsed. + /// + /// finalConstVarOrType ::= + /// | 'final' type? + /// | 'const' type? + /// | 'var' + /// | type Token _skipFinalConstVarOrType(Token startToken) { Keyword keyword = startToken.keyword; if (keyword == Keyword.FINAL || keyword == Keyword.CONST) { @@ -7677,40 +7206,38 @@ return null; } - /** - * Parse a list of formal parameters, starting at the [startToken], without - * actually creating a formal parameter list or changing the current token. - * Return the token following the formal parameter list that was parsed, or - * `null` if the given token is not the first token in a valid list of formal - * parameter. - * - * Note that unlike other skip methods, this method uses a heuristic. In the - * worst case, the parameters could be prefixed by metadata, which would - * require us to be able to skip arbitrary expressions. Rather than duplicate - * the logic of most of the parse methods we simply look for something that is - * likely to be a list of parameters and then skip to returning the token - * after the closing parenthesis. - * - * This method must be kept in sync with [parseFormalParameterList]. - * - * formalParameterList ::= - * '(' ')' - * | '(' normalFormalParameters (',' optionalFormalParameters)? ')' - * | '(' optionalFormalParameters ')' - * - * normalFormalParameters ::= - * normalFormalParameter (',' normalFormalParameter)* - * - * optionalFormalParameters ::= - * optionalPositionalFormalParameters - * | namedFormalParameters - * - * optionalPositionalFormalParameters ::= - * '[' defaultFormalParameter (',' defaultFormalParameter)* ']' - * - * namedFormalParameters ::= - * '{' defaultNamedParameter (',' defaultNamedParameter)* '}' - */ + /// Parse a list of formal parameters, starting at the [startToken], without + /// actually creating a formal parameter list or changing the current token. + /// Return the token following the formal parameter list that was parsed, or + /// `null` if the given token is not the first token in a valid list of formal + /// parameter. + /// + /// Note that unlike other skip methods, this method uses a heuristic. In the + /// worst case, the parameters could be prefixed by metadata, which would + /// require us to be able to skip arbitrary expressions. Rather than duplicate + /// the logic of most of the parse methods we simply look for something that + /// is likely to be a list of parameters and then skip to returning the token + /// after the closing parenthesis. + /// + /// This method must be kept in sync with [parseFormalParameterList]. + /// + /// formalParameterList ::= + /// '(' ')' + /// | '(' normalFormalParameters (',' optionalFormalParameters)? ')' + /// | '(' optionalFormalParameters ')' + /// + /// normalFormalParameters ::= + /// normalFormalParameter (',' normalFormalParameter)* + /// + /// optionalFormalParameters ::= + /// optionalPositionalFormalParameters + /// | namedFormalParameters + /// + /// optionalPositionalFormalParameters ::= + /// '[' defaultFormalParameter (',' defaultFormalParameter)* ']' + /// + /// namedFormalParameters ::= + /// '{' defaultNamedParameter (',' defaultNamedParameter)* '}' Token _skipFormalParameterList(Token startToken) { if (!_tokenMatches(startToken, TokenType.OPEN_PAREN)) { return null; @@ -7761,10 +7288,8 @@ return _skipPastMatchingToken(startToken); } - /** - * If the [startToken] is a begin token with an associated end token, then - * return the token following the end token. Otherwise, return `null`. - */ + /// If the [startToken] is a begin token with an associated end token, then + /// return the token following the end token. Otherwise, return `null`. Token _skipPastMatchingToken(Token startToken) { if (startToken is! BeginToken) { return null; @@ -7776,15 +7301,13 @@ return closeParen.next; } - /** - * Parse a string literal that contains interpolations, starting at the - * [startToken], without actually creating a string literal or changing the - * current token. Return the token following the string literal that was - * parsed, or `null` if the given token is not the first token in a valid - * string literal. - * - * This method must be kept in sync with [parseStringInterpolation]. - */ + /// Parse a string literal that contains interpolations, starting at the + /// [startToken], without actually creating a string literal or changing the + /// current token. Return the token following the string literal that was + /// parsed, or `null` if the given token is not the first token in a valid + /// string literal. + /// + /// This method must be kept in sync with [parseStringInterpolation]. Token _skipStringInterpolation(Token startToken) { Token token = startToken; TokenType type = token.type; @@ -7836,18 +7359,16 @@ return token; } - /** - * Parse a list of type parameters, starting at the [startToken], without - * actually creating a type parameter list or changing the current token. - * Return the token following the type parameter list that was parsed, or - * `null` if the given token is not the first token in a valid type parameter - * list. - * - * This method must be kept in sync with [parseTypeParameterList]. - * - * typeParameterList ::= - * '<' typeParameter (',' typeParameter)* '>' - */ + /// Parse a list of type parameters, starting at the [startToken], without + /// actually creating a type parameter list or changing the current token. + /// Return the token following the type parameter list that was parsed, or + /// `null` if the given token is not the first token in a valid type parameter + /// list. + /// + /// This method must be kept in sync with [parseTypeParameterList]. + /// + /// typeParameterList ::= + /// '<' typeParameter (',' typeParameter)* '>' Token _skipTypeParameterList(Token startToken) { if (!_tokenMatches(startToken, TokenType.LT)) { return null; @@ -7889,10 +7410,8 @@ return next; } - /** - * Assuming that the current token is an index token ('[]'), split it into two - * tokens ('[' and ']'), leaving the left bracket as the current token. - */ + /// Assuming that the current token is an index token ('[]'), split it into + /// two tokens ('[' and ']'), leaving the left bracket as the current token. void _splitIndex() { // Split the token into two separate tokens. BeginToken leftBracket = _createToken( @@ -7907,42 +7426,30 @@ _currentToken = leftBracket; } - /** - * Return `true` if the given [token] has the given [type]. - */ + /// Return `true` if the given [token] has the given [type]. bool _tokenMatches(Token token, TokenType type) => token.type == type; - /** - * Return `true` if the given [token] is a valid identifier. Valid identifiers - * include built-in identifiers (pseudo-keywords). - */ + /// Return `true` if the given [token] is a valid identifier. Valid + /// identifiers include built-in identifiers (pseudo-keywords). bool _tokenMatchesIdentifier(Token token) => _tokenMatches(token, TokenType.IDENTIFIER) || _tokenMatchesPseudoKeyword(token); - /** - * Return `true` if the given [token] is either an identifier or a keyword. - */ + /// Return `true` if the given [token] is either an identifier or a keyword. bool _tokenMatchesIdentifierOrKeyword(Token token) => _tokenMatches(token, TokenType.IDENTIFIER) || token.type.isKeyword; - /** - * Return `true` if the given [token] matches the given [keyword]. - */ + /// Return `true` if the given [token] matches the given [keyword]. bool _tokenMatchesKeyword(Token token, Keyword keyword) => token.keyword == keyword; - /** - * Return `true` if the given [token] matches a pseudo keyword. - */ + /// Return `true` if the given [token] matches a pseudo keyword. bool _tokenMatchesPseudoKeyword(Token token) => token.keyword?.isBuiltInOrPseudo ?? false; - /** - * Translate the characters at the given [index] in the given [lexeme], - * appending the translated character to the given [buffer]. The index is - * assumed to be valid. - */ + /// Translate the characters at the given [index] in the given [lexeme], + /// appending the translated character to the given [buffer]. The index is + /// assumed to be valid. int _translateCharacter(StringBuffer buffer, String lexeme, int index) { int currentChar = lexeme.codeUnitAt(index); if (currentChar != 0x5C) { @@ -8081,10 +7588,8 @@ return currentIndex + 1; } - /** - * Decrements the error reporting lock level. If level is more than `0`, then - * [reportError] wont report any error. - */ + /// Decrements the error reporting lock level. If level is more than `0`, then + /// [reportError] wont report any error. void _unlockErrorListener() { if (_errorListenerLock == 0) { throw new StateError("Attempt to unlock not locked error listener."); @@ -8092,10 +7597,8 @@ _errorListenerLock--; } - /** - * Validate that the given [parameterList] does not contain any field - * initializers. - */ + /// Validate that the given [parameterList] does not contain any field + /// initializers. void _validateFormalParameterList(FormalParameterList parameterList) { for (FormalParameter parameter in parameterList.parameters) { if (parameter is FieldFormalParameter) { @@ -8106,10 +7609,8 @@ } } - /** - * Validate that the given set of [modifiers] is appropriate for a class and - * return the 'abstract' keyword if there is one. - */ + /// Validate that the given set of [modifiers] is appropriate for a class and + /// return the 'abstract' keyword if there is one. Token _validateModifiersForClass(Modifiers modifiers) { _validateModifiersForTopLevelDeclaration(modifiers); if (modifiers.constKeyword != null) { @@ -8128,10 +7629,8 @@ return modifiers.abstractKeyword; } - /** - * Validate that the given set of [modifiers] is appropriate for a constructor - * and return the 'const' keyword if there is one. - */ + /// Validate that the given set of [modifiers] is appropriate for a + /// constructor and return the 'const' keyword if there is one. Token _validateModifiersForConstructor(Modifiers modifiers) { if (modifiers.abstractKeyword != null) { _reportErrorForToken( @@ -8171,10 +7670,8 @@ return constKeyword; } - /** - * Validate that the given set of [modifiers] is appropriate for an enum and - * return the 'abstract' keyword if there is one. - */ + /// Validate that the given set of [modifiers] is appropriate for an enum and + /// return the 'abstract' keyword if there is one. void _validateModifiersForEnum(Modifiers modifiers) { _validateModifiersForTopLevelDeclaration(modifiers); if (modifiers.abstractKeyword != null) { @@ -8196,10 +7693,8 @@ } } - /** - * Validate that the given set of [modifiers] is appropriate for a field and - * return the 'final', 'const' or 'var' keyword if there is one. - */ + /// Validate that the given set of [modifiers] is appropriate for a field and + /// return the 'final', 'const' or 'var' keyword if there is one. Token _validateModifiersForField(Modifiers modifiers) { if (modifiers.abstractKeyword != null) { _reportErrorForCurrentToken(ParserErrorCode.ABSTRACT_CLASS_MEMBER); @@ -8258,10 +7753,8 @@ return Token.lexicallyFirst([constKeyword, finalKeyword, varKeyword]); } - /** - * Validate that the given set of [modifiers] is appropriate for a local - * function. - */ + /// Validate that the given set of [modifiers] is appropriate for a local + /// function. void _validateModifiersForFunctionDeclarationStatement(Modifiers modifiers) { if (modifiers.abstractKeyword != null || modifiers.constKeyword != null || @@ -8275,10 +7768,8 @@ } } - /** - * Validate that the given set of [modifiers] is appropriate for a getter, - * setter, or method. - */ + /// Validate that the given set of [modifiers] is appropriate for a getter, + /// setter, or method. void _validateModifiersForGetterOrSetterOrMethod(Modifiers modifiers) { if (modifiers.abstractKeyword != null) { _reportErrorForCurrentToken(ParserErrorCode.ABSTRACT_CLASS_MEMBER); @@ -8313,10 +7804,8 @@ } } - /** - * Validate that the given set of [modifiers] is appropriate for a getter, - * setter, or method. - */ + /// Validate that the given set of [modifiers] is appropriate for a getter, + /// setter, or method. void _validateModifiersForOperator(Modifiers modifiers) { if (modifiers.abstractKeyword != null) { _reportErrorForCurrentToken(ParserErrorCode.ABSTRACT_CLASS_MEMBER); @@ -8343,10 +7832,8 @@ } } - /** - * Validate that the given set of [modifiers] is appropriate for a top-level - * declaration. - */ + /// Validate that the given set of [modifiers] is appropriate for a top-level + /// declaration. void _validateModifiersForTopLevelDeclaration(Modifiers modifiers) { if (modifiers.covariantKeyword != null) { _reportErrorForToken(ParserErrorCode.COVARIANT_TOP_LEVEL_DECLARATION, @@ -8362,10 +7849,8 @@ } } - /** - * Validate that the given set of [modifiers] is appropriate for a top-level - * function. - */ + /// Validate that the given set of [modifiers] is appropriate for a top-level + /// function. void _validateModifiersForTopLevelFunction(Modifiers modifiers) { _validateModifiersForTopLevelDeclaration(modifiers); if (modifiers.abstractKeyword != null) { @@ -8383,10 +7868,8 @@ } } - /** - * Validate that the given set of [modifiers] is appropriate for a field and - * return the 'final', 'const' or 'var' keyword if there is one. - */ + /// Validate that the given set of [modifiers] is appropriate for a field and + /// return the 'final', 'const' or 'var' keyword if there is one. Token _validateModifiersForTopLevelVariable(Modifiers modifiers) { _validateModifiersForTopLevelDeclaration(modifiers); if (modifiers.abstractKeyword != null) { @@ -8414,10 +7897,8 @@ return Token.lexicallyFirst([constKeyword, finalKeyword, varKeyword]); } - /** - * Validate that the given set of [modifiers] is appropriate for a class and - * return the 'abstract' keyword if there is one. - */ + /// Validate that the given set of [modifiers] is appropriate for a class and + /// return the 'abstract' keyword if there is one. void _validateModifiersForTypedef(Modifiers modifiers) { _validateModifiersForTopLevelDeclaration(modifiers); if (modifiers.abstractKeyword != null) { @@ -8442,9 +7923,7 @@ } } -/** - * Instances of this class are thrown when the parser detects that AST has - * too many nested expressions to be parsed safely and avoid possibility of - * [StackOverflowError] in the parser or during later analysis. - */ +/// Instances of this class are thrown when the parser detects that AST has +/// too many nested expressions to be parsed safely and avoid possibility of +/// [StackOverflowError] in the parser or during later analysis. class _TooDeepTreeError {}
diff --git a/pkg/analyzer/lib/src/generated/parser_fasta.dart b/pkg/analyzer/lib/src/generated/parser_fasta.dart index 946f327..dfb3261 100644 --- a/pkg/analyzer/lib/src/generated/parser_fasta.dart +++ b/pkg/analyzer/lib/src/generated/parser_fasta.dart
@@ -44,6 +44,11 @@ void set enableOptionalNewAndConst(bool enable) {} @override + void set enableSetLiterals(bool value) { + fastaParser.parseSetLiterals = value; + } + + @override void set parseFunctionBodies(bool parseFunctionBodies) { astBuilder.parseFunctionBodies = parseFunctionBodies; }
diff --git a/pkg/analyzer/lib/src/generated/resolver.dart b/pkg/analyzer/lib/src/generated/resolver.dart index 7fd6ce9..70d2b41 100644 --- a/pkg/analyzer/lib/src/generated/resolver.dart +++ b/pkg/analyzer/lib/src/generated/resolver.dart
@@ -1,4 +1,4 @@ -// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file +// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. @@ -58,14 +58,14 @@ nameScope: nameScope); @override - Object visitMethodInvocation(MethodInvocation node) { + void visitMethodInvocation(MethodInvocation node) { super.visitMethodInvocation(node); SimpleIdentifier methodName = node.methodName; if (methodName.isSynthetic) { // This isn't a constructor invocation because the method name is // synthetic. - return null; + return; } Expression target = node.target; @@ -73,7 +73,7 @@ // Possible cases: C() or C<>() if (node.realTarget != null) { // This isn't a constructor invocation because it's in a cascade. - return null; + return; } Element element = nameScope.lookup(methodName, definingLibrary); if (element is ClassElement) { @@ -204,7 +204,6 @@ } } } - return null; } /// Return the token that should be used in the [InstanceCreationExpression] @@ -220,27 +219,35 @@ static InterfaceType getType(TypeSystem typeSystem, ClassElement element, TypeArgumentList typeArguments) { DartType type = element.type; + List<TypeParameterElement> typeParameters = element.typeParameters; - if (typeArguments != null && - typeParameters != null && - typeArguments.arguments.length == typeParameters.length) { - List<DartType> argumentTypes = typeArguments.arguments + if (typeParameters.isEmpty) { + return type; + } + + if (typeArguments == null) { + return typeSystem.instantiateToBounds(type); + } + + List<DartType> argumentTypes; + if (typeArguments.arguments.length == typeParameters.length) { + argumentTypes = typeArguments.arguments .map((TypeAnnotation argument) => argument.type) .toList(); - List<DartType> parameterTypes = typeParameters - .map((TypeParameterElement parameter) => parameter.type) - .toList(); - type = type.substitute2(argumentTypes, parameterTypes); - } else if (typeArguments == null && typeParameters != null) { - type = typeSystem.instantiateToBounds(type); + } else { + argumentTypes = List<DartType>.filled( + typeParameters.length, DynamicTypeImpl.instance); } - return type; + List<DartType> parameterTypes = typeParameters + .map((TypeParameterElement parameter) => parameter.type) + .toList(); + return type.substitute2(argumentTypes, parameterTypes); } } /// Instances of the class `BestPracticesVerifier` traverse an AST structure /// looking for violations of Dart best practices. -class BestPracticesVerifier extends RecursiveAstVisitor<Object> { +class BestPracticesVerifier extends RecursiveAstVisitor<void> { // static String _HASHCODE_GETTER_NAME = "hashCode"; static String _NULL_TYPE_NAME = "Null"; @@ -288,7 +295,7 @@ } @override - Object visitAnnotation(Annotation node) { + void visitAnnotation(Annotation node) { ElementAnnotation element = resolutionMap.elementAnnotationForAnnotation(node); if (element?.isFactory == true) { @@ -306,46 +313,46 @@ HintCode.INVALID_IMMUTABLE_ANNOTATION, node, []); } } - return super.visitAnnotation(node); + super.visitAnnotation(node); } @override - Object visitArgumentList(ArgumentList node) { + void visitArgumentList(ArgumentList node) { for (Expression argument in node.arguments) { ParameterElement parameter = argument.staticParameterElement; if (parameter?.isOptionalPositional == true) { _checkForDeprecatedMemberUse(parameter, argument); } } - return super.visitArgumentList(node); + super.visitArgumentList(node); } @override - Object visitAsExpression(AsExpression node) { + void visitAsExpression(AsExpression node) { _checkForUnnecessaryCast(node); - return super.visitAsExpression(node); + super.visitAsExpression(node); } @override - Object visitAssignmentExpression(AssignmentExpression node) { + void visitAssignmentExpression(AssignmentExpression node) { TokenType operatorType = node.operator.type; if (operatorType == TokenType.EQ) { _checkForInvalidAssignment(node.leftHandSide, node.rightHandSide); } else { _checkForDeprecatedMemberUse(node.staticElement, node); } - return super.visitAssignmentExpression(node); + super.visitAssignmentExpression(node); } @override - Object visitBinaryExpression(BinaryExpression node) { + void visitBinaryExpression(BinaryExpression node) { _checkForDivisionOptimizationHint(node); _checkForDeprecatedMemberUse(node.staticElement, node); - return super.visitBinaryExpression(node); + super.visitBinaryExpression(node); } @override - Object visitClassDeclaration(ClassDeclaration node) { + void visitClassDeclaration(ClassDeclaration node) { var element = AbstractClassElementImpl.getImpl(node.declaredElement); _enclosingClass = element; _invalidAccessVerifier._enclosingClass = element; @@ -359,7 +366,7 @@ // Commented out until we decide that we want this hint in the analyzer // checkForOverrideEqualsButNotHashCode(node); _checkForImmutable(node); - return super.visitClassDeclaration(node); + super.visitClassDeclaration(node); } finally { _enclosingClass = null; _invalidAccessVerifier._enclosingClass = null; @@ -368,7 +375,7 @@ } @override - Object visitConstructorDeclaration(ConstructorDeclaration node) { + void visitConstructorDeclaration(ConstructorDeclaration node) { if (resolutionMap.elementDeclaredByConstructorDeclaration(node).isFactory) { if (node.body is BlockFunctionBody) { // Check the block for a return statement, if not, create the hint. @@ -378,37 +385,37 @@ } } } - return super.visitConstructorDeclaration(node); + super.visitConstructorDeclaration(node); } @override - Object visitExportDirective(ExportDirective node) { + void visitExportDirective(ExportDirective node) { _checkForDeprecatedMemberUse(node.uriElement, node); - return super.visitExportDirective(node); + super.visitExportDirective(node); } @override - Object visitFieldDeclaration(FieldDeclaration node) { + void visitFieldDeclaration(FieldDeclaration node) { bool wasInDeprecatedMember = _inDeprecatedMember; if (_hasDeprecatedAnnotation(node.metadata)) { _inDeprecatedMember = true; } try { - return super.visitFieldDeclaration(node); + super.visitFieldDeclaration(node); } finally { _inDeprecatedMember = wasInDeprecatedMember; } } @override - Object visitFormalParameterList(FormalParameterList node) { + void visitFormalParameterList(FormalParameterList node) { _checkRequiredParameter(node); - return super.visitFormalParameterList(node); + super.visitFormalParameterList(node); } @override - Object visitFunctionDeclaration(FunctionDeclaration node) { + void visitFunctionDeclaration(FunctionDeclaration node) { bool wasInDeprecatedMember = _inDeprecatedMember; ExecutableElement element = node.declaredElement; if (element != null && element.hasDeprecated) { @@ -417,42 +424,42 @@ try { _checkForMissingReturn( node.returnType, node.functionExpression.body, element, node); - return super.visitFunctionDeclaration(node); + super.visitFunctionDeclaration(node); } finally { _inDeprecatedMember = wasInDeprecatedMember; } } @override - Object visitImportDirective(ImportDirective node) { + void visitImportDirective(ImportDirective node) { _checkForDeprecatedMemberUse(node.uriElement, node); ImportElement importElement = node.element; if (importElement != null && importElement.isDeferred) { _checkForLoadLibraryFunction(node, importElement); } - return super.visitImportDirective(node); + super.visitImportDirective(node); } @override - Object visitIndexExpression(IndexExpression node) { + void visitIndexExpression(IndexExpression node) { _checkForDeprecatedMemberUse(node.staticElement, node); - return super.visitIndexExpression(node); + super.visitIndexExpression(node); } @override - Object visitInstanceCreationExpression(InstanceCreationExpression node) { + void visitInstanceCreationExpression(InstanceCreationExpression node) { _checkForDeprecatedMemberUse(node.staticElement, node); - return super.visitInstanceCreationExpression(node); + super.visitInstanceCreationExpression(node); } @override - Object visitIsExpression(IsExpression node) { + void visitIsExpression(IsExpression node) { _checkAllTypeChecks(node); - return super.visitIsExpression(node); + super.visitIsExpression(node); } @override - Object visitMethodDeclaration(MethodDeclaration node) { + void visitMethodDeclaration(MethodDeclaration node) { bool wasInDeprecatedMember = _inDeprecatedMember; ExecutableElement element = node.declaredElement; if (element != null && element.hasDeprecated) { @@ -463,14 +470,14 @@ //checkForOverridingPrivateMember(node); _checkForMissingReturn(node.returnType, node.body, element, node); _checkForUnnecessaryNoSuchMethod(node); - return super.visitMethodDeclaration(node); + super.visitMethodDeclaration(node); } finally { _inDeprecatedMember = wasInDeprecatedMember; } } @override - Object visitMethodInvocation(MethodInvocation node) { + void visitMethodInvocation(MethodInvocation node) { _checkForNullAwareHints(node, node.operator); DartType staticInvokeType = node.staticInvokeType; Element callElement = staticInvokeType?.element; @@ -478,11 +485,11 @@ callElement.name == FunctionElement.CALL_METHOD_NAME) { _checkForDeprecatedMemberUse(callElement, node); } - return super.visitMethodInvocation(node); + super.visitMethodInvocation(node); } @override - Object visitMixinDeclaration(MixinDeclaration node) { + void visitMixinDeclaration(MixinDeclaration node) { _enclosingClass = node.declaredElement; _invalidAccessVerifier._enclosingClass = _enclosingClass; @@ -492,7 +499,7 @@ } try { - return super.visitMixinDeclaration(node); + super.visitMixinDeclaration(node); } finally { _enclosingClass = null; _invalidAccessVerifier._enclosingClass = null; @@ -501,61 +508,61 @@ } @override - Object visitPostfixExpression(PostfixExpression node) { + void visitPostfixExpression(PostfixExpression node) { _checkForDeprecatedMemberUse(node.staticElement, node); - return super.visitPostfixExpression(node); + super.visitPostfixExpression(node); } @override - Object visitPrefixExpression(PrefixExpression node) { + void visitPrefixExpression(PrefixExpression node) { _checkForDeprecatedMemberUse(node.staticElement, node); - return super.visitPrefixExpression(node); + super.visitPrefixExpression(node); } @override - Object visitPropertyAccess(PropertyAccess node) { + void visitPropertyAccess(PropertyAccess node) { _checkForNullAwareHints(node, node.operator); - return super.visitPropertyAccess(node); + super.visitPropertyAccess(node); } @override - Object visitRedirectingConstructorInvocation( + void visitRedirectingConstructorInvocation( RedirectingConstructorInvocation node) { _checkForDeprecatedMemberUse(node.staticElement, node); - return super.visitRedirectingConstructorInvocation(node); + super.visitRedirectingConstructorInvocation(node); } @override - Object visitSimpleIdentifier(SimpleIdentifier node) { + void visitSimpleIdentifier(SimpleIdentifier node) { _checkForDeprecatedMemberUseAtIdentifier(node); _invalidAccessVerifier.verify(node); - return super.visitSimpleIdentifier(node); + super.visitSimpleIdentifier(node); } @override - Object visitSuperConstructorInvocation(SuperConstructorInvocation node) { + void visitSuperConstructorInvocation(SuperConstructorInvocation node) { _checkForDeprecatedMemberUse(node.staticElement, node); - return super.visitSuperConstructorInvocation(node); + super.visitSuperConstructorInvocation(node); } @override - Object visitTopLevelVariableDeclaration(TopLevelVariableDeclaration node) { + void visitTopLevelVariableDeclaration(TopLevelVariableDeclaration node) { bool wasInDeprecatedMember = _inDeprecatedMember; if (_hasDeprecatedAnnotation(node.metadata)) { _inDeprecatedMember = true; } try { - return super.visitTopLevelVariableDeclaration(node); + super.visitTopLevelVariableDeclaration(node); } finally { _inDeprecatedMember = wasInDeprecatedMember; } } @override - Object visitVariableDeclaration(VariableDeclaration node) { + void visitVariableDeclaration(VariableDeclaration node) { _checkForInvalidAssignment(node.name, node.initializer); - return super.visitVariableDeclaration(node); + super.visitVariableDeclaration(node); } /// Check for the passed is expression for the unnecessary type check hint @@ -641,8 +648,7 @@ bool isLocalParameter(Element element, AstNode node) { if (element is ParameterElement) { ExecutableElement definingFunction = element.enclosingElement; - FunctionBody body = - node.getAncestor((ancestor) => ancestor is FunctionBody); + FunctionBody body = node.thisOrAncestorOfType<FunctionBody>(); while (body != null) { ExecutableElement enclosingFunction; AstNode parent = body.parent; @@ -656,7 +662,7 @@ if (enclosingFunction == definingFunction) { return true; } - body = parent?.getAncestor((ancestor) => ancestor is FunctionBody); + body = parent?.thisOrAncestorOfType<FunctionBody>(); } } return false; @@ -849,16 +855,14 @@ ? ErrorVerifier.getStaticType(lhs) : leftVariableElement.type; DartType staticRightType = ErrorVerifier.getStaticType(rhs); - if (!_typeSystem.isAssignableTo(staticRightType, leftType, - isDeclarationCast: true)) { + if (!_typeSystem.isAssignableTo(staticRightType, leftType)) { // The warning was generated on this rhs return false; } // Test for, and then generate the hint DartType bestRightType = rhs.staticType; if (leftType != null && bestRightType != null) { - if (!_typeSystem.isAssignableTo(bestRightType, leftType, - isDeclarationCast: true)) { + if (!_typeSystem.isAssignableTo(bestRightType, leftType)) { _errorReporter.reportTypeErrorForNode( HintCode.INVALID_ASSIGNMENT, rhs, [bestRightType, leftType]); return true; @@ -1316,7 +1320,7 @@ /// Instances of the class `Dart2JSVerifier` traverse an AST structure looking /// for hints for code that will be compiled to JS, such as /// [HintCode.IS_DOUBLE]. -class Dart2JSVerifier extends RecursiveAstVisitor<Object> { +class Dart2JSVerifier extends RecursiveAstVisitor<void> { /// The name of the `double` type. static String _DOUBLE_TYPE_NAME = "double"; @@ -1329,9 +1333,9 @@ Dart2JSVerifier(this._errorReporter); @override - Object visitIsExpression(IsExpression node) { + void visitIsExpression(IsExpression node) { _checkForIsDoubleHints(node); - return super.visitIsExpression(node); + super.visitIsExpression(node); } /// Check for instances of `x is double`, `x is int`, `x is! double` and @@ -1374,7 +1378,7 @@ } /// A visitor that finds dead code and unused labels. -class DeadCodeVerifier extends RecursiveAstVisitor<Object> { +class DeadCodeVerifier extends RecursiveAstVisitor<void> { /// The error reporter by which errors will be reported. final ErrorReporter _errorReporter; @@ -1391,7 +1395,7 @@ : this._typeSystem = typeSystem ?? new StrongTypeSystemImpl(null); @override - Object visitBinaryExpression(BinaryExpression node) { + void visitBinaryExpression(BinaryExpression node) { Token operator = node.operator; bool isAmpAmp = operator.type == TokenType.AMPERSAND_AMPERSAND; bool isBarBar = operator.type == TokenType.BAR_BAR; @@ -1407,14 +1411,14 @@ HintCode.DEAD_CODE, node.rightOperand); // Only visit the LHS: lhsCondition?.accept(this); - return null; + return; } else if (value == false && isAmpAmp) { // Report error on "if" block: false && !e! _errorReporter.reportErrorForNode( HintCode.DEAD_CODE, node.rightOperand); // Only visit the LHS: lhsCondition?.accept(this); - return null; + return; } } } @@ -1438,27 +1442,25 @@ // } // } } - return super.visitBinaryExpression(node); + super.visitBinaryExpression(node); } /// For each block, this method reports and error on all statements between /// the end of the block and the first return statement (assuming there it is /// not at the end of the block.) @override - Object visitBlock(Block node) { + void visitBlock(Block node) { NodeList<Statement> statements = node.statements; _checkForDeadStatementsInNodeList(statements); - return null; } @override - Object visitBreakStatement(BreakStatement node) { + void visitBreakStatement(BreakStatement node) { labelTracker?.recordUsage(node.label?.name); - return null; } @override - Object visitConditionalExpression(ConditionalExpression node) { + void visitConditionalExpression(ConditionalExpression node) { Expression conditionExpression = node.condition; conditionExpression?.accept(this); if (!_isDebugConstant(conditionExpression)) { @@ -1470,27 +1472,26 @@ _errorReporter.reportErrorForNode( HintCode.DEAD_CODE, node.elseExpression); node.thenExpression?.accept(this); - return null; + return; } else { // Report error on "if" block: false ? !1! : 2 _errorReporter.reportErrorForNode( HintCode.DEAD_CODE, node.thenExpression); node.elseExpression?.accept(this); - return null; + return; } } } - return super.visitConditionalExpression(node); + super.visitConditionalExpression(node); } @override - Object visitContinueStatement(ContinueStatement node) { + void visitContinueStatement(ContinueStatement node) { labelTracker?.recordUsage(node.label?.name); - return null; } @override - Object visitExportDirective(ExportDirective node) { + void visitExportDirective(ExportDirective node) { ExportElement exportElement = node.element; if (exportElement != null) { // The element is null when the URI is invalid. @@ -1501,11 +1502,11 @@ } } } - return super.visitExportDirective(node); + super.visitExportDirective(node); } @override - Object visitIfStatement(IfStatement node) { + void visitIfStatement(IfStatement node) { Expression conditionExpression = node.condition; conditionExpression?.accept(this); if (!_isDebugConstant(conditionExpression)) { @@ -1519,22 +1520,22 @@ _errorReporter.reportErrorForNode( HintCode.DEAD_CODE, elseStatement); node.thenStatement?.accept(this); - return null; + return; } } else { // Report error on if block: if (false) {!} else {} _errorReporter.reportErrorForNode( HintCode.DEAD_CODE, node.thenStatement); node.elseStatement?.accept(this); - return null; + return; } } } - return super.visitIfStatement(node); + super.visitIfStatement(node); } @override - Object visitImportDirective(ImportDirective node) { + void visitImportDirective(ImportDirective node) { ImportElement importElement = node.element; if (importElement != null) { // The element is null when the URI is invalid, but not when the URI is @@ -1546,34 +1547,33 @@ } } } - return super.visitImportDirective(node); + super.visitImportDirective(node); } @override - Object visitLabeledStatement(LabeledStatement node) { + void visitLabeledStatement(LabeledStatement node) { _pushLabels(node.labels); try { super.visitLabeledStatement(node); } finally { _popLabels(); } - return null; } @override - Object visitSwitchCase(SwitchCase node) { + void visitSwitchCase(SwitchCase node) { _checkForDeadStatementsInNodeList(node.statements, allowMandated: true); - return super.visitSwitchCase(node); + super.visitSwitchCase(node); } @override - Object visitSwitchDefault(SwitchDefault node) { + void visitSwitchDefault(SwitchDefault node) { _checkForDeadStatementsInNodeList(node.statements, allowMandated: true); - return super.visitSwitchDefault(node); + super.visitSwitchDefault(node); } @override - Object visitSwitchStatement(SwitchStatement node) { + void visitSwitchStatement(SwitchStatement node) { List<Label> labels = <Label>[]; for (SwitchMember member in node.members) { labels.addAll(member.labels); @@ -1584,11 +1584,10 @@ } finally { _popLabels(); } - return null; } @override - Object visitTryStatement(TryStatement node) { + void visitTryStatement(TryStatement node) { node.body?.accept(this); node.finallyBlock?.accept(this); NodeList<CatchClause> catchClauses = node.catchClauses; @@ -1615,7 +1614,7 @@ int length = lastCatchClause.end - offset; _errorReporter.reportErrorForOffset( HintCode.DEAD_CODE_CATCH_FOLLOWING_CATCH, offset, length); - return null; + return; } } int length = visitedTypes.length; @@ -1630,7 +1629,7 @@ offset, length, [currentType.displayName, type.displayName]); - return null; + return; } } visitedTypes.add(currentType); @@ -1649,15 +1648,14 @@ int length = lastCatchClause.end - offset; _errorReporter.reportErrorForOffset( HintCode.DEAD_CODE_CATCH_FOLLOWING_CATCH, offset, length); - return null; + return; } } } - return null; } @override - Object visitWhileStatement(WhileStatement node) { + void visitWhileStatement(WhileStatement node) { Expression conditionExpression = node.condition; conditionExpression?.accept(this); if (!_isDebugConstant(conditionExpression)) { @@ -1667,12 +1665,11 @@ if (result.value.toBoolValue() == false) { // Report error on while block: while (false) {!} _errorReporter.reportErrorForNode(HintCode.DEAD_CODE, node.body); - return null; + return; } } } node.body?.accept(this); - return null; } /// Resolve the names in the given [combinator] in the scope of the given @@ -2273,7 +2270,7 @@ /// Instances of the class `EnumMemberBuilder` build the members in enum /// declarations. -class EnumMemberBuilder extends RecursiveAstVisitor<Object> { +class EnumMemberBuilder extends RecursiveAstVisitor<void> { /// The type provider used to access the types needed to build an element /// model for enum declarations. final TypeProvider _typeProvider; @@ -2285,7 +2282,7 @@ EnumMemberBuilder(this._typeProvider); @override - Object visitEnumDeclaration(EnumDeclaration node) { + void visitEnumDeclaration(EnumDeclaration node) { // // Finish building the enum. // @@ -2351,7 +2348,7 @@ enumElement.accessors = getters; // Client code isn't allowed to invoke the constructor, so we do not model // it. - return super.visitEnumDeclaration(node); + super.visitEnumDeclaration(node); } /// Create a getter that corresponds to the given [field]. @@ -3907,38 +3904,38 @@ nameScope: nameScope); @override - Object visitBlockFunctionBody(BlockFunctionBody node) { + void visitBlockFunctionBody(BlockFunctionBody node) { if (_shouldBeSkipped(node)) { return null; } - return super.visitBlockFunctionBody(node); + super.visitBlockFunctionBody(node); } @override - Object visitExpressionFunctionBody(ExpressionFunctionBody node) { + void visitExpressionFunctionBody(ExpressionFunctionBody node) { if (_shouldBeSkipped(node)) { return null; } - return super.visitExpressionFunctionBody(node); + super.visitExpressionFunctionBody(node); } @override - Object visitFieldDeclaration(FieldDeclaration node) { + void visitFieldDeclaration(FieldDeclaration node) { if (node.isStatic) { _addStaticVariables(node.fields.variables); } - return super.visitFieldDeclaration(node); + super.visitFieldDeclaration(node); } @override - Object visitNode(AstNode node) { - return super.visitNode(node); + void visitNode(AstNode node) { + super.visitNode(node); } @override - Object visitTopLevelVariableDeclaration(TopLevelVariableDeclaration node) { + void visitTopLevelVariableDeclaration(TopLevelVariableDeclaration node) { _addStaticVariables(node.variables.variables); - return super.visitTopLevelVariableDeclaration(node); + super.visitTopLevelVariableDeclaration(node); } /// Add all of the [variables] with initializers to the list of variables @@ -4341,12 +4338,12 @@ } @override - Object visitAnnotation(Annotation node) { + void visitAnnotation(Annotation node) { AstNode parent = node.parent; if (identical(parent, _enclosingClassDeclaration) || identical(parent, _enclosingFunctionTypeAlias) || identical(parent, _enclosingMixinDeclaration)) { - return null; + return; } node.name?.accept(this); node.constructorName?.accept(this); @@ -4364,11 +4361,10 @@ } else { elementAnnotationImpl.annotationAst = _createCloner().cloneNode(node); } - return null; } @override - Object visitArgumentList(ArgumentList node) { + void visitArgumentList(ArgumentList node) { DartType callerType = InferenceContext.getContext(node); if (callerType is FunctionType) { Map<String, DartType> namedParameterTypes = @@ -4408,26 +4404,24 @@ } } } - return super.visitArgumentList(node); + super.visitArgumentList(node); } @override - Object visitAssertInitializer(AssertInitializer node) { + void visitAssertInitializer(AssertInitializer node) { InferenceContext.setType(node.condition, typeProvider.boolType); super.visitAssertInitializer(node); - return null; } @override - Object visitAssertStatement(AssertStatement node) { + void visitAssertStatement(AssertStatement node) { InferenceContext.setType(node.condition, typeProvider.boolType); super.visitAssertStatement(node); _propagateTrueState(node.condition); - return null; } @override - Object visitAssignmentExpression(AssignmentExpression node) { + void visitAssignmentExpression(AssignmentExpression node) { node.leftHandSide?.accept(this); TokenType operator = node.operator.type; if (operator == TokenType.EQ || @@ -4438,21 +4432,20 @@ node.rightHandSide?.accept(this); node.accept(elementResolver); node.accept(typeAnalyzer); - return null; } @override - Object visitAwaitExpression(AwaitExpression node) { + void visitAwaitExpression(AwaitExpression node) { DartType contextType = InferenceContext.getContext(node); if (contextType != null) { var futureUnion = _createFutureOr(contextType); InferenceContext.setType(node.expression, futureUnion); } - return super.visitAwaitExpression(node); + super.visitAwaitExpression(node); } @override - Object visitBinaryExpression(BinaryExpression node) { + void visitBinaryExpression(BinaryExpression node) { TokenType operatorType = node.operator.type; Expression leftOperand = node.leftOperand; Expression rightOperand = node.rightOperand; @@ -4527,11 +4520,10 @@ rightOperand?.accept(this); } node.accept(typeAnalyzer); - return null; } @override - Object visitBlockFunctionBody(BlockFunctionBody node) { + void visitBlockFunctionBody(BlockFunctionBody node) { _overrideManager.enterScope(); try { inferenceContext.pushReturnContext(node); @@ -4540,28 +4532,26 @@ _overrideManager.exitScope(); inferenceContext.popReturnContext(node); } - return null; } @override - Object visitBreakStatement(BreakStatement node) { + void visitBreakStatement(BreakStatement node) { // // We do not visit the label because it needs to be visited in the context // of the statement. // node.accept(elementResolver); node.accept(typeAnalyzer); - return null; } @override - Object visitCascadeExpression(CascadeExpression node) { + void visitCascadeExpression(CascadeExpression node) { InferenceContext.setTypeFromNode(node.target, node); - return super.visitCascadeExpression(node); + super.visitCascadeExpression(node); } @override - Object visitClassDeclaration(ClassDeclaration node) { + void visitClassDeclaration(ClassDeclaration node) { // // Resolve the metadata in the library scope. // @@ -4582,12 +4572,11 @@ enclosingClass = outerType; _enclosingClassDeclaration = null; } - return null; } /// Implementation of this method should be synchronized with /// [visitClassDeclaration]. - visitClassDeclarationIncrementally(ClassDeclaration node) { + void visitClassDeclarationIncrementally(ClassDeclaration node) { // // Resolve the metadata in the library scope. // @@ -4603,31 +4592,29 @@ } @override - Object visitComment(Comment node) { + void visitComment(Comment node) { AstNode parent = node.parent; if (parent is FunctionDeclaration || parent is FunctionTypeAlias || parent is ConstructorDeclaration || parent is MethodDeclaration) { - return null; + return; } super.visitComment(node); - return null; } @override - Object visitCommentReference(CommentReference node) { + void visitCommentReference(CommentReference node) { // // We do not visit the identifier because it needs to be visited in the // context of the reference. // node.accept(elementResolver); node.accept(typeAnalyzer); - return null; } @override - Object visitCompilationUnit(CompilationUnit node) { + void visitCompilationUnit(CompilationUnit node) { _overrideManager.enterScope(); try { NodeList<Directive> directives = node.directives; @@ -4645,11 +4632,10 @@ } node.accept(elementResolver); node.accept(typeAnalyzer); - return null; } @override - Object visitConditionalExpression(ConditionalExpression node) { + void visitConditionalExpression(ConditionalExpression node) { Expression condition = node.condition; condition?.accept(this); Expression thenExpression = node.thenExpression; @@ -4696,11 +4682,10 @@ _propagateFalseState(condition); _propagateState(elseExpression); } - return null; } @override - Object visitConstructorDeclaration(ConstructorDeclaration node) { + void visitConstructorDeclaration(ConstructorDeclaration node) { ExecutableElement outerFunction = _enclosingFunction; FunctionBody outerFunctionBody = _currentFunctionBody; try { @@ -4716,7 +4701,6 @@ ConstructorElementImpl constructor = node.declaredElement; constructor.constantInitializers = _createCloner().cloneNodeList(node.initializers); - return null; } @override @@ -4732,7 +4716,7 @@ } @override - Object visitConstructorFieldInitializer(ConstructorFieldInitializer node) { + void visitConstructorFieldInitializer(ConstructorFieldInitializer node) { // // We visit the expression, but do not visit the field name because it needs // to be visited in the context of the constructor field initializer node. @@ -4742,11 +4726,10 @@ node.expression?.accept(this); node.accept(elementResolver); node.accept(typeAnalyzer); - return null; } @override - Object visitConstructorName(ConstructorName node) { + void visitConstructorName(ConstructorName node) { // // We do not visit either the type name, because it won't be visited anyway, // or the name, because it needs to be visited in the context of the @@ -4754,22 +4737,20 @@ // node.accept(elementResolver); node.accept(typeAnalyzer); - return null; } @override - Object visitContinueStatement(ContinueStatement node) { + void visitContinueStatement(ContinueStatement node) { // // We do not visit the label because it needs to be visited in the context // of the statement. // node.accept(elementResolver); node.accept(typeAnalyzer); - return null; } @override - Object visitDefaultFormalParameter(DefaultFormalParameter node) { + void visitDefaultFormalParameter(DefaultFormalParameter node) { InferenceContext.setType(node.defaultValue, resolutionMap.elementDeclaredByFormalParameter(node.parameter)?.type); super.visitDefaultFormalParameter(node); @@ -4785,11 +4766,10 @@ (element as ConstVariableElement).constantInitializer = _createCloner().cloneNode(node.defaultValue); } - return null; } @override - Object visitDoStatement(DoStatement node) { + void visitDoStatement(DoStatement node) { _overrideManager.enterScope(); try { InferenceContext.setType(node.condition, typeProvider.boolType); @@ -4799,19 +4779,18 @@ } // TODO(brianwilkerson) If the loop can only be exited because the condition // is false, then propagateFalseState(node.getCondition()); - return null; } @override - Object visitEmptyFunctionBody(EmptyFunctionBody node) { + void visitEmptyFunctionBody(EmptyFunctionBody node) { if (resolveOnlyCommentInFunctionBody) { - return null; + return; } - return super.visitEmptyFunctionBody(node); + super.visitEmptyFunctionBody(node); } @override - Object visitEnumDeclaration(EnumDeclaration node) { + void visitEnumDeclaration(EnumDeclaration node) { // // Resolve the metadata in the library scope // and associate the annotations with the element. @@ -4836,13 +4815,12 @@ enclosingClass = outerType; _enclosingClassDeclaration = null; } - return null; } @override - Object visitExpressionFunctionBody(ExpressionFunctionBody node) { + void visitExpressionFunctionBody(ExpressionFunctionBody node) { if (resolveOnlyCommentInFunctionBody) { - return null; + return; } _overrideManager.enterScope(); try { @@ -4861,11 +4839,10 @@ _overrideManager.exitScope(); inferenceContext.popReturnContext(node); } - return null; } @override - Object visitFieldDeclaration(FieldDeclaration node) { + void visitFieldDeclaration(FieldDeclaration node) { _overrideManager.enterScope(); try { super.visitFieldDeclaration(node); @@ -4875,18 +4852,16 @@ _overrideManager.exitScope(); _overrideManager.applyOverrides(overrides); } - return null; } @override - Object visitForEachStatement(ForEachStatement node) { + void visitForEachStatement(ForEachStatement node) { _overrideManager.enterScope(); try { super.visitForEachStatement(node); } finally { _overrideManager.exitScope(); } - return null; } @override @@ -4959,14 +4934,13 @@ } @override - Object visitForStatement(ForStatement node) { + void visitForStatement(ForStatement node) { _overrideManager.enterScope(); try { super.visitForStatement(node); } finally { _overrideManager.exitScope(); } - return null; } @override @@ -4988,7 +4962,7 @@ } @override - Object visitFunctionDeclaration(FunctionDeclaration node) { + void visitFunctionDeclaration(FunctionDeclaration node) { ExecutableElement outerFunction = _enclosingFunction; FunctionBody outerFunctionBody = _currentFunctionBody; try { @@ -5002,7 +4976,6 @@ _currentFunctionBody = outerFunctionBody; _enclosingFunction = outerFunction; } - return null; } @override @@ -5012,7 +4985,7 @@ } @override - Object visitFunctionExpression(FunctionExpression node) { + void visitFunctionExpression(FunctionExpression node) { ExecutableElement outerFunction = _enclosingFunction; FunctionBody outerFunctionBody = _currentFunctionBody; try { @@ -5039,21 +5012,19 @@ _currentFunctionBody = outerFunctionBody; _enclosingFunction = outerFunction; } - return null; } @override - Object visitFunctionExpressionInvocation(FunctionExpressionInvocation node) { + void visitFunctionExpressionInvocation(FunctionExpressionInvocation node) { node.function?.accept(this); node.accept(elementResolver); _inferArgumentTypesForInvocation(node); node.argumentList?.accept(this); node.accept(typeAnalyzer); - return null; } @override - Object visitFunctionTypeAlias(FunctionTypeAlias node) { + void visitFunctionTypeAlias(FunctionTypeAlias node) { // Resolve the metadata in the library scope. if (node.metadata != null) { node.metadata.accept(this); @@ -5065,7 +5036,6 @@ } finally { _enclosingFunctionTypeAlias = outerAlias; } - return null; } @override @@ -5075,20 +5045,19 @@ } @override - Object visitGenericFunctionType(GenericFunctionType node) => null; + void visitGenericFunctionType(GenericFunctionType node) {} @override - Object visitGenericTypeAliasInFunctionScope(GenericTypeAlias node) { + void visitGenericTypeAliasInFunctionScope(GenericTypeAlias node) { super.visitGenericTypeAliasInFunctionScope(node); safelyVisitComment(node.documentationComment); - return null; } @override - Object visitHideCombinator(HideCombinator node) => null; + void visitHideCombinator(HideCombinator node) {} @override - Object visitIfStatement(IfStatement node) { + void visitIfStatement(IfStatement node) { Expression condition = node.condition; InferenceContext.setType(condition, typeProvider.boolType); condition?.accept(this); @@ -5147,11 +5116,10 @@ perBranchOverrides.add(elseOverrides); _overrideManager.mergeOverrides(perBranchOverrides); } - return null; } @override - Object visitIndexExpression(IndexExpression node) { + void visitIndexExpression(IndexExpression node) { node.target?.accept(this); node.accept(elementResolver); var method = node.staticElement; @@ -5161,27 +5129,25 @@ } node.index?.accept(this); node.accept(typeAnalyzer); - return null; } @override - Object visitInstanceCreationExpression(InstanceCreationExpression node) { + void visitInstanceCreationExpression(InstanceCreationExpression node) { node.constructorName?.accept(this); _inferArgumentTypesForInstanceCreate(node); node.argumentList?.accept(this); node.accept(elementResolver); node.accept(typeAnalyzer); - return null; } @override - Object visitLabel(Label node) => null; + void visitLabel(Label node) {} @override - Object visitLibraryIdentifier(LibraryIdentifier node) => null; + void visitLibraryIdentifier(LibraryIdentifier node) {} @override - Object visitListLiteral(ListLiteral node) { + void visitListLiteral(ListLiteral node) { InterfaceType listT; if (node.typeArguments != null) { @@ -5202,11 +5168,10 @@ InferenceContext.clearType(node); } super.visitListLiteral(node); - return null; } @override - Object visitMapLiteral(MapLiteral node) { + void visitMapLiteral(MapLiteral node) { InterfaceType mapT; if (node.typeArguments != null) { var targs = node.typeArguments.arguments.map((t) => t.type).toList(); @@ -5215,6 +5180,15 @@ } } else { mapT = typeAnalyzer.inferMapType(node, downwards: true); + if (mapT != null && + node.typeArguments == null && + node.entries.isEmpty && + typeSystem.isAssignableTo(typeProvider.setNullType, mapT) && + !typeSystem.isAssignableTo(typeProvider.mapNullNullType, mapT)) { + // The node is really an empty set literal with no type arguments, so + // don't try to visit the replaced map literal. + return; + } } if (mapT != null) { DartType kType = mapT.typeArguments[0]; @@ -5228,11 +5202,10 @@ InferenceContext.clearType(node); } super.visitMapLiteral(node); - return null; } @override - Object visitMethodDeclaration(MethodDeclaration node) { + void visitMethodDeclaration(MethodDeclaration node) { ExecutableElement outerFunction = _enclosingFunction; FunctionBody outerFunctionBody = _currentFunctionBody; try { @@ -5246,7 +5219,6 @@ _currentFunctionBody = outerFunctionBody; _enclosingFunction = outerFunction; } - return null; } @override @@ -5256,7 +5228,7 @@ } @override - Object visitMethodInvocation(MethodInvocation node) { + void visitMethodInvocation(MethodInvocation node) { // // We visit the target and argument list, but do not visit the method name // because it needs to be visited in the context of the invocation. @@ -5267,11 +5239,10 @@ _inferArgumentTypesForInvocation(node); node.argumentList?.accept(this); node.accept(typeAnalyzer); - return null; } @override - Object visitMixinDeclaration(MixinDeclaration node) { + void visitMixinDeclaration(MixinDeclaration node) { // // Resolve the metadata in the library scope. // @@ -5292,31 +5263,29 @@ enclosingClass = outerType; _enclosingMixinDeclaration = null; } - return null; } @override - Object visitNamedExpression(NamedExpression node) { + void visitNamedExpression(NamedExpression node) { InferenceContext.setTypeFromNode(node.expression, node); - return super.visitNamedExpression(node); + super.visitNamedExpression(node); } @override - Object visitNode(AstNode node) { + void visitNode(AstNode node) { node.visitChildren(this); node.accept(elementResolver); node.accept(typeAnalyzer); - return null; } @override - Object visitParenthesizedExpression(ParenthesizedExpression node) { + void visitParenthesizedExpression(ParenthesizedExpression node) { InferenceContext.setTypeFromNode(node.expression, node); - return super.visitParenthesizedExpression(node); + super.visitParenthesizedExpression(node); } @override - Object visitPrefixedIdentifier(PrefixedIdentifier node) { + void visitPrefixedIdentifier(PrefixedIdentifier node) { // // We visit the prefix, but do not visit the identifier because it needs to // be visited in the context of the prefix. @@ -5324,11 +5293,10 @@ node.prefix?.accept(this); node.accept(elementResolver); node.accept(typeAnalyzer); - return null; } @override - Object visitPropertyAccess(PropertyAccess node) { + void visitPropertyAccess(PropertyAccess node) { // // We visit the target, but do not visit the property name because it needs // to be visited in the context of the property access node. @@ -5336,11 +5304,10 @@ node.target?.accept(this); node.accept(elementResolver); node.accept(typeAnalyzer); - return null; } @override - Object visitRedirectingConstructorInvocation( + void visitRedirectingConstructorInvocation( RedirectingConstructorInvocation node) { // // We visit the argument list, but do not visit the optional identifier @@ -5352,11 +5319,10 @@ node.argumentList?.accept(this); node.accept(elementResolver); node.accept(typeAnalyzer); - return null; } @override - Object visitReturnStatement(ReturnStatement node) { + void visitReturnStatement(ReturnStatement node) { Expression e = node.expression; InferenceContext.setType(e, inferenceContext.returnContext); super.visitReturnStatement(node); @@ -5369,14 +5335,13 @@ } inferenceContext.addReturnOrYieldType(type); } - return null; } @override - Object visitShowCombinator(ShowCombinator node) => null; + void visitShowCombinator(ShowCombinator node) {} @override - Object visitSuperConstructorInvocation(SuperConstructorInvocation node) { + void visitSuperConstructorInvocation(SuperConstructorInvocation node) { // // We visit the argument list, but do not visit the optional identifier // because it needs to be visited in the context of the constructor @@ -5387,11 +5352,10 @@ node.argumentList?.accept(this); node.accept(elementResolver); node.accept(typeAnalyzer); - return null; } @override - Object visitSwitchCase(SwitchCase node) { + void visitSwitchCase(SwitchCase node) { _overrideManager.enterScope(); try { InferenceContext.setType( @@ -5400,22 +5364,20 @@ } finally { _overrideManager.exitScope(); } - return null; } @override - Object visitSwitchDefault(SwitchDefault node) { + void visitSwitchDefault(SwitchDefault node) { _overrideManager.enterScope(); try { super.visitSwitchDefault(node); } finally { _overrideManager.exitScope(); } - return null; } @override - Object visitSwitchStatementInScope(SwitchStatement node) { + void visitSwitchStatementInScope(SwitchStatement node) { var previousExpressionType = _enclosingSwitchStatementExpressionType; try { node.expression?.accept(this); @@ -5424,11 +5386,10 @@ } finally { _enclosingSwitchStatementExpressionType = previousExpressionType; } - return null; } @override - Object visitTopLevelVariableDeclaration(TopLevelVariableDeclaration node) { + void visitTopLevelVariableDeclaration(TopLevelVariableDeclaration node) { _overrideManager.enterScope(); try { super.visitTopLevelVariableDeclaration(node); @@ -5438,14 +5399,13 @@ _overrideManager.exitScope(); _overrideManager.applyOverrides(overrides); } - return null; } @override - Object visitTypeName(TypeName node) => null; + void visitTypeName(TypeName node) {} @override - Object visitVariableDeclaration(VariableDeclaration node) { + void visitVariableDeclaration(VariableDeclaration node) { InferenceContext.setTypeFromNode(node.initializer, node); super.visitVariableDeclaration(node); VariableElement element = node.declaredElement; @@ -5461,22 +5421,20 @@ (element as ConstVariableElement).constantInitializer = _createCloner().cloneNode(node.initializer); } - return null; } @override - Object visitVariableDeclarationList(VariableDeclarationList node) { + void visitVariableDeclarationList(VariableDeclarationList node) { for (VariableDeclaration decl in node.variables) { VariableElement variableElement = resolutionMap.elementDeclaredByVariableDeclaration(decl); InferenceContext.setType(decl, variableElement?.type); } super.visitVariableDeclarationList(node); - return null; } @override - Object visitWhileStatement(WhileStatement node) { + void visitWhileStatement(WhileStatement node) { // Note: since we don't call the base class, we have to maintain // _implicitLabelScope ourselves. ImplicitLabelScope outerImplicitScope = _implicitLabelScope; @@ -5502,11 +5460,10 @@ // is false, then propagateFalseState(condition); node.accept(elementResolver); node.accept(typeAnalyzer); - return null; } @override - Object visitYieldStatement(YieldStatement node) { + void visitYieldStatement(YieldStatement node) { Expression e = node.expression; DartType returnType = inferenceContext.returnContext; bool isGenerator = _enclosingFunction?.isGenerator ?? false; @@ -5542,7 +5499,6 @@ inferenceContext.addReturnOrYieldType(type); } } - return null; } /// Checks each promoted variable in the current scope for compliance with the @@ -6110,7 +6066,7 @@ /// The abstract class `ScopedVisitor` maintains name and label scopes as an AST /// structure is being visited. -abstract class ScopedVisitor extends UnifyingAstVisitor<Object> { +abstract class ScopedVisitor extends UnifyingAstVisitor<void> { /// The element for the library containing the compilation unit being visited. final LibraryElement definingLibrary; @@ -6185,7 +6141,7 @@ } @override - Object visitBlock(Block node) { + void visitBlock(Block node) { Scope outerScope = nameScope; try { EnclosedScope enclosedScope = new BlockScope(nameScope, node); @@ -6194,11 +6150,10 @@ } finally { nameScope = outerScope; } - return null; } @override - Object visitBlockFunctionBody(BlockFunctionBody node) { + void visitBlockFunctionBody(BlockFunctionBody node) { ImplicitLabelScope implicitOuterScope = _implicitLabelScope; try { _implicitLabelScope = ImplicitLabelScope.ROOT; @@ -6206,11 +6161,10 @@ } finally { _implicitLabelScope = implicitOuterScope; } - return null; } @override - Object visitCatchClause(CatchClause node) { + void visitCatchClause(CatchClause node) { SimpleIdentifier exception = node.exceptionParameter; if (exception != null) { Scope outerScope = nameScope; @@ -6228,11 +6182,10 @@ } else { super.visitCatchClause(node); } - return null; } @override - Object visitClassDeclaration(ClassDeclaration node) { + void visitClassDeclaration(ClassDeclaration node) { ClassElement classElement = node.declaredElement; Scope outerScope = nameScope; try { @@ -6256,7 +6209,6 @@ } finally { nameScope = outerScope; } - return null; } void visitClassDeclarationInScope(ClassDeclaration node) { @@ -6275,7 +6227,7 @@ } @override - Object visitClassTypeAlias(ClassTypeAlias node) { + void visitClassTypeAlias(ClassTypeAlias node) { Scope outerScope = nameScope; try { ClassElement element = node.declaredElement; @@ -6285,11 +6237,10 @@ } finally { nameScope = outerScope; } - return null; } @override - Object visitConstructorDeclaration(ConstructorDeclaration node) { + void visitConstructorDeclaration(ConstructorDeclaration node) { ConstructorElement constructorElement = node.declaredElement; if (constructorElement == null) { StringBuffer buffer = new StringBuffer(); @@ -6329,7 +6280,6 @@ } finally { nameScope = outerScope; } - return null; } void visitConstructorDeclarationInScope(ConstructorDeclaration node) { @@ -6337,17 +6287,16 @@ } @override - Object visitDeclaredIdentifier(DeclaredIdentifier node) { + void visitDeclaredIdentifier(DeclaredIdentifier node) { VariableElement element = node.declaredElement; if (element != null) { nameScope.define(element); } super.visitDeclaredIdentifier(node); - return null; } @override - Object visitDoStatement(DoStatement node) { + void visitDoStatement(DoStatement node) { ImplicitLabelScope outerImplicitScope = _implicitLabelScope; try { _implicitLabelScope = _implicitLabelScope.nest(node); @@ -6356,11 +6305,10 @@ } finally { _implicitLabelScope = outerImplicitScope; } - return null; } @override - Object visitEnumDeclaration(EnumDeclaration node) { + void visitEnumDeclaration(EnumDeclaration node) { ClassElement classElement = node.declaredElement; Scope outerScope = nameScope; try { @@ -6382,7 +6330,6 @@ } finally { nameScope = outerScope; } - return null; } void visitEnumMembersInScope(EnumDeclaration node) { @@ -6392,7 +6339,7 @@ } @override - Object visitForEachStatement(ForEachStatement node) { + void visitForEachStatement(ForEachStatement node) { Scope outerNameScope = nameScope; ImplicitLabelScope outerImplicitScope = _implicitLabelScope; try { @@ -6403,7 +6350,6 @@ nameScope = outerNameScope; _implicitLabelScope = outerImplicitScope; } - return null; } /// Visit the given statement after it's scope has been created. This replaces @@ -6423,7 +6369,7 @@ } @override - Object visitFormalParameterList(FormalParameterList node) { + void visitFormalParameterList(FormalParameterList node) { super.visitFormalParameterList(node); // We finished resolving function signature, now include formal parameters // scope. Note: we must not do this if the parent is a @@ -6436,11 +6382,10 @@ if (nameScope is FunctionTypeScope) { (nameScope as FunctionTypeScope).defineParameters(); } - return null; } @override - Object visitForStatement(ForStatement node) { + void visitForStatement(ForStatement node) { Scope outerNameScope = nameScope; ImplicitLabelScope outerImplicitScope = _implicitLabelScope; try { @@ -6451,7 +6396,6 @@ nameScope = outerNameScope; _implicitLabelScope = outerImplicitScope; } - return null; } /// Visit the given statement after it's scope has been created. This replaces @@ -6468,7 +6412,7 @@ } @override - Object visitFunctionDeclaration(FunctionDeclaration node) { + void visitFunctionDeclaration(FunctionDeclaration node) { ExecutableElement functionElement = node.declaredElement; if (functionElement != null && functionElement.enclosingElement is! CompilationUnitElement) { @@ -6487,7 +6431,6 @@ } finally { nameScope = outerScope; } - return null; } void visitFunctionDeclarationInScope(FunctionDeclaration node) { @@ -6495,7 +6438,7 @@ } @override - Object visitFunctionExpression(FunctionExpression node) { + void visitFunctionExpression(FunctionExpression node) { if (node.parent is FunctionDeclaration) { // We have already created a function scope and don't need to do so again. super.visitFunctionExpression(node); @@ -6528,11 +6471,10 @@ nameScope = outerScope; } } - return null; } @override - Object visitFunctionTypeAlias(FunctionTypeAlias node) { + void visitFunctionTypeAlias(FunctionTypeAlias node) { Scope outerScope = nameScope; try { nameScope = new FunctionTypeScope(nameScope, node.declaredElement); @@ -6540,7 +6482,6 @@ } finally { nameScope = outerScope; } - return null; } void visitFunctionTypeAliasInScope(FunctionTypeAlias node) { @@ -6548,7 +6489,7 @@ } @override - Object visitFunctionTypedFormalParameter(FunctionTypedFormalParameter node) { + void visitFunctionTypedFormalParameter(FunctionTypedFormalParameter node) { Scope outerScope = nameScope; try { ParameterElement parameterElement = node.declaredElement; @@ -6569,16 +6510,16 @@ } finally { nameScope = outerScope; } - return null; } @override - Object visitGenericFunctionType(GenericFunctionType node) { + void visitGenericFunctionType(GenericFunctionType node) { DartType type = node.type; if (type == null) { // The function type hasn't been resolved yet, so we can't create a scope // for its parameters. - return super.visitGenericFunctionType(node); + super.visitGenericFunctionType(node); + return; } GenericFunctionTypeElement element = type.element; Scope outerScope = nameScope; @@ -6595,11 +6536,10 @@ } finally { nameScope = outerScope; } - return null; } @override - Object visitGenericTypeAlias(GenericTypeAlias node) { + void visitGenericTypeAlias(GenericTypeAlias node) { GenericTypeAliasElement element = node.declaredElement; Scope outerScope = nameScope; try { @@ -6622,34 +6562,29 @@ } finally { nameScope = outerScope; } - return null; } - Object visitGenericTypeAliasInFunctionScope(GenericTypeAlias node) { - return null; - } + void visitGenericTypeAliasInFunctionScope(GenericTypeAlias node) {} @override - Object visitIfStatement(IfStatement node) { + void visitIfStatement(IfStatement node) { node.condition?.accept(this); visitStatementInScope(node.thenStatement); visitStatementInScope(node.elseStatement); - return null; } @override - Object visitLabeledStatement(LabeledStatement node) { + void visitLabeledStatement(LabeledStatement node) { LabelScope outerScope = _addScopesFor(node.labels, node.unlabeled); try { super.visitLabeledStatement(node); } finally { labelScope = outerScope; } - return null; } @override - Object visitMethodDeclaration(MethodDeclaration node) { + void visitMethodDeclaration(MethodDeclaration node) { Scope outerScope = nameScope; try { ExecutableElement methodElement = node.declaredElement; @@ -6664,7 +6599,6 @@ } finally { nameScope = outerScope; } - return null; } void visitMethodDeclarationInScope(MethodDeclaration node) { @@ -6672,7 +6606,7 @@ } @override - Object visitMixinDeclaration(MixinDeclaration node) { + void visitMixinDeclaration(MixinDeclaration node) { ClassElement element = node.declaredElement; Scope outerScope = nameScope; @@ -6689,7 +6623,6 @@ nameScope = outerScope; enclosingClass = outerClass; } - return null; } void visitMixinDeclarationInScope(MixinDeclaration node) { @@ -6727,7 +6660,7 @@ } @override - Object visitSwitchCase(SwitchCase node) { + void visitSwitchCase(SwitchCase node) { node.expression.accept(this); Scope outerNameScope = nameScope; try { @@ -6736,11 +6669,10 @@ } finally { nameScope = outerNameScope; } - return null; } @override - Object visitSwitchDefault(SwitchDefault node) { + void visitSwitchDefault(SwitchDefault node) { Scope outerNameScope = nameScope; try { nameScope = new EnclosedScope(nameScope); @@ -6748,11 +6680,10 @@ } finally { nameScope = outerNameScope; } - return null; } @override - Object visitSwitchStatement(SwitchStatement node) { + void visitSwitchStatement(SwitchStatement node) { LabelScope outerScope = labelScope; ImplicitLabelScope outerImplicitScope = _implicitLabelScope; try { @@ -6770,7 +6701,6 @@ labelScope = outerScope; _implicitLabelScope = outerImplicitScope; } - return null; } void visitSwitchStatementInScope(SwitchStatement node) { @@ -6778,7 +6708,7 @@ } @override - Object visitVariableDeclaration(VariableDeclaration node) { + void visitVariableDeclaration(VariableDeclaration node) { super.visitVariableDeclaration(node); if (node.parent.parent is! TopLevelVariableDeclaration && node.parent.parent is! FieldDeclaration) { @@ -6787,11 +6717,10 @@ nameScope.define(element); } } - return null; } @override - Object visitWhileStatement(WhileStatement node) { + void visitWhileStatement(WhileStatement node) { node.condition?.accept(this); ImplicitLabelScope outerImplicitScope = _implicitLabelScope; try { @@ -6800,7 +6729,6 @@ } finally { _implicitLabelScope = outerImplicitScope; } - return null; } /// Add scopes for each of the given labels. @@ -7889,6 +7817,9 @@ /// Return the type representing the built-in type 'List'. InterfaceType get listType; + /// Return the type representing 'Map<Null, Null>'. + InterfaceType get mapNullNullType; + /// Return the type representing the built-in type 'Map'. InterfaceType get mapType; @@ -7908,6 +7839,12 @@ /// Return the type representing the built-in type 'Object'. InterfaceType get objectType; + /// Return the type representing 'Set<Null>'. + InterfaceType get setNullType; + + /// Return the type representing the built-in type 'Set'. + InterfaceType get setType; + /// Return the type representing the built-in type 'StackTrace'. InterfaceType get stackTraceType; @@ -8025,9 +7962,18 @@ /// The type representing the built-in type 'Map'. InterfaceType _mapType; + /// The type representing the built-in type 'Map<Null, Null>'. + InterfaceType _mapNullNullType; + /// An shared object representing the value 'null'. DartObjectImpl _nullObject; + /// The type representing the type 'Set'. + InterfaceType _setType; + + /// The type representing the type 'Set<Null>'. + InterfaceType _setNullType; + /// The type representing the type 'Null'. InterfaceType _nullType; @@ -8121,6 +8067,9 @@ InterfaceType get listType => _listType; @override + InterfaceType get mapNullNullType => _mapNullNullType; + + @override InterfaceType get mapType => _mapType; @override @@ -8141,6 +8090,12 @@ InterfaceType get objectType => _objectType; @override + InterfaceType get setNullType => _setNullType; + + @override + InterfaceType get setType => _setType; + + @override InterfaceType get stackTraceType => _stackTraceType; @override @@ -8195,6 +8150,7 @@ _nullType = _getType(coreNamespace, "Null"); _numType = _getType(coreNamespace, "num"); _objectType = _getType(coreNamespace, "Object"); + _setType = _getType(coreNamespace, "Set"); _stackTraceType = _getType(coreNamespace, "StackTrace"); _streamType = _getType(asyncNamespace, "Stream"); _stringType = _getType(coreNamespace, "String"); @@ -8204,6 +8160,8 @@ _futureDynamicType = _futureType.instantiate(<DartType>[_dynamicType]); _futureNullType = _futureType.instantiate(<DartType>[_nullType]); _iterableDynamicType = _iterableType.instantiate(<DartType>[_dynamicType]); + _mapNullNullType = _mapType.instantiate(<DartType>[_nullType, _nullType]); + _setNullType = _setType.instantiate(<DartType>[_nullType]); _streamDynamicType = _streamType.instantiate(<DartType>[_dynamicType]); // FutureOr<T> is still fairly new, so if we're analyzing an SDK that // doesn't have it yet, create an element for it. @@ -8311,7 +8269,7 @@ } @override - Object visitAnnotation(Annotation node) { + void visitAnnotation(Annotation node) { // // Visit annotations, if the annotation is @proxy, on a class, and "proxy" // resolves to the proxy annotation in dart.core, then resolve the @@ -8336,11 +8294,10 @@ elementAnnotation.element = element; } } - return null; } @override - Object visitCatchClause(CatchClause node) { + void visitCatchClause(CatchClause node) { super.visitCatchClause(node); SimpleIdentifier exception = node.exceptionParameter; if (exception != null) { @@ -8372,11 +8329,10 @@ // TODO(brianwilkerson) Report the internal error } } - return null; } @override - Object visitClassDeclaration(ClassDeclaration node) { + void visitClassDeclaration(ClassDeclaration node) { _hasReferenceToSuper = false; super.visitClassDeclaration(node); ClassElementImpl classElement = _getClassElement(node.name); @@ -8385,7 +8341,6 @@ classElement.hasBeenInferred = false; classElement.hasReferenceToSuper = _hasReferenceToSuper; } - return null; } @override @@ -8414,7 +8369,6 @@ } _resolveWithClause(classElement, withClause); _resolveImplementsClause(classElement, implementsClause); - return null; } @override @@ -8443,7 +8397,7 @@ } @override - Object visitClassTypeAlias(ClassTypeAlias node) { + void visitClassTypeAlias(ClassTypeAlias node) { super.visitClassTypeAlias(node); ErrorCode errorCode = CompileTimeErrorCode.MIXIN_WITH_NON_CLASS_SUPERCLASS; InterfaceType superclassType = @@ -8457,15 +8411,14 @@ } _resolveWithClause(classElement, node.withClause); _resolveImplementsClause(classElement, node.implementsClause); - return null; } @override - Object visitConstructorDeclaration(ConstructorDeclaration node) { + void visitConstructorDeclaration(ConstructorDeclaration node) { super.visitConstructorDeclaration(node); if (node.declaredElement == null) { ClassDeclaration classNode = - node.getAncestor((node) => node is ClassDeclaration); + node.thisOrAncestorOfType<ClassDeclaration>(); StringBuffer buffer = new StringBuffer(); buffer.write("The element for the constructor "); buffer.write(node.name == null ? "<unnamed>" : node.name.name); @@ -8481,11 +8434,10 @@ AnalysisEngine.instance.logger.logError(buffer.toString(), new CaughtException(new AnalysisException(), null)); } - return null; } @override - Object visitDeclaredIdentifier(DeclaredIdentifier node) { + void visitDeclaredIdentifier(DeclaredIdentifier node) { super.visitDeclaredIdentifier(node); DartType declaredType; TypeAnnotation typeName = node.type; @@ -8497,11 +8449,10 @@ LocalVariableElementImpl element = node.declaredElement as LocalVariableElementImpl; element.declaredType = declaredType; - return null; } @override - Object visitFieldFormalParameter(FieldFormalParameter node) { + void visitFieldFormalParameter(FieldFormalParameter node) { super.visitFieldFormalParameter(node); Element element = node.identifier.staticElement; if (element is ParameterElementImpl) { @@ -8526,11 +8477,10 @@ } else { // TODO(brianwilkerson) Report this internal error } - return null; } @override - Object visitFunctionDeclaration(FunctionDeclaration node) { + void visitFunctionDeclaration(FunctionDeclaration node) { super.visitFunctionDeclaration(node); ExecutableElementImpl element = node.declaredElement as ExecutableElementImpl; @@ -8547,19 +8497,17 @@ element.declaredReturnType = _computeReturnType(node.returnType); element.type = new FunctionTypeImpl(element); _inferSetterReturnType(element); - return null; } @override - Object visitFunctionTypeAlias(FunctionTypeAlias node) { + void visitFunctionTypeAlias(FunctionTypeAlias node) { var element = node.declaredElement as GenericTypeAliasElementImpl; super.visitFunctionTypeAlias(node); element.function.returnType = _computeReturnType(node.returnType); - return null; } @override - Object visitFunctionTypedFormalParameter(FunctionTypedFormalParameter node) { + void visitFunctionTypedFormalParameter(FunctionTypedFormalParameter node) { super.visitFunctionTypedFormalParameter(node); Element element = node.identifier.staticElement; if (element is ParameterElementImpl) { @@ -8567,28 +8515,26 @@ } else { // TODO(brianwilkerson) Report this internal error } - return null; } @override - Object visitGenericFunctionType(GenericFunctionType node) { + void visitGenericFunctionType(GenericFunctionType node) { GenericFunctionTypeElementImpl element = node.type?.element; if (element != null) { super.visitGenericFunctionType(node); element.returnType = _computeReturnType(node.returnType) ?? DynamicTypeImpl.instance; } - return null; } @override - Object visitMethodDeclaration(MethodDeclaration node) { + void visitMethodDeclaration(MethodDeclaration node) { super.visitMethodDeclaration(node); ExecutableElementImpl element = node.declaredElement as ExecutableElementImpl; if (element == null) { ClassDeclaration classNode = - node.getAncestor((node) => node is ClassDeclaration); + node.thisOrAncestorOfType<ClassDeclaration>(); StringBuffer buffer = new StringBuffer(); buffer.write("The element for the method "); buffer.write(node.name.name); @@ -8609,7 +8555,7 @@ // already set - statically or inferred. We don't want to overwrite them. if (LibraryElementImpl.hasResolutionCapability( definingLibrary, LibraryResolutionCapability.resolvedTypeNames)) { - return null; + return; } element.declaredReturnType = _computeReturnType(node.returnType); @@ -8630,8 +8576,6 @@ variable.declaredType = type; } } - - return null; } @override @@ -8640,25 +8584,24 @@ MixinElementImpl element = node.declaredElement; _resolveOnClause(element, node.onClause); _resolveImplementsClause(element, node.implementsClause); - return null; } @override - Object visitNode(AstNode node) { + void visitNode(AstNode node) { // In API mode we need to skip: // - function bodies; // - default values of parameters; // - initializers of top-level variables. if (mode == TypeResolverMode.api) { if (node is FunctionBody) { - return null; + return; } if (node is DefaultFormalParameter) { node.parameter.accept(this); - return null; + return; } if (node is VariableDeclaration) { - return null; + return; } } @@ -8672,7 +8615,8 @@ if (mode == TypeResolverMode.local) { // We are in the state of visiting all nodes. if (_localModeVisitAll) { - return super.visitNode(node); + super.visitNode(node); + return; } // Ensure that the name scope is ready. @@ -8740,15 +8684,14 @@ } else if (node is VariableDeclarationList) { node.variables.forEach(visitNode); } - return null; + return; } - // The mode in which we visit all nodes. - return super.visitNode(node); + super.visitNode(node); } @override - Object visitSimpleFormalParameter(SimpleFormalParameter node) { + void visitSimpleFormalParameter(SimpleFormalParameter node) { super.visitSimpleFormalParameter(node); DartType declaredType; TypeAnnotation typeName = node.type; @@ -8763,25 +8706,23 @@ } else { // TODO(brianwilkerson) Report the internal error. } - return null; } @override - Object visitSuperExpression(SuperExpression node) { + void visitSuperExpression(SuperExpression node) { _hasReferenceToSuper = true; - return super.visitSuperExpression(node); + super.visitSuperExpression(node); } @override - Object visitTypeName(TypeName node) { + void visitTypeName(TypeName node) { super.visitTypeName(node); _typeNameResolver.nameScope = this.nameScope; _typeNameResolver.resolveTypeName(node); - return null; } @override - Object visitTypeParameter(TypeParameter node) { + void visitTypeParameter(TypeParameter node) { super.visitTypeParameter(node); AstNode parent2 = node.parent?.parent; if (parent2 is ClassDeclaration || @@ -8800,11 +8741,10 @@ } } } - return null; } @override - Object visitVariableDeclaration(VariableDeclaration node) { + void visitVariableDeclaration(VariableDeclaration node) { super.visitVariableDeclaration(node); var variableList = node.parent as VariableDeclarationList; // When the library is resynthesized, the types of field elements are @@ -8812,7 +8752,7 @@ if (variableList.parent is FieldDeclaration && LibraryElementImpl.hasResolutionCapability( definingLibrary, LibraryResolutionCapability.resolvedTypeNames)) { - return null; + return; } // Resolve the type. DartType declaredType; @@ -8826,7 +8766,6 @@ if (element is VariableElementImpl) { element.declaredType = declaredType; } - return null; } /// Given the [returnType] of a function, compute the return type of the @@ -9264,20 +9203,20 @@ nameScope: nameScope); @override - Object visitBlockFunctionBody(BlockFunctionBody node) { + void visitBlockFunctionBody(BlockFunctionBody node) { assert(_localVariableInfo != null); - return super.visitBlockFunctionBody(node); + super.visitBlockFunctionBody(node); } @override - Object visitConstructorDeclaration(ConstructorDeclaration node) { + void visitConstructorDeclaration(ConstructorDeclaration node) { ExecutableElement outerFunction = _enclosingFunction; LocalVariableInfo outerLocalVariableInfo = _localVariableInfo; try { _localVariableInfo ??= new LocalVariableInfo(); (node.body as FunctionBodyImpl).localVariableInfo = _localVariableInfo; _enclosingFunction = node.declaredElement; - return super.visitConstructorDeclaration(node); + super.visitConstructorDeclaration(node); } finally { _localVariableInfo = outerLocalVariableInfo; _enclosingFunction = outerFunction; @@ -9285,16 +9224,16 @@ } @override - Object visitExportDirective(ExportDirective node) => null; + void visitExportDirective(ExportDirective node) {} @override - Object visitExpressionFunctionBody(ExpressionFunctionBody node) { + void visitExpressionFunctionBody(ExpressionFunctionBody node) { assert(_localVariableInfo != null); - return super.visitExpressionFunctionBody(node); + super.visitExpressionFunctionBody(node); } @override - Object visitFunctionDeclaration(FunctionDeclaration node) { + void visitFunctionDeclaration(FunctionDeclaration node) { ExecutableElement outerFunction = _enclosingFunction; LocalVariableInfo outerLocalVariableInfo = _localVariableInfo; try { @@ -9302,7 +9241,7 @@ (node.functionExpression.body as FunctionBodyImpl).localVariableInfo = _localVariableInfo; _enclosingFunction = node.declaredElement; - return super.visitFunctionDeclaration(node); + super.visitFunctionDeclaration(node); } finally { _localVariableInfo = outerLocalVariableInfo; _enclosingFunction = outerFunction; @@ -9310,7 +9249,7 @@ } @override - Object visitFunctionExpression(FunctionExpression node) { + void visitFunctionExpression(FunctionExpression node) { if (node.parent is! FunctionDeclaration) { ExecutableElement outerFunction = _enclosingFunction; LocalVariableInfo outerLocalVariableInfo = _localVariableInfo; @@ -9318,28 +9257,28 @@ _localVariableInfo ??= new LocalVariableInfo(); (node.body as FunctionBodyImpl).localVariableInfo = _localVariableInfo; _enclosingFunction = node.declaredElement; - return super.visitFunctionExpression(node); + super.visitFunctionExpression(node); } finally { _localVariableInfo = outerLocalVariableInfo; _enclosingFunction = outerFunction; } } else { - return super.visitFunctionExpression(node); + super.visitFunctionExpression(node); } } @override - Object visitImportDirective(ImportDirective node) => null; + void visitImportDirective(ImportDirective node) {} @override - Object visitMethodDeclaration(MethodDeclaration node) { + void visitMethodDeclaration(MethodDeclaration node) { ExecutableElement outerFunction = _enclosingFunction; LocalVariableInfo outerLocalVariableInfo = _localVariableInfo; try { _localVariableInfo ??= new LocalVariableInfo(); (node.body as FunctionBodyImpl).localVariableInfo = _localVariableInfo; _enclosingFunction = node.declaredElement; - return super.visitMethodDeclaration(node); + super.visitMethodDeclaration(node); } finally { _localVariableInfo = outerLocalVariableInfo; _enclosingFunction = outerFunction; @@ -9347,43 +9286,43 @@ } @override - Object visitSimpleIdentifier(SimpleIdentifier node) { + void visitSimpleIdentifier(SimpleIdentifier node) { // Ignore if already resolved - declaration or type. if (node.inDeclarationContext()) { - return null; + return; } // Ignore if it cannot be a reference to a local variable. AstNode parent = node.parent; if (parent is FieldFormalParameter) { - return null; + return; } else if (parent is ConstructorDeclaration && parent.returnType == node) { - return null; + return; } else if (parent is ConstructorFieldInitializer && parent.fieldName == node) { - return null; + return; } // Ignore if qualified. if (parent is PrefixedIdentifier && identical(parent.identifier, node)) { - return null; + return; } if (parent is PropertyAccess && identical(parent.propertyName, node)) { - return null; + return; } if (parent is MethodInvocation && identical(parent.methodName, node) && parent.realTarget != null) { - return null; + return; } if (parent is ConstructorName) { - return null; + return; } if (parent is Label) { - return null; + return; } // Prepare VariableElement. Element element = nameScope.lookup(node, definingLibrary); if (element is! VariableElement) { - return null; + return; } // Must be local or parameter. ElementKind kind = element.kind; @@ -9396,13 +9335,10 @@ } } } - return null; } @override - Object visitTypeName(TypeName node) { - return null; - } + void visitTypeName(TypeName node) {} } class _InvalidAccessVerifier { @@ -9614,7 +9550,7 @@ } class _ResolverVisitor_isVariableAccessedInClosure - extends RecursiveAstVisitor<Object> { + extends RecursiveAstVisitor<void> { final Element variable; bool result = false; @@ -9624,30 +9560,29 @@ _ResolverVisitor_isVariableAccessedInClosure(this.variable); @override - Object visitFunctionExpression(FunctionExpression node) { + void visitFunctionExpression(FunctionExpression node) { bool inClosure = this._inClosure; try { this._inClosure = true; - return super.visitFunctionExpression(node); + super.visitFunctionExpression(node); } finally { this._inClosure = inClosure; } } @override - Object visitSimpleIdentifier(SimpleIdentifier node) { + void visitSimpleIdentifier(SimpleIdentifier node) { if (result) { - return null; + return; } if (_inClosure && identical(node.staticElement, variable)) { result = true; } - return null; } } class _ResolverVisitor_isVariablePotentiallyMutatedIn - extends RecursiveAstVisitor<Object> { + extends RecursiveAstVisitor<void> { final Element variable; bool result = false; @@ -9655,15 +9590,14 @@ _ResolverVisitor_isVariablePotentiallyMutatedIn(this.variable); @override - Object visitSimpleIdentifier(SimpleIdentifier node) { + void visitSimpleIdentifier(SimpleIdentifier node) { if (result) { - return null; + return; } if (identical(node.staticElement, variable)) { if (node.inSetterContext()) { result = true; } } - return null; } }
diff --git a/pkg/analyzer/lib/src/generated/sdk.dart b/pkg/analyzer/lib/src/generated/sdk.dart index d024db1..c7ae2db 100644 --- a/pkg/analyzer/lib/src/generated/sdk.dart +++ b/pkg/analyzer/lib/src/generated/sdk.dart
@@ -265,7 +265,7 @@ } } -class SdkLibrariesReader_LibraryBuilder extends RecursiveAstVisitor<Object> { +class SdkLibrariesReader_LibraryBuilder extends RecursiveAstVisitor<void> { /** * The prefix added to the name of a library to form the URI used in code to * reference the library. @@ -351,7 +351,7 @@ } @override - Object visitMapLiteralEntry(MapLiteralEntry node) { + void visitMapLiteralEntry(MapLiteralEntry node) { String libraryName = null; Expression key = node.key; if (key is SimpleStringLiteral) { @@ -392,7 +392,6 @@ } _librariesMap.setLibrary(libraryName, library); } - return null; } }
diff --git a/pkg/analyzer/lib/src/generated/static_type_analyzer.dart b/pkg/analyzer/lib/src/generated/static_type_analyzer.dart index dfc94e4..378592a 100644 --- a/pkg/analyzer/lib/src/generated/static_type_analyzer.dart +++ b/pkg/analyzer/lib/src/generated/static_type_analyzer.dart
@@ -1,4 +1,4 @@ -// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file +// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. @@ -11,6 +11,8 @@ import 'package:analyzer/dart/element/element.dart'; import 'package:analyzer/dart/element/type.dart'; import 'package:analyzer/src/dart/ast/ast.dart'; +import 'package:analyzer/src/dart/ast/ast_factory.dart'; +import 'package:analyzer/src/dart/ast/utilities.dart'; import 'package:analyzer/src/dart/element/element.dart'; import 'package:analyzer/src/dart/element/member.dart' show ConstructorMember; import 'package:analyzer/src/dart/element/type.dart'; @@ -28,7 +30,7 @@ * * Every node representing an expression should be resolved to the Type of the expression. * </ol> */ -class StaticTypeAnalyzer extends SimpleAstVisitor<Object> { +class StaticTypeAnalyzer extends SimpleAstVisitor<void> { /** * The resolver driving the resolution and type analysis. */ @@ -171,6 +173,22 @@ ParameterizedType inferMapType(MapLiteral node, {bool downwards: false}) { DartType contextType = InferenceContext.getContext(node); + if (contextType != null && + node.typeArguments == null && + node.entries.isEmpty && + _typeSystem.isAssignableTo(_typeProvider.setNullType, contextType) && + !_typeSystem.isAssignableTo( + _typeProvider.mapNullNullType, contextType)) { + // The node is really an empty set literal with no type arguments. Rewrite + // the AST and infer the type of the set as appropriate. + SetLiteral setLiteral = new AstFactoryImpl().setLiteral( + node.constKeyword, null, node.leftBracket, null, node.rightBracket); + InferenceContext.setType(setLiteral, contextType); + NodeReplacer.replace(node, setLiteral); + DartType type = inferSetType(setLiteral, downwards: downwards); + setLiteral.staticType = type; + return type; + } List<DartType> elementTypes; List<ParameterElement> parameters; if (downwards) { @@ -206,14 +224,46 @@ return inferred; } + DartType inferSetType(SetLiteral node, {bool downwards: false}) { + DartType contextType = InferenceContext.getContext(node); + + var ts = _typeSystem as StrongTypeSystemImpl; + List<DartType> elementTypes; + List<ParameterElement> parameters; + + if (downwards) { + if (contextType == null) { + return null; + } + + elementTypes = []; + parameters = []; + } else { + // Also use upwards information to infer the type. + elementTypes = node.elements + .map((e) => e.staticType) + .where((t) => t != null) + .toList(); + var setTypeParam = _typeProvider.setType.typeParameters[0].type; + var syntheticParamElement = new ParameterElementImpl.synthetic( + 'element', setTypeParam, ParameterKind.POSITIONAL); + parameters = new List.filled(elementTypes.length, syntheticParamElement); + } + DartType inferred = ts.inferGenericFunctionOrType<InterfaceType>( + _typeProvider.setType, parameters, elementTypes, contextType, + downwards: downwards, + errorReporter: _resolver.errorReporter, + errorNode: node); + return inferred; + } + /** * The Dart Language Specification, 12.5: <blockquote>The static type of a string literal is * `String`.</blockquote> */ @override - Object visitAdjacentStrings(AdjacentStrings node) { + void visitAdjacentStrings(AdjacentStrings node) { _recordStaticType(node, _typeProvider.stringType); - return null; } /** @@ -225,9 +275,8 @@ * The static type of a cast expression <i>e as T</i> is <i>T</i>.</blockquote> */ @override - Object visitAsExpression(AsExpression node) { + void visitAsExpression(AsExpression node) { _recordStaticType(node, _getType(node.type)); - return null; } /** @@ -270,7 +319,7 @@ * <i>e<sub>3</sub></i>.</blockquote> */ @override - Object visitAssignmentExpression(AssignmentExpression node) { + void visitAssignmentExpression(AssignmentExpression node) { TokenType operator = node.operator.type; if (operator == TokenType.EQ) { Expression rightHandSide = node.rightHandSide; @@ -281,7 +330,7 @@ // bound of the static types of the LHS and RHS. _analyzeLeastUpperBound(node, node.leftHandSide, node.rightHandSide, read: true); - return null; + return; } else if (operator == TokenType.AMPERSAND_AMPERSAND_EQ || operator == TokenType.BAR_BAR_EQ) { _recordStaticType(node, _typeProvider.boolType); @@ -295,7 +344,6 @@ staticType); _recordStaticType(node, staticType); } - return null; } /** @@ -305,7 +353,7 @@ * the static type of e. */ @override - Object visitAwaitExpression(AwaitExpression node) { + void visitAwaitExpression(AwaitExpression node) { // Await the Future. This results in whatever type is (ultimately) returned. DartType awaitType(DartType awaitedType) { if (awaitedType == null) { @@ -318,7 +366,6 @@ } _recordStaticType(node, awaitType(_getStaticType(node.expression))); - return null; } /** @@ -359,14 +406,14 @@ * <i>super.op(e<sub>2</sub>)</i>.</blockquote> */ @override - Object visitBinaryExpression(BinaryExpression node) { + void visitBinaryExpression(BinaryExpression node) { if (node.operator.type == TokenType.QUESTION_QUESTION) { // Evaluation of an if-null expression e of the form e1 ?? e2 is // equivalent to the evaluation of the expression // ((x) => x == null ? e2 : x)(e1). The static type of e is the least // upper bound of the static type of e1 and the static type of e2. _analyzeLeastUpperBound(node, node.leftOperand, node.rightOperand); - return null; + return; } DartType staticType = node.staticInvokeType?.returnType ?? _dynamicType; staticType = _typeSystem.refineBinaryExpressionType( @@ -375,7 +422,6 @@ node.rightOperand.staticType, staticType); _recordStaticType(node, staticType); - return null; } /** @@ -383,9 +429,8 @@ * bool.</blockquote> */ @override - Object visitBooleanLiteral(BooleanLiteral node) { + void visitBooleanLiteral(BooleanLiteral node) { _recordStaticType(node, _typeProvider.boolType); - return null; } /** @@ -394,9 +439,8 @@ * t;}(e)</i>.</blockquote> */ @override - Object visitCascadeExpression(CascadeExpression node) { + void visitCascadeExpression(CascadeExpression node) { _recordStaticType(node, _getStaticType(node.target)); - return null; } /** @@ -409,16 +453,14 @@ * and the static type of <i>e<sub>3</sub></i>.</blockquote> */ @override - Object visitConditionalExpression(ConditionalExpression node) { + void visitConditionalExpression(ConditionalExpression node) { _analyzeLeastUpperBound(node, node.thenExpression, node.elseExpression); - return null; } @override - Object visitDeclaredIdentifier(DeclaredIdentifier node) { + void visitDeclaredIdentifier(DeclaredIdentifier node) { super.visitDeclaredIdentifier(node); _inferForEachLoopVariableType(node); - return null; } /** @@ -426,13 +468,12 @@ * double.</blockquote> */ @override - Object visitDoubleLiteral(DoubleLiteral node) { + void visitDoubleLiteral(DoubleLiteral node) { _recordStaticType(node, _typeProvider.doubleType); - return null; } @override - Object visitFunctionDeclaration(FunctionDeclaration node) { + void visitFunctionDeclaration(FunctionDeclaration node) { FunctionExpression function = node.functionExpression; ExecutableElementImpl functionElement = node.declaredElement as ExecutableElementImpl; @@ -441,13 +482,12 @@ // we only need to handle local functions. if (node.returnType == null) { _inferLocalFunctionReturnType(node.functionExpression); - return null; + return; } functionElement.returnType = _computeStaticReturnTypeOfFunctionDeclaration(node); } _recordStaticType(function, functionElement.type); - return null; } /** @@ -481,14 +521,13 @@ * specified as dynamic.</blockquote> */ @override - Object visitFunctionExpression(FunctionExpression node) { + void visitFunctionExpression(FunctionExpression node) { if (node.parent is FunctionDeclaration) { // The function type will be resolved and set when we visit the parent // node. - return null; + return; } _inferLocalFunctionReturnType(node); - return null; } /** @@ -504,11 +543,10 @@ * static type of <i>i</i> is the declared return type of <i>F</i>.</blockquote> */ @override - Object visitFunctionExpressionInvocation(FunctionExpressionInvocation node) { + void visitFunctionExpressionInvocation(FunctionExpressionInvocation node) { _inferGenericInvocationExpression(node); DartType staticType = _computeInvokeReturnType(node.staticInvokeType); _recordStaticType(node, staticType); - return null; } /** @@ -517,7 +555,7 @@ * <i>[]</i> on <i>e<sub>1</sub></i> with argument <i>e<sub>2</sub></i>.</blockquote> */ @override - Object visitIndexExpression(IndexExpression node) { + void visitIndexExpression(IndexExpression node) { if (node.inSetterContext()) { ExecutableElement staticMethodElement = node.staticElement; DartType staticType = _computeArgumentType(staticMethodElement); @@ -527,7 +565,6 @@ DartType staticType = _computeStaticReturnType(staticMethodElement); _recordStaticType(node, staticType); } - return null; } /** @@ -540,11 +577,9 @@ * form <i>const T(a<sub>1</sub>, …, a<sub>n</sub>)</i> is <i>T</i>. </blockquote> */ @override - Object visitInstanceCreationExpression(InstanceCreationExpression node) { + void visitInstanceCreationExpression(InstanceCreationExpression node) { _inferInstanceCreationExpression(node); - _recordStaticType(node, node.constructorName.type.type); - return null; } /** @@ -565,7 +600,7 @@ * </blockquote> */ @override - Object visitIntegerLiteral(IntegerLiteral node) { + void visitIntegerLiteral(IntegerLiteral node) { // Check the parent context for negated integer literals. var context = InferenceContext.getContext( (node as IntegerLiteralImpl).immediatelyNegated ? node.parent : node); @@ -576,7 +611,6 @@ } else { _recordStaticType(node, _typeProvider.doubleType); } - return null; } /** @@ -586,9 +620,8 @@ * The static type of an is-expression is `bool`.</blockquote> */ @override - Object visitIsExpression(IsExpression node) { + void visitIsExpression(IsExpression node) { _recordStaticType(node, _typeProvider.boolType); - return null; } /** @@ -600,7 +633,7 @@ * .</blockquote> */ @override - Object visitListLiteral(ListLiteral node) { + void visitListLiteral(ListLiteral node) { TypeArgumentList typeArguments = node.typeArguments; // If we have explicit arguments, use them @@ -615,7 +648,7 @@ } _recordStaticType( node, _typeProvider.listType.instantiate(<DartType>[staticType])); - return null; + return; } DartType listDynamicType = @@ -631,12 +664,11 @@ // everything was successful? _resolver.inferenceContext.recordInference(node, inferred); _recordStaticType(node, inferred); - return null; + return; } // If we have no type arguments and couldn't infer any, use dynamic. _recordStaticType(node, listDynamicType); - return null; } /** @@ -652,12 +684,9 @@ * <i>String</i>.</blockquote> */ @override - Object visitMapLiteral(MapLiteral node) { + void visitMapLiteral(MapLiteral node) { TypeArgumentList typeArguments = node.typeArguments; - DartType mapDynamicType = _typeProvider.mapType - .instantiate(<DartType>[_dynamicType, _dynamicType]); - // If we have type arguments, use them if (typeArguments != null) { DartType staticKeyType = _dynamicType; @@ -677,9 +706,12 @@ node, _typeProvider.mapType .instantiate(<DartType>[staticKeyType, staticValueType])); - return null; + return; } + DartType mapDynamicType = _typeProvider.mapType + .instantiate(<DartType>[_dynamicType, _dynamicType]); + // If we have no explicit type arguments, try to infer type arguments. ParameterizedType inferred = inferMapType(node); @@ -690,12 +722,11 @@ // everything was successful? _resolver.inferenceContext.recordInference(node, inferred); _recordStaticType(node, inferred); - return null; + return; } // If no type arguments and no inference, use dynamic _recordStaticType(node, mapDynamicType); - return null; } /** @@ -735,7 +766,7 @@ * <i>F</i>.</blockquote> */ @override - Object visitMethodInvocation(MethodInvocation node) { + void visitMethodInvocation(MethodInvocation node) { _inferGenericInvocationExpression(node); // Record static return type of the static element. bool inferredStaticType = _inferMethodInvocationObject(node) || @@ -746,14 +777,12 @@ _computeInvokeReturnType(node.staticInvokeType); _recordStaticType(node, staticStaticType); } - return null; } @override - Object visitNamedExpression(NamedExpression node) { + void visitNamedExpression(NamedExpression node) { Expression expression = node.expression; _recordStaticType(node, _getStaticType(expression)); - return null; } /** @@ -761,16 +790,14 @@ * </blockquote> */ @override - Object visitNullLiteral(NullLiteral node) { + void visitNullLiteral(NullLiteral node) { _recordStaticType(node, _typeProvider.nullType); - return null; } @override - Object visitParenthesizedExpression(ParenthesizedExpression node) { + void visitParenthesizedExpression(ParenthesizedExpression node) { Expression expression = node.expression; _recordStaticType(node, _getStaticType(expression)); - return null; } /** @@ -800,7 +827,7 @@ * = r - 1; return r}(e1, e2)</i></blockquote> */ @override - Object visitPostfixExpression(PostfixExpression node) { + void visitPostfixExpression(PostfixExpression node) { Expression operand = node.operand; DartType staticType = _getStaticType(operand, read: true); TokenType operator = node.operator.type; @@ -811,14 +838,13 @@ } } _recordStaticType(node, staticType); - return null; } /** * See [visitSimpleIdentifier]. */ @override - Object visitPrefixedIdentifier(PrefixedIdentifier node) { + void visitPrefixedIdentifier(PrefixedIdentifier node) { SimpleIdentifier prefixedIdentifier = node.identifier; Element staticElement = prefixedIdentifier.staticElement; DartType staticType = _dynamicType; @@ -850,7 +876,6 @@ _recordStaticType(prefixedIdentifier, staticType); _recordStaticType(node, staticType); } - return null; } /** @@ -859,7 +884,7 @@ * form <i>op super</i> is equivalent to the method invocation <i>super.op()<i>.</blockquote> */ @override - Object visitPrefixExpression(PrefixExpression node) { + void visitPrefixExpression(PrefixExpression node) { TokenType operator = node.operator.type; if (operator == TokenType.BANG) { _recordStaticType(node, _typeProvider.boolType); @@ -876,7 +901,6 @@ } _recordStaticType(node, staticType); } - return null; } /** @@ -921,7 +945,7 @@ * The static type of <i>i</i> is the declared return type of <i>m</i>.</blockquote> */ @override - Object visitPropertyAccess(PropertyAccess node) { + void visitPropertyAccess(PropertyAccess node) { SimpleIdentifier propertyName = node.propertyName; Element staticElement = propertyName.staticElement; DartType staticType = _dynamicType; @@ -937,7 +961,6 @@ _recordStaticType(propertyName, staticType); _recordStaticType(node, staticType); } - return null; } /** @@ -945,9 +968,47 @@ * bottom.</blockquote> */ @override - Object visitRethrowExpression(RethrowExpression node) { + void visitRethrowExpression(RethrowExpression node) { _recordStaticType(node, _typeProvider.bottomType); - return null; + } + + @override + void visitSetLiteral(SetLiteral node) { + TypeArgumentList typeArguments = node.typeArguments; + + // If we have type arguments, use them + if (typeArguments != null) { + DartType elementType = _dynamicType; + NodeList<TypeAnnotation> arguments = typeArguments.arguments; + if (arguments != null && arguments.length == 1) { + DartType type = _getType(arguments[0]); + if (type != null) { + elementType = type; + } + } + _recordStaticType( + node, _typeProvider.setType.instantiate(<DartType>[elementType])); + return; + } + + DartType setDynamicType = + _typeProvider.setType.instantiate(<DartType>[_dynamicType]); + + // If we have no explicit type arguments, try to infer type arguments. + ParameterizedType inferred = inferSetType(node); + + if (inferred != setDynamicType) { + // TODO(jmesserly): this results in an "inferred" message even when we + // in fact had an error above, because it will still attempt to return + // a type. Perhaps we should record inference from TypeSystem if + // everything was successful? + _resolver.inferenceContext.recordInference(node, inferred); + _recordStaticType(node, inferred); + return; + } + + // If no type arguments and no inference, use dynamic + _recordStaticType(node, setDynamicType); } /** @@ -989,7 +1050,7 @@ * </blockquote> */ @override - Object visitSimpleIdentifier(SimpleIdentifier node) { + void visitSimpleIdentifier(SimpleIdentifier node) { Element element = node.staticElement; DartType staticType = _dynamicType; if (element is ClassElement) { @@ -1019,7 +1080,7 @@ var parent = node.parent; if (parent is PrefixedIdentifier && parent.prefix == node || parent is MethodInvocation && parent.target == node) { - return null; + return; } staticType = _typeProvider.dynamicType; } else if (element is DynamicElementImpl) { @@ -1029,7 +1090,6 @@ } staticType = _inferGenericInstantiationFromContext(node, staticType); _recordStaticType(node, staticType); - return null; } /** @@ -1037,9 +1097,8 @@ * `String`.</blockquote> */ @override - Object visitSimpleStringLiteral(SimpleStringLiteral node) { + void visitSimpleStringLiteral(SimpleStringLiteral node) { _recordStaticType(node, _typeProvider.stringType); - return null; } /** @@ -1047,13 +1106,12 @@ * `String`.</blockquote> */ @override - Object visitStringInterpolation(StringInterpolation node) { + void visitStringInterpolation(StringInterpolation node) { _recordStaticType(node, _typeProvider.stringType); - return null; } @override - Object visitSuperExpression(SuperExpression node) { + void visitSuperExpression(SuperExpression node) { if (thisType == null) { // TODO(brianwilkerson) Report this error if it hasn't already been // reported. @@ -1061,13 +1119,11 @@ } else { _recordStaticType(node, thisType); } - return null; } @override - Object visitSymbolLiteral(SymbolLiteral node) { + void visitSymbolLiteral(SymbolLiteral node) { _recordStaticType(node, _typeProvider.symbolType); - return null; } /** @@ -1075,7 +1131,7 @@ * interface of the immediately enclosing class.</blockquote> */ @override - Object visitThisExpression(ThisExpression node) { + void visitThisExpression(ThisExpression node) { if (thisType == null) { // TODO(brianwilkerson) Report this error if it hasn't already been // reported. @@ -1083,7 +1139,6 @@ } else { _recordStaticType(node, thisType); } - return null; } /** @@ -1091,13 +1146,12 @@ * bottom.</blockquote> */ @override - Object visitThrowExpression(ThrowExpression node) { + void visitThrowExpression(ThrowExpression node) { _recordStaticType(node, _typeProvider.bottomType); - return null; } @override - Object visitVariableDeclaration(VariableDeclaration node) { + void visitVariableDeclaration(VariableDeclaration node) { Expression initializer = node.initializer; _inferLocalVariableType(node, initializer); if (initializer != null) { @@ -1108,7 +1162,6 @@ _resolver.overrideVariable(element, rightType, true); } } - return null; } /**
diff --git a/pkg/analyzer/lib/src/generated/testing/ast_test_factory.dart b/pkg/analyzer/lib/src/generated/testing/ast_test_factory.dart index 8dcf359..7da4bb2 100644 --- a/pkg/analyzer/lib/src/generated/testing/ast_test_factory.dart +++ b/pkg/analyzer/lib/src/generated/testing/ast_test_factory.dart
@@ -1066,6 +1066,15 @@ static ScriptTag scriptTag(String scriptTag) => astFactory.scriptTag(TokenFactory.tokenFromString(scriptTag)); + static SetLiteral setLiteral(Keyword keyword, TypeArgumentList typeArguments, + List<Expression> elements) => + astFactory.setLiteral( + keyword == null ? null : TokenFactory.tokenFromKeyword(keyword), + typeArguments, + TokenFactory.tokenFromType(TokenType.OPEN_CURLY_BRACKET), + elements, + TokenFactory.tokenFromType(TokenType.CLOSE_CURLY_BRACKET)); + static ShowCombinator showCombinator(List<SimpleIdentifier> identifiers) => astFactory.showCombinator( TokenFactory.tokenFromString("show"), identifiers);
diff --git a/pkg/analyzer/lib/src/generated/testing/element_factory.dart b/pkg/analyzer/lib/src/generated/testing/element_factory.dart index 27a7460..8dfa63d 100644 --- a/pkg/analyzer/lib/src/generated/testing/element_factory.dart +++ b/pkg/analyzer/lib/src/generated/testing/element_factory.dart
@@ -416,8 +416,8 @@ AnalysisContext context, String libraryName) { String fileName = "/$libraryName.dart"; CompilationUnitElementImpl unit = compilationUnit(fileName); - LibraryElementImpl library = - new LibraryElementImpl(context, libraryName, 0, libraryName.length); + LibraryElementImpl library = new LibraryElementImpl( + context, null, libraryName, 0, libraryName.length); library.definingCompilationUnit = unit; return library; }
diff --git a/pkg/analyzer/lib/src/generated/testing/test_type_provider.dart b/pkg/analyzer/lib/src/generated/testing/test_type_provider.dart index 17afba9..1f4cc10 100644 --- a/pkg/analyzer/lib/src/generated/testing/test_type_provider.dart +++ b/pkg/analyzer/lib/src/generated/testing/test_type_provider.dart
@@ -1,4 +1,4 @@ -// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file +// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. @@ -6,6 +6,7 @@ import 'package:analyzer/dart/ast/token.dart'; import 'package:analyzer/dart/element/element.dart'; import 'package:analyzer/dart/element/type.dart'; +import 'package:analyzer/src/dart/analysis/driver.dart'; import 'package:analyzer/src/dart/element/element.dart'; import 'package:analyzer/src/dart/element/type.dart'; import 'package:analyzer/src/generated/constant.dart'; @@ -108,6 +109,11 @@ InterfaceType _mapType; /** + * The type representing the built-in type 'Map'. + */ + InterfaceType _mapNullNullType; + + /** * An shared object representing the value 'null'. */ DartObjectImpl _nullObject; @@ -128,6 +134,16 @@ InterfaceType _objectType; /** + * The type representing the built-in type 'Set'. + */ + InterfaceType _setType; + + /** + * The type representing the built-in type 'Set'. + */ + InterfaceType _setNullType; + + /** * The type representing the built-in type 'StackTrace'. */ InterfaceType _stackTraceType; @@ -168,7 +184,13 @@ */ AnalysisContext _context; - TestTypeProvider([this._context]); + /** + * The analysis driver, if any. Used to create an appropriate 'dart:async' + * library to back `Future<T>`. + */ + AnalysisDriver _driver; + + TestTypeProvider([this._context, this._driver]); @override InterfaceType get boolType { @@ -377,6 +399,14 @@ } @override + InterfaceType get mapNullNullType { + if (_mapNullNullType == null) { + _mapNullNullType = mapType.instantiate(<DartType>[nullType, nullType]); + } + return _mapNullNullType; + } + + @override InterfaceType get mapType { if (_mapType == null) { ClassElementImpl mapElement = @@ -422,7 +452,7 @@ // Create a library element for "dart:core" // This enables the "isDartCoreNull" getter. var library = new LibraryElementImpl.forNode( - _context, AstTestFactory.libraryIdentifier2(["dart.core"])); + _context, null, AstTestFactory.libraryIdentifier2(["dart.core"])); var unit = new CompilationUnitElementImpl(); library.definingCompilationUnit = unit; unit.librarySource = unit.source = new StringSource('', null); @@ -464,6 +494,23 @@ } @override + InterfaceType get setNullType { + if (_setNullType == null) { + _setNullType = setType.instantiate(<DartType>[nullType]); + } + return _setNullType; + } + + @override + InterfaceType get setType { + if (_setType == null) { + ClassElementImpl setElement = ElementFactory.classElement2("Set", ["E"]); + _setType = setElement.type; + } + return _setType; + } + + @override InterfaceType get stackTraceType { if (_stackTraceType == null) { ClassElementImpl stackTraceElement = @@ -558,11 +605,16 @@ } void _initDartAsync() { - Source asyncSource = _context.sourceFactory.forUri(DartSdk.DART_ASYNC); - _context.setContents(asyncSource, ""); + Source asyncSource; + if (_driver == null) { + asyncSource = _context.sourceFactory.forUri(DartSdk.DART_ASYNC); + _context.setContents(asyncSource, ""); + } else { + asyncSource = _driver.sourceFactory.forUri(DartSdk.DART_ASYNC); + } CompilationUnitElementImpl asyncUnit = new CompilationUnitElementImpl(); LibraryElementImpl asyncLibrary = new LibraryElementImpl.forNode( - _context, AstTestFactory.libraryIdentifier2(["dart.async"])); + _context, null, AstTestFactory.libraryIdentifier2(["dart.async"])); asyncLibrary.definingCompilationUnit = asyncUnit; asyncUnit.librarySource = asyncUnit.source = asyncSource;
diff --git a/pkg/analyzer/lib/src/generated/type_system.dart b/pkg/analyzer/lib/src/generated/type_system.dart index beb1160..540a948 100644 --- a/pkg/analyzer/lib/src/generated/type_system.dart +++ b/pkg/analyzer/lib/src/generated/type_system.dart
@@ -466,7 +466,8 @@ List<DartType> tArgs2 = i2.typeArguments; assert(tArgs1.length == tArgs2.length); for (int i = 0; i < tArgs1.length; i++) { - if (!_matchSubtypeOf(tArgs1[i], tArgs2[i], visited, origin, + if (!_matchSubtypeOf( + tArgs1[i], tArgs2[i], new HashSet<Element>(), origin, covariant: covariant)) { return false; } @@ -478,22 +479,12 @@ } // Guard against loops in the class hierarchy - // - // TODO(jmesserly): this function isn't guarding against anything (it's not - // passsing down `visitedSet`, so adding the element has no effect). - // - // If that's fixed, it breaks inference tests for types like - // `Iterable<Iterable<?>>` matched aganinst `List<List<int>>`. - // - // The fix is for type arguments (above) to not pass down `visited`, similar - // to how _isInterfaceSubtypeOf does not pass down `visited` for type - // arguments. bool guardedInterfaceSubtype(InterfaceType t1) { - var visitedSet = visited ?? new HashSet<Element>(); - if (visitedSet.add(t1.element)) { + visited ??= new HashSet<Element>(); + if (visited.add(t1.element)) { bool matched = _matchInterfaceSubtypeOf(t1, i2, visited, origin, covariant: covariant); - visitedSet.remove(t1.element); + visited.remove(t1.element); return matched; } else { // In the case of a recursive type parameter, consider the subtype @@ -729,13 +720,6 @@ static bool _comparingTypeParameterBounds = false; /** - * True if declaration casts should be allowed, otherwise false. - * - * This affects the behavior of [isAssignableTo]. - */ - final bool declarationCasts; - - /** * True if implicit casts should be allowed, otherwise false. * * This affects the behavior of [isAssignableTo]. @@ -744,8 +728,7 @@ final TypeProvider typeProvider; - StrongTypeSystemImpl(this.typeProvider, - {this.declarationCasts: true, this.implicitCasts: true}); + StrongTypeSystemImpl(this.typeProvider, {this.implicitCasts: true}); @override bool get isStrong => true; @@ -1048,8 +1031,7 @@ } @override - bool isAssignableTo(DartType fromType, DartType toType, - {bool isDeclarationCast = false}) { + bool isAssignableTo(DartType fromType, DartType toType) { // An actual subtype if (isSubtypeOf(fromType, toType)) { return true; @@ -1063,11 +1045,7 @@ } } - if (isDeclarationCast) { - if (!declarationCasts) { - return false; - } - } else if (!implicitCasts) { + if (!implicitCasts) { return false; } @@ -1819,8 +1797,7 @@ * Return `true` if the [leftType] is assignable to the [rightType] (that is, * if leftType <==> rightType). */ - bool isAssignableTo(DartType leftType, DartType rightType, - {bool isDeclarationCast = false}); + bool isAssignableTo(DartType leftType, DartType rightType); /** * Return `true` if the [leftType] is more specific than the [rightType] @@ -2096,7 +2073,6 @@ static TypeSystem create(AnalysisContext context) { var options = context.analysisOptions as AnalysisOptionsImpl; return new StrongTypeSystemImpl(context.typeProvider, - declarationCasts: options.declarationCasts, implicitCasts: options.implicitCasts); } }
diff --git a/pkg/analyzer/lib/src/hint/sdk_constraint_extractor.dart b/pkg/analyzer/lib/src/hint/sdk_constraint_extractor.dart index 9ff1b29..0cd3180 100644 --- a/pkg/analyzer/lib/src/hint/sdk_constraint_extractor.dart +++ b/pkg/analyzer/lib/src/hint/sdk_constraint_extractor.dart
@@ -12,44 +12,84 @@ /// The file from which the constraint is to be extracted. final File pubspecFile; - /// The version range that was + /// A flag indicating whether the [_constraintText], [_constraintOffset] and + /// [_constraint] have been initialized. + bool _initialized = false; + + /// The text of the constraint, or `null` if the range has not yet been + /// computed or if there was an error when attempting to compute the range. + String _constraintText; + + /// The offset of the constraint text, or `-1` if the offset is not known. + int _constraintOffset = -1; + + /// The cached range of supported versions, or `null` if the range has not yet + /// been computed or if there was an error when attempting to compute the + /// range. VersionConstraint _constraint; /// Initialize a newly created extractor to extract the SDK version constraint /// from the given `pubspec.yaml` file. SdkConstraintExtractor(this.pubspecFile); - /// Return the range of supported versions. + /// Return the range of supported versions, or `null` if the range could not + /// be computed. VersionConstraint constraint() { if (_constraint == null) { - try { - String constraintText = _getConstraintText(); - if (constraintText != null) { - _constraint = new VersionConstraint.parse(constraintText); + String text = constraintText(); + if (text != null) { + try { + _constraint = new VersionConstraint.parse(text); + } catch (e) { + // Ignore this, leaving [_constraint] unset. } - } catch (e) { - // Return `null` by falling through without setting `_versionRange`. } } return _constraint; } + /// Return the offset of the constraint text. + int constraintOffset() { + if (_constraintText == null) { + _initializeTextAndOffset(); + } + return _constraintOffset; + } + /// Return the constraint text following "sdk:". - String _getConstraintText() { - String fileContent = pubspecFile.readAsStringSync(); - YamlDocument document = loadYamlDocument(fileContent); - YamlNode contents = document.contents; - if (contents is YamlMap) { - var environment = contents['environment']; - if (environment is YamlMap) { - var sdk = environment['sdk']; - if (sdk is String) { - return sdk; - } else if (sdk is YamlScalar) { - return sdk.toString(); + String constraintText() { + if (_constraintText == null) { + _initializeTextAndOffset(); + } + return _constraintText; + } + + /// Initialize both [_constraintText] and [_constraintOffset], or neither if + /// there is an error or if the pubspec does not contain an sdk constraint. + void _initializeTextAndOffset() { + if (!_initialized) { + _initialized = true; + try { + String fileContent = pubspecFile.readAsStringSync(); + YamlDocument document = loadYamlDocument(fileContent); + YamlNode contents = document.contents; + if (contents is YamlMap) { + YamlNode environment = contents.nodes['environment']; + if (environment is YamlMap) { + YamlNode sdk = environment.nodes['sdk']; + if (sdk is YamlScalar) { + _constraintText = sdk.value; + _constraintOffset = sdk.span.start.offset; + if (sdk.style == ScalarStyle.SINGLE_QUOTED || + sdk.style == ScalarStyle.DOUBLE_QUOTED) { + _constraintOffset++; + } + } + } } + } catch (e) { + // Ignore this, leaving both fields unset. } } - return null; } }
diff --git a/pkg/analyzer/lib/src/hint/sdk_constraint_verifier.dart b/pkg/analyzer/lib/src/hint/sdk_constraint_verifier.dart index 3636897..429883f 100644 --- a/pkg/analyzer/lib/src/hint/sdk_constraint_verifier.dart +++ b/pkg/analyzer/lib/src/hint/sdk_constraint_verifier.dart
@@ -44,6 +44,16 @@ _checkFutureAndStream ??= !before_2_1_0.intersect(_versionRange).isEmpty; @override + void visitHideCombinator(HideCombinator node) { + // Don't flag references to either `Future` or `Stream` within a combinator. + } + + @override + void visitShowCombinator(ShowCombinator node) { + // Don't flag references to either `Future` or `Stream` within a combinator. + } + + @override void visitSimpleIdentifier(SimpleIdentifier node) { if (node.inDeclarationContext()) { return;
diff --git a/pkg/analyzer/lib/src/lint/analysis.dart b/pkg/analyzer/lib/src/lint/analysis.dart index bc4e089..be9fa8e 100644 --- a/pkg/analyzer/lib/src/lint/analysis.dart +++ b/pkg/analyzer/lib/src/lint/analysis.dart
@@ -1,4 +1,4 @@ -// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file +// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. @@ -6,12 +6,15 @@ import 'dart:collection'; import 'dart:io' as io; +import 'package:analyzer/dart/analysis/results.dart'; import 'package:analyzer/file_system/file_system.dart' show File, Folder, ResourceProvider, ResourceUriResolver; import 'package:analyzer/file_system/physical_file_system.dart'; import 'package:analyzer/src/context/builder.dart'; +import 'package:analyzer/src/dart/analysis/byte_store.dart'; import 'package:analyzer/src/dart/analysis/driver.dart'; import 'package:analyzer/src/dart/analysis/file_state.dart'; +import 'package:analyzer/src/dart/analysis/performance_logger.dart'; import 'package:analyzer/src/dart/sdk/sdk.dart'; import 'package:analyzer/src/file_system/file_system.dart'; import 'package:analyzer/src/generated/engine.dart' hide AnalysisResult; @@ -25,8 +28,6 @@ import 'package:analyzer/src/services/lint.dart'; import 'package:analyzer/src/source/package_map_resolver.dart'; import 'package:analyzer/src/util/sdk.dart'; -import 'package:analyzer/src/dart/analysis/byte_store.dart'; -import 'package:analyzer/src/dart/analysis/performance_logger.dart'; import 'package:package_config/packages.dart' show Packages; import 'package:package_config/packages_file.dart' as pkgfile show parse; import 'package:package_config/src/packages_impl.dart' show MapPackages; @@ -49,7 +50,6 @@ AnalysisOptions _buildAnalyzerOptions(LinterOptions options) { AnalysisOptionsImpl analysisOptions = new AnalysisOptionsImpl(); analysisOptions.hint = false; - analysisOptions.previewDart2 = options.previewDart2; analysisOptions.lint = options.enableLints; analysisOptions.generateSdkErrors = options.showSdkWarnings; analysisOptions.enableTiming = options.enableTiming; @@ -83,9 +83,6 @@ /// Whether to use Dart's Strong Mode analyzer. bool strongMode = true; - /// Whether to use Dart 2.0 features. - bool previewDart2 = false; - /// The mock SDK (to speed up testing) or `null` to use the actual SDK. DartSdk mockSdk; @@ -100,6 +97,13 @@ void set enableAssertInitializer(bool enable) { // Ignored because the option is now always enabled. } + + /// Whether to use Dart 2.0 features. + @deprecated + bool get previewDart2 => true; + + @deprecated + void set previewDart2(bool value) {} } class LintDriver {
diff --git a/pkg/analyzer/lib/src/lint/linter.dart b/pkg/analyzer/lib/src/lint/linter.dart index 1732ba7..348322f 100644 --- a/pkg/analyzer/lib/src/lint/linter.dart +++ b/pkg/analyzer/lib/src/lint/linter.dart
@@ -1,14 +1,20 @@ -// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file +// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. import 'dart:async'; import 'dart:io'; -import 'package:analyzer/analyzer.dart'; import 'package:analyzer/dart/analysis/declared_variables.dart'; +import 'package:analyzer/dart/ast/ast.dart'; import 'package:analyzer/dart/ast/token.dart'; +import 'package:analyzer/dart/element/element.dart'; +import 'package:analyzer/error/error.dart'; +import 'package:analyzer/error/listener.dart'; import 'package:analyzer/file_system/file_system.dart' as file_system; +import 'package:analyzer/src/dart/ast/ast.dart'; +import 'package:analyzer/src/dart/ast/token.dart'; +import 'package:analyzer/src/dart/error/lint_codes.dart'; import 'package:analyzer/src/generated/engine.dart' show AnalysisErrorInfo, AnalysisErrorInfoImpl, Logger; import 'package:analyzer/src/generated/java_engine.dart' show CaughtException; @@ -200,6 +206,16 @@ TypeProvider get typeProvider; TypeSystem get typeSystem; + + /// Return `true` if it would be valid for the given instance creation + /// [expression] to have a keyword of `const`. + /// + /// The [expression] is expected to be a node within one of the compilation + /// units in [allUnits]. + /// + /// Note that this method can cause constant evaluation to occur, which can be + /// computationally expensive. + bool canBeConst(InstanceCreationExpression expression); } /// Implementation of [LinterContext] @@ -221,6 +237,34 @@ LinterContextImpl(this.allUnits, this.currentUnit, this.declaredVariables, this.typeProvider, this.typeSystem); + + @override + bool canBeConst(InstanceCreationExpression expression) { + // + // Verify that the invoked constructor is a const constructor. + // + ConstructorElement element = expression.staticElement; + if (element == null || !element.isConst) { + return false; + } + // + // Verify that the evaluation of the constructor would not produce an + // exception. + // + Token oldKeyword = expression.keyword; + ConstantAnalysisErrorListener listener = + new ConstantAnalysisErrorListener(); + try { + expression.keyword = new KeywordToken(Keyword.CONST, expression.offset); + LibraryElement library = element.library; + ErrorReporter errorReporter = new ErrorReporter(listener, element.source); + expression.accept(new ConstantVerifier( + errorReporter, library, typeProvider, declaredVariables)); + } finally { + expression.keyword = oldKeyword; + } + return !listener.hasConstError; + } } class LinterContextUnit { @@ -319,15 +363,21 @@ @override AstVisitor getVisitor() => null; - void reportLint(AstNode node, {bool ignoreSyntheticNodes: true}) { + void reportLint(AstNode node, + {List<Object> arguments: const [], + ErrorCode errorCode, + bool ignoreSyntheticNodes: true}) { if (node != null && (!node.isSynthetic || !ignoreSyntheticNodes)) { - reporter.reportErrorForNode(lintCode, node, []); + reporter.reportErrorForNode(lintCode, node, arguments); } } - void reportLintForToken(Token token, {bool ignoreSyntheticTokens: true}) { + void reportLintForToken(Token token, + {List<Object> arguments: const [], + ErrorCode errorCode, + bool ignoreSyntheticTokens: true}) { if (token != null && (!token.isSynthetic || !ignoreSyntheticTokens)) { - reporter.reportErrorForToken(lintCode, token, []); + reporter.reportErrorForToken(lintCode, token, arguments); } } @@ -380,27 +430,19 @@ /// This method is invoked to let the [LintRule] register node processors /// in the given [registry]. /// - /// In a future release of the analyzer, a `context` argument will be added. - /// To opt into the new API, use [NodeLintRuleWithContext] instead. - void registerNodeProcessors(NodeLintRegistry registry); + /// The node processors may use the provided [context] to access information + /// that is not available from the AST nodes or their associated elements. + void registerNodeProcessors(NodeLintRegistry registry, LinterContext context); } /// [LintRule]s that implement this interface want to process only some types /// of AST nodes, and will register their processors in the registry. /// -/// TODO(paulberry): once NodeLintRule is removed, rename this interface to -/// NodeLintRule. -abstract class NodeLintRuleWithContext extends NodeLintRule { - /// This method is invoked to let the [LintRule] register node processors - /// in the given [registry]. - /// - /// The node processors may use the provided [context] to access information - /// that is not available from the AST nodes or their associated elements. - /// In a future release of the analyzer, [context] will become a required - /// parameter. - void registerNodeProcessors(NodeLintRegistry registry, - [LinterContext context]); -} +/// This class exists solely to allow a smoother transition from analyzer +/// version 0.33.*. It will be removed in a future analyzer release, so please +/// use [NodeLintRule] instead. +@deprecated +abstract class NodeLintRuleWithContext extends NodeLintRule {} class PrintingReporter implements Reporter, Logger { final Printer _print;
diff --git a/pkg/analyzer/lib/src/lint/options_rule_validator.dart b/pkg/analyzer/lib/src/lint/options_rule_validator.dart index 2d6911a..0858037 100644 --- a/pkg/analyzer/lib/src/lint/options_rule_validator.dart +++ b/pkg/analyzer/lib/src/lint/options_rule_validator.dart
@@ -2,13 +2,26 @@ // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. -import 'package:analyzer/analyzer.dart'; +import 'package:analyzer/error/error.dart'; +import 'package:analyzer/error/listener.dart'; +import 'package:analyzer/src/analysis_options/error/option_codes.dart'; +import 'package:analyzer/src/lint/linter.dart'; import 'package:analyzer/src/lint/registry.dart'; import 'package:analyzer/src/plugin/options.dart'; import 'package:analyzer/src/util/yaml.dart'; import 'package:yaml/yaml.dart'; /** + * A hint code indicating reference to a deprecated lint. + * + * Parameters: + * 0: the rule name + */ +const AnalysisOptionsHintCode DEPRECATED_LINT_HINT = + const AnalysisOptionsHintCode('DEPRECATED_LINT_HINT', + "'{0}' is a deprecated lint rule and should not be used"); + +/** * An error code indicating an undefined lint rule. * * Parameters: @@ -19,12 +32,22 @@ 'UNDEFINED_LINT_WARNING', "'{0}' is not a recognized lint rule"); /** + * Rule provider. + */ +typedef LintRuleProvider = Iterable<LintRule> Function(); + +/** * Validates `linter` rule configurations. */ class LinterRuleOptionsValidator extends OptionsValidator { static const linter = 'linter'; static const rulesKey = 'rules'; + final LintRuleProvider ruleProvider; + + LinterRuleOptionsValidator({LintRuleProvider provider}) + : ruleProvider = provider ?? (() => Registry.ruleRegistry.rules); + @override List<AnalysisError> validate(ErrorReporter reporter, YamlMap options) { List<AnalysisError> errors = <AnalysisError>[]; @@ -38,15 +61,22 @@ validateRules(YamlNode rules, ErrorReporter reporter) { if (rules is YamlList) { - List<String> registeredLints = - Registry.ruleRegistry.map((r) => r.name).toList(); rules.nodes.forEach((YamlNode ruleNode) { Object value = ruleNode.value; - if (value != null && !registeredLints.contains(value)) { - reporter.reportErrorForSpan( - UNDEFINED_LINT_WARNING, ruleNode.span, [value]); + if (value != null) { + LintRule rule = getRegisteredLint(value); + if (rule == null) { + reporter.reportErrorForSpan( + UNDEFINED_LINT_WARNING, ruleNode.span, [value]); + } else if (rule.maturity == Maturity.deprecated) { + reporter.reportErrorForSpan( + DEPRECATED_LINT_HINT, ruleNode.span, [value]); + } } }); } } + + LintRule getRegisteredLint(Object value) => ruleProvider() + .firstWhere((rule) => rule.name == value, orElse: () => null); }
diff --git a/pkg/analyzer/lib/src/lint/project.dart b/pkg/analyzer/lib/src/lint/project.dart index f87c70f..7243747 100644 --- a/pkg/analyzer/lib/src/lint/project.dart +++ b/pkg/analyzer/lib/src/lint/project.dart
@@ -5,6 +5,7 @@ import 'dart:async'; import 'dart:io'; +import 'package:analyzer/dart/analysis/results.dart'; import 'package:analyzer/dart/element/element.dart'; import 'package:analyzer/src/dart/analysis/driver.dart'; import 'package:analyzer/src/generated/resolver.dart'; @@ -135,7 +136,7 @@ for (Source source in sources) { String path = source.uri.path; if (path.startsWith(libDir) && !path.startsWith(libSrcDir)) { - AnalysisResult result = await driver.getResult(source.fullName); + ResolvedUnitResult result = await driver.getResult(source.fullName); LibraryElement library = result.libraryElement; NamespaceBuilder namespaceBuilder = new NamespaceBuilder();
diff --git a/pkg/analyzer/lib/src/lint/pub.dart b/pkg/analyzer/lib/src/lint/pub.dart index 1db39bf..8e6deed 100644 --- a/pkg/analyzer/lib/src/lint/pub.dart +++ b/pkg/analyzer/lib/src/lint/pub.dart
@@ -1,4 +1,4 @@ -// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file +// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. @@ -81,8 +81,7 @@ PSEntry get version; } -abstract class PSDependencyList extends Object - with IterableMixin<PSDependency> {} +abstract class PSDependencyList with IterableMixin<PSDependency> {} class PSEntry { final PSNode key; @@ -110,7 +109,7 @@ String get text; } -abstract class PSNodeList extends Object with IterableMixin<PSNode> { +abstract class PSNodeList with IterableMixin<PSNode> { @override Iterator<PSNode> get iterator; PSNode get token; @@ -137,8 +136,8 @@ T visitPackageAuthors(PSNodeList authors) => null; T visitPackageDependencies(PSDependencyList dependencies) => null; T visitPackageDependency(PSDependency dependency) => null; - T visitPackageDependencyOverrides(PSDependencyList dependencies) => null; T visitPackageDependencyOverride(PSDependency dependency) => null; + T visitPackageDependencyOverrides(PSDependencyList dependencies) => null; T visitPackageDescription(PSEntry description) => null; T visitPackageDevDependencies(PSDependencyList dependencies) => null; T visitPackageDevDependency(PSDependency dependency) => null;
diff --git a/pkg/analyzer/lib/src/lint/registry.dart b/pkg/analyzer/lib/src/lint/registry.dart index 24b5e47..4e02ac7 100644 --- a/pkg/analyzer/lib/src/lint/registry.dart +++ b/pkg/analyzer/lib/src/lint/registry.dart
@@ -1,4 +1,4 @@ -// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file +// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. @@ -10,7 +10,7 @@ /** * Registry of lint rules. */ -class Registry extends Object with IterableMixin<LintRule> { +class Registry with IterableMixin<LintRule> { /** * The default registry to be used by clients. */
diff --git a/pkg/analyzer/lib/src/lint/util.dart b/pkg/analyzer/lib/src/lint/util.dart index 39248bc..2e12794 100644 --- a/pkg/analyzer/lib/src/lint/util.dart +++ b/pkg/analyzer/lib/src/lint/util.dart
@@ -1,17 +1,20 @@ -// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file +// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. import 'dart:io'; -import 'package:analyzer/analyzer.dart'; +import 'package:analyzer/dart/ast/ast.dart'; import 'package:analyzer/dart/ast/token.dart'; +import 'package:analyzer/dart/ast/visitor.dart'; +import 'package:analyzer/error/error.dart'; +import 'package:analyzer/error/listener.dart'; import 'package:analyzer/src/dart/ast/token.dart'; import 'package:analyzer/src/dart/scanner/reader.dart'; import 'package:analyzer/src/dart/scanner/scanner.dart'; import 'package:analyzer/src/generated/parser.dart' show Parser; import 'package:analyzer/src/string_source.dart' show StringSource; -import 'package:path/path.dart' as p; +import 'package:path/path.dart' as path; final _identifier = new RegExp(r'^([(_|$)a-zA-Z]+([_a-zA-Z0-9])*)$'); @@ -32,21 +35,21 @@ String createLibraryNamePrefix( {String libraryPath, String projectRoot, String packageName}) { // Use the posix context to canonicalize separators (`\`). - var libraryDirectory = p.posix.dirname(libraryPath); - var path = p.posix.relative(libraryDirectory, from: projectRoot); + var libraryDirectory = path.posix.dirname(libraryPath); + var relativePath = path.posix.relative(libraryDirectory, from: projectRoot); // Drop 'lib/'. - var segments = p.split(path); + var segments = path.split(relativePath); if (segments[0] == 'lib') { - path = p.posix.joinAll(segments.sublist(1)); + relativePath = path.posix.joinAll(segments.sublist(1)); } // Replace separators. - path = path.replaceAll('/', '.'); + relativePath = relativePath.replaceAll('/', '.'); // Add separator if needed. - if (path.isNotEmpty) { - path = '.$path'; + if (relativePath.isNotEmpty) { + relativePath = '.$relativePath'; } - return '$packageName$path'; + return '$packageName$relativePath'; } /// Returns `true` if this [fileName] is a Dart file.
diff --git a/pkg/analyzer/lib/src/summary/expr_builder.dart b/pkg/analyzer/lib/src/summary/expr_builder.dart index 66112ea..77d31cd 100644 --- a/pkg/analyzer/lib/src/summary/expr_builder.dart +++ b/pkg/analyzer/lib/src/summary/expr_builder.dart
@@ -48,239 +48,245 @@ if (requireValidConst && !uc.isValidConst) { return null; } - try { - for (UnlinkedExprOperation operation in uc.operations) { - switch (operation) { - case UnlinkedExprOperation.pushNull: - _push(AstTestFactory.nullLiteral()); - break; - // bool - case UnlinkedExprOperation.pushFalse: - _push(AstTestFactory.booleanLiteral(false)); - break; - case UnlinkedExprOperation.pushTrue: - _push(AstTestFactory.booleanLiteral(true)); - break; - // literals - case UnlinkedExprOperation.pushInt: - int value = uc.ints[intPtr++]; - _push(AstTestFactory.integer(value)); - break; - case UnlinkedExprOperation.pushLongInt: - int value = 0; - int count = uc.ints[intPtr++]; - for (int i = 0; i < count; i++) { - int next = uc.ints[intPtr++]; - value = value << 32 | next; - } - _push(AstTestFactory.integer(value)); - break; - case UnlinkedExprOperation.pushDouble: - double value = uc.doubles[doublePtr++]; - _push(AstTestFactory.doubleLiteral(value)); - break; - case UnlinkedExprOperation.makeSymbol: - String component = uc.strings[stringPtr++]; - _push(AstTestFactory.symbolLiteral([component])); - break; - // String - case UnlinkedExprOperation.pushString: - String value = uc.strings[stringPtr++]; - _push(AstTestFactory.string2(value)); - break; - case UnlinkedExprOperation.concatenate: - int count = uc.ints[intPtr++]; - List<InterpolationElement> elements = <InterpolationElement>[]; - for (int i = 0; i < count; i++) { - Expression expr = _pop(); - InterpolationElement element = _newInterpolationElement(expr); - elements.insert(0, element); - } - _push(AstTestFactory.string(elements)); - break; - // binary - case UnlinkedExprOperation.equal: - _pushBinary(TokenType.EQ_EQ); - break; - case UnlinkedExprOperation.notEqual: - _pushBinary(TokenType.BANG_EQ); - break; - case UnlinkedExprOperation.and: - _pushBinary(TokenType.AMPERSAND_AMPERSAND); - break; - case UnlinkedExprOperation.or: - _pushBinary(TokenType.BAR_BAR); - break; - case UnlinkedExprOperation.bitXor: - _pushBinary(TokenType.CARET); - break; - case UnlinkedExprOperation.bitAnd: - _pushBinary(TokenType.AMPERSAND); - break; - case UnlinkedExprOperation.bitOr: - _pushBinary(TokenType.BAR); - break; - case UnlinkedExprOperation.bitShiftLeft: - _pushBinary(TokenType.LT_LT); - break; - case UnlinkedExprOperation.bitShiftRight: - _pushBinary(TokenType.GT_GT); - break; - case UnlinkedExprOperation.add: - _pushBinary(TokenType.PLUS); - break; - case UnlinkedExprOperation.subtract: - _pushBinary(TokenType.MINUS); - break; - case UnlinkedExprOperation.multiply: - _pushBinary(TokenType.STAR); - break; - case UnlinkedExprOperation.divide: - _pushBinary(TokenType.SLASH); - break; - case UnlinkedExprOperation.floorDivide: - _pushBinary(TokenType.TILDE_SLASH); - break; - case UnlinkedExprOperation.modulo: - _pushBinary(TokenType.PERCENT); - break; - case UnlinkedExprOperation.greater: - _pushBinary(TokenType.GT); - break; - case UnlinkedExprOperation.greaterEqual: - _pushBinary(TokenType.GT_EQ); - break; - case UnlinkedExprOperation.less: - _pushBinary(TokenType.LT); - break; - case UnlinkedExprOperation.lessEqual: - _pushBinary(TokenType.LT_EQ); - break; - // prefix - case UnlinkedExprOperation.complement: - _pushPrefix(TokenType.TILDE); - break; - case UnlinkedExprOperation.negate: - _pushPrefix(TokenType.MINUS); - break; - case UnlinkedExprOperation.not: - _pushPrefix(TokenType.BANG); - break; - // conditional - case UnlinkedExprOperation.conditional: - Expression elseExpr = _pop(); - Expression thenExpr = _pop(); - Expression condition = _pop(); - _push(AstTestFactory.conditionalExpression( - condition, thenExpr, elseExpr)); - break; - case UnlinkedExprOperation.invokeMethodRef: - _pushInvokeMethodRef(); - break; - case UnlinkedExprOperation.invokeMethod: - List<Expression> arguments = _buildArguments(); - TypeArgumentList typeArguments = _buildTypeArguments(); - Expression target = _pop(); - String name = uc.strings[stringPtr++]; - _push(AstTestFactory.methodInvocation3( - target, name, typeArguments, arguments)); - break; - // containers - case UnlinkedExprOperation.makeUntypedList: - _pushList(null); - break; - case UnlinkedExprOperation.makeTypedList: - TypeAnnotation itemType = _newTypeName(); - _pushList( - AstTestFactory.typeArgumentList(<TypeAnnotation>[itemType])); - break; - case UnlinkedExprOperation.makeUntypedMap: - _pushMap(null); - break; - case UnlinkedExprOperation.makeTypedMap: - TypeAnnotation keyType = _newTypeName(); - TypeAnnotation valueType = _newTypeName(); - _pushMap(AstTestFactory.typeArgumentList( - <TypeAnnotation>[keyType, valueType])); - break; - case UnlinkedExprOperation.pushReference: - _pushReference(); - break; - case UnlinkedExprOperation.extractProperty: - _pushExtractProperty(); - break; - case UnlinkedExprOperation.invokeConstructor: - _pushInstanceCreation(); - break; - case UnlinkedExprOperation.pushParameter: - String name = uc.strings[stringPtr++]; - SimpleIdentifier identifier = AstTestFactory.identifier3(name); - identifier.staticElement = parametersInScope[name]; - _push(identifier); - break; - case UnlinkedExprOperation.ifNull: - _pushBinary(TokenType.QUESTION_QUESTION); - break; - case UnlinkedExprOperation.await: - Expression expression = _pop(); - _push(AstTestFactory.awaitExpression(expression)); - break; - case UnlinkedExprOperation.pushLocalFunctionReference: - _pushLocalFunctionReference(); - break; - case UnlinkedExprOperation.assignToRef: - var ref = _createReference(); - _push(_createAssignment(ref)); - break; - case UnlinkedExprOperation.typeCast: - Expression expression = _pop(); - TypeAnnotation type = _newTypeName(); - _push(AstTestFactory.asExpression(expression, type)); - break; - case UnlinkedExprOperation.typeCheck: - Expression expression = _pop(); - TypeAnnotation type = _newTypeName(); - _push(AstTestFactory.isExpression(expression, false, type)); - break; - case UnlinkedExprOperation.throwException: - Expression expression = _pop(); - _push(AstTestFactory.throwExpression2(expression)); - break; - case UnlinkedExprOperation.assignToProperty: - Expression target = _pop(); - String name = uc.strings[stringPtr++]; - SimpleIdentifier propertyNode = AstTestFactory.identifier3(name); - PropertyAccess propertyAccess = - AstTestFactory.propertyAccess(target, propertyNode); - _push(_createAssignment(propertyAccess)); - break; - case UnlinkedExprOperation.assignToIndex: - Expression index = _pop(); - Expression target = _pop(); - IndexExpression indexExpression = - AstTestFactory.indexExpression(target, index); - _push(_createAssignment(indexExpression)); - break; - case UnlinkedExprOperation.extractIndex: - Expression index = _pop(); - Expression target = _pop(); - _push(AstTestFactory.indexExpression(target, index)); - break; - case UnlinkedExprOperation.pushSuper: - case UnlinkedExprOperation.pushThis: - throw const _InvalidConstantException(); // TODO(paulberry) - case UnlinkedExprOperation.cascadeSectionBegin: - case UnlinkedExprOperation.cascadeSectionEnd: - case UnlinkedExprOperation.pushLocalFunctionReference: - case UnlinkedExprOperation.pushError: - case UnlinkedExprOperation.pushTypedAbstract: - case UnlinkedExprOperation.pushUntypedAbstract: - throw new UnimplementedError( - 'Unexpected $operation in a constant expression.'); - } + for (UnlinkedExprOperation operation in uc.operations) { + switch (operation) { + case UnlinkedExprOperation.pushNull: + _push(AstTestFactory.nullLiteral()); + break; + // bool + case UnlinkedExprOperation.pushFalse: + _push(AstTestFactory.booleanLiteral(false)); + break; + case UnlinkedExprOperation.pushTrue: + _push(AstTestFactory.booleanLiteral(true)); + break; + // literals + case UnlinkedExprOperation.pushInt: + int value = uc.ints[intPtr++]; + _push(AstTestFactory.integer(value)); + break; + case UnlinkedExprOperation.pushLongInt: + int value = 0; + int count = uc.ints[intPtr++]; + for (int i = 0; i < count; i++) { + int next = uc.ints[intPtr++]; + value = value << 32 | next; + } + _push(AstTestFactory.integer(value)); + break; + case UnlinkedExprOperation.pushDouble: + double value = uc.doubles[doublePtr++]; + _push(AstTestFactory.doubleLiteral(value)); + break; + case UnlinkedExprOperation.makeSymbol: + String component = uc.strings[stringPtr++]; + _push(AstTestFactory.symbolLiteral([component])); + break; + // String + case UnlinkedExprOperation.pushString: + String value = uc.strings[stringPtr++]; + _push(AstTestFactory.string2(value)); + break; + case UnlinkedExprOperation.concatenate: + int count = uc.ints[intPtr++]; + List<InterpolationElement> elements = <InterpolationElement>[]; + for (int i = 0; i < count; i++) { + Expression expr = _pop(); + InterpolationElement element = _newInterpolationElement(expr); + elements.insert(0, element); + } + _push(AstTestFactory.string(elements)); + break; + // binary + case UnlinkedExprOperation.equal: + _pushBinary(TokenType.EQ_EQ); + break; + case UnlinkedExprOperation.notEqual: + _pushBinary(TokenType.BANG_EQ); + break; + case UnlinkedExprOperation.and: + _pushBinary(TokenType.AMPERSAND_AMPERSAND); + break; + case UnlinkedExprOperation.or: + _pushBinary(TokenType.BAR_BAR); + break; + case UnlinkedExprOperation.bitXor: + _pushBinary(TokenType.CARET); + break; + case UnlinkedExprOperation.bitAnd: + _pushBinary(TokenType.AMPERSAND); + break; + case UnlinkedExprOperation.bitOr: + _pushBinary(TokenType.BAR); + break; + case UnlinkedExprOperation.bitShiftLeft: + _pushBinary(TokenType.LT_LT); + break; + case UnlinkedExprOperation.bitShiftRight: + _pushBinary(TokenType.GT_GT); + break; + case UnlinkedExprOperation.add: + _pushBinary(TokenType.PLUS); + break; + case UnlinkedExprOperation.subtract: + _pushBinary(TokenType.MINUS); + break; + case UnlinkedExprOperation.multiply: + _pushBinary(TokenType.STAR); + break; + case UnlinkedExprOperation.divide: + _pushBinary(TokenType.SLASH); + break; + case UnlinkedExprOperation.floorDivide: + _pushBinary(TokenType.TILDE_SLASH); + break; + case UnlinkedExprOperation.modulo: + _pushBinary(TokenType.PERCENT); + break; + case UnlinkedExprOperation.greater: + _pushBinary(TokenType.GT); + break; + case UnlinkedExprOperation.greaterEqual: + _pushBinary(TokenType.GT_EQ); + break; + case UnlinkedExprOperation.less: + _pushBinary(TokenType.LT); + break; + case UnlinkedExprOperation.lessEqual: + _pushBinary(TokenType.LT_EQ); + break; + // prefix + case UnlinkedExprOperation.complement: + _pushPrefix(TokenType.TILDE); + break; + case UnlinkedExprOperation.negate: + _pushPrefix(TokenType.MINUS); + break; + case UnlinkedExprOperation.not: + _pushPrefix(TokenType.BANG); + break; + // conditional + case UnlinkedExprOperation.conditional: + Expression elseExpr = _pop(); + Expression thenExpr = _pop(); + Expression condition = _pop(); + _push(AstTestFactory.conditionalExpression( + condition, thenExpr, elseExpr)); + break; + case UnlinkedExprOperation.invokeMethodRef: + _pushInvokeMethodRef(); + break; + case UnlinkedExprOperation.invokeMethod: + List<Expression> arguments = _buildArguments(); + TypeArgumentList typeArguments = _buildTypeArguments(); + Expression target = _pop(); + String name = uc.strings[stringPtr++]; + _push(AstTestFactory.methodInvocation3( + target, name, typeArguments, arguments)); + break; + // containers + case UnlinkedExprOperation.makeUntypedList: + _pushList(null); + break; + case UnlinkedExprOperation.makeTypedList: + TypeAnnotation itemType = _newTypeName(); + _pushList( + AstTestFactory.typeArgumentList(<TypeAnnotation>[itemType])); + break; + case UnlinkedExprOperation.makeUntypedMap: + _pushMap(null); + break; + case UnlinkedExprOperation.makeTypedMap: + TypeAnnotation keyType = _newTypeName(); + TypeAnnotation valueType = _newTypeName(); + _pushMap(AstTestFactory.typeArgumentList( + <TypeAnnotation>[keyType, valueType])); + break; + case UnlinkedExprOperation.makeUntypedSet: + _pushSet(null); + break; + case UnlinkedExprOperation.makeTypedSet: + TypeAnnotation itemType = _newTypeName(); + _pushSet(AstTestFactory.typeArgumentList(<TypeAnnotation>[itemType])); + break; + case UnlinkedExprOperation.pushReference: + _pushReference(); + break; + case UnlinkedExprOperation.extractProperty: + _pushExtractProperty(); + break; + case UnlinkedExprOperation.invokeConstructor: + _pushInstanceCreation(); + break; + case UnlinkedExprOperation.pushParameter: + String name = uc.strings[stringPtr++]; + SimpleIdentifier identifier = AstTestFactory.identifier3(name); + identifier.staticElement = parametersInScope[name]; + _push(identifier); + break; + case UnlinkedExprOperation.ifNull: + _pushBinary(TokenType.QUESTION_QUESTION); + break; + case UnlinkedExprOperation.await: + Expression expression = _pop(); + _push(AstTestFactory.awaitExpression(expression)); + break; + case UnlinkedExprOperation.pushLocalFunctionReference: + _pushLocalFunctionReference(); + break; + case UnlinkedExprOperation.assignToRef: + var ref = _createReference(); + _push(_createAssignment(ref)); + break; + case UnlinkedExprOperation.typeCast: + Expression expression = _pop(); + TypeAnnotation type = _newTypeName(); + _push(AstTestFactory.asExpression(expression, type)); + break; + case UnlinkedExprOperation.typeCheck: + Expression expression = _pop(); + TypeAnnotation type = _newTypeName(); + _push(AstTestFactory.isExpression(expression, false, type)); + break; + case UnlinkedExprOperation.throwException: + Expression expression = _pop(); + _push(AstTestFactory.throwExpression2(expression)); + break; + case UnlinkedExprOperation.assignToProperty: + Expression target = _pop(); + String name = uc.strings[stringPtr++]; + SimpleIdentifier propertyNode = AstTestFactory.identifier3(name); + PropertyAccess propertyAccess = + AstTestFactory.propertyAccess(target, propertyNode); + _push(_createAssignment(propertyAccess)); + break; + case UnlinkedExprOperation.assignToIndex: + Expression index = _pop(); + Expression target = _pop(); + IndexExpression indexExpression = + AstTestFactory.indexExpression(target, index); + _push(_createAssignment(indexExpression)); + break; + case UnlinkedExprOperation.extractIndex: + Expression index = _pop(); + Expression target = _pop(); + _push(AstTestFactory.indexExpression(target, index)); + break; + case UnlinkedExprOperation.pushSuper: + _push(AstTestFactory.superExpression()); + break; + case UnlinkedExprOperation.pushThis: + _push(AstTestFactory.thisExpression()); + break; + case UnlinkedExprOperation.cascadeSectionBegin: + case UnlinkedExprOperation.cascadeSectionEnd: + case UnlinkedExprOperation.pushLocalFunctionReference: + case UnlinkedExprOperation.pushError: + case UnlinkedExprOperation.pushTypedAbstract: + case UnlinkedExprOperation.pushUntypedAbstract: + throw new UnimplementedError( + 'Unexpected $operation in a constant expression.'); } - } on _InvalidConstantException { - return AstTestFactory.identifier3(r'#invalidConst'); } return stack.single; } @@ -430,9 +436,6 @@ ..staticElement = element; return AstTestFactory.identifier(enclosing, identifier); } - if (requireValidConst && element == null) { - throw const _InvalidConstantException(); - } SimpleIdentifier property = AstTestFactory.identifier3(info.name) ..staticElement = element; return AstTestFactory.propertyAccess(enclosing, property); @@ -522,12 +525,16 @@ Expression _createReference() { EntityRef ref = uc.references[refPtr++]; - ReferenceInfo info = resynthesizer.getReferenceInfo(ref.reference); - Expression node = _buildIdentifierSequence(info); - if (requireValidConst && node is Identifier && node.staticElement == null) { - throw const _InvalidConstantException(); + if (ref.paramReference != 0) { + // This is a reference to a type parameter. For type inference purposes + // we don't actually need to know which type parameter it's a reference + // to; we just need to know that it represents a type. So map it to + // `Object`. + return AstTestFactory.identifier3('Object') + ..staticElement = resynthesizer.typeProvider.objectType.element; } - return node; + ReferenceInfo info = resynthesizer.getReferenceInfo(ref.reference); + return _buildIdentifierSequence(info); } PropertyAccessorElement _getStringLengthElement() => @@ -605,11 +612,11 @@ } else if (info.element is ClassElement) { constructorName = null; } else { - List<Expression> arguments = _buildArguments(); - SimpleIdentifier name = AstTestFactory.identifier3(info.name); - name.staticElement = info.element; - name.setProperty(ARGUMENT_LIST, AstTestFactory.argumentList(arguments)); - _push(name); + // Unexpected element, consider it unresolved. + _buildArguments(); + var identifier = AstTestFactory.identifier3('__unresolved__') + ..staticType = resynthesizer.typeProvider.dynamicType; + _push(identifier); return; } InterfaceType definingType = resynthesizer.createConstructorDefiningType( @@ -657,9 +664,6 @@ constructorNode = AstTestFactory.constructorName(typeNode, null); } constructorNode.staticElement = constructorElement; - if (constructorElement == null) { - throw const _InvalidConstantException(); - } // create InstanceCreationExpression InstanceCreationExpression instanceCreation = AstTestFactory.instanceCreationExpression( @@ -720,7 +724,6 @@ } void _pushLocalFunctionReference() { - _throwIfConst(); int popCount = uc.ints[intPtr++]; // Note: nonzero popCount is no longer used. assert(popCount == 0); @@ -796,6 +799,15 @@ _push(_createReference()); } + void _pushSet(TypeArgumentList typeArguments) { + int count = uc.ints[intPtr++]; + List<Expression> elements = <Expression>[]; + for (int i = 0; i < count; i++) { + elements.insert(0, _pop()); + } + _push(AstTestFactory.setLiteral(Keyword.CONST, typeArguments, elements)); + } + List<Expression> _removeTopItems(int count) { int start = stack.length - count; int end = stack.length; @@ -804,12 +816,6 @@ return items; } - void _throwIfConst() { - if (requireValidConst) { - throw const _InvalidConstantException(); - } - } - /// Figures out the default value of [parametersInScope] based on [context]. /// /// If [context] is (or contains) a constructor, then its parameters are used. @@ -827,11 +833,3 @@ return result; } } - -/** - * This exception is thrown when we detect that the constant expression - * being resynthesized is not a valid constant expression. - */ -class _InvalidConstantException { - const _InvalidConstantException(); -}
diff --git a/pkg/analyzer/lib/src/summary/flat_buffers.dart b/pkg/analyzer/lib/src/summary/flat_buffers.dart index 3449a3b..c291d61 100644 --- a/pkg/analyzer/lib/src/summary/flat_buffers.dart +++ b/pkg/analyzer/lib/src/summary/flat_buffers.dart
@@ -1,4 +1,4 @@ -// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file +// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. @@ -757,7 +757,7 @@ /** * List of booleans backed by 8-bit unsigned integers. */ -class _FbBoolList extends Object with ListMixin<bool> implements List<bool> { +class _FbBoolList with ListMixin<bool> implements List<bool> { final BufferContext bc; final int offset; int _length; @@ -829,7 +829,7 @@ /** * The base class for immutable lists read from flat buffers. */ -abstract class _FbList<E> extends Object with ListMixin<E> implements List<E> { +abstract class _FbList<E> with ListMixin<E> implements List<E> { final BufferContext bc; final int offset; int _length;
diff --git a/pkg/analyzer/lib/src/summary/format.fbs b/pkg/analyzer/lib/src/summary/format.fbs index 4289b7f..44e6520d 100644 --- a/pkg/analyzer/lib/src/summary/format.fbs +++ b/pkg/analyzer/lib/src/summary/format.fbs
@@ -639,7 +639,19 @@ pushThis, /// Push `super` expression onto the stack. - pushSuper + pushSuper, + + /// Pop the top n values from the stack (where n is obtained from + /// [UnlinkedExpr.ints]), place them in a [Set], and push the result back + /// onto the stack. The type parameter for the [Set] is implicitly + /// `dynamic`. + makeUntypedSet, + + /// Pop the top n values from the stack (where n is obtained from + /// [UnlinkedExpr.ints]), place them in a [Set], and push the result back + /// onto the stack. The type parameter for the [Set] is obtained from + /// [UnlinkedExpr.references]. + makeTypedSet } /// Enum used to indicate the kind of a parameter.
diff --git a/pkg/analyzer/lib/src/summary/idl.dart b/pkg/analyzer/lib/src/summary/idl.dart index 8a85d55..02bd1fd 100644 --- a/pkg/analyzer/lib/src/summary/idl.dart +++ b/pkg/analyzer/lib/src/summary/idl.dart
@@ -1954,6 +1954,18 @@ /// Push `super` expression onto the stack. pushSuper, + + /// Pop the top n values from the stack (where n is obtained from + /// [UnlinkedExpr.ints]), place them in a [Set], and push the result back + /// onto the stack. The type parameter for the [Set] is implicitly + /// `dynamic`. + makeUntypedSet, + + /// Pop the top n values from the stack (where n is obtained from + /// [UnlinkedExpr.ints]), place them in a [Set], and push the result back + /// onto the stack. The type parameter for the [Set] is obtained from + /// [UnlinkedExpr.references]. + makeTypedSet, } /// Unlinked summary information about an import declaration.
diff --git a/pkg/analyzer/lib/src/summary/link.dart b/pkg/analyzer/lib/src/summary/link.dart index 7feaae8..8e0381c 100644 --- a/pkg/analyzer/lib/src/summary/link.dart +++ b/pkg/analyzer/lib/src/summary/link.dart
@@ -1,7 +1,9 @@ -// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file +// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. +import 'package:analyzer/dart/analysis/session.dart'; + /// This library is capable of producing linked summaries from unlinked /// ones (or prelinked ones). It functions by building a miniature /// element model to represent the contents of the summaries, and then @@ -416,14 +418,12 @@ AnalysisOptionsForLink(this._linker); @override - bool get declarationCasts => true; - - @override bool get hint => false; @override bool get implicitCasts => true; + @deprecated @override bool get previewDart2 => true; @@ -439,7 +439,7 @@ /// Element representing a class or enum resynthesized from a summary /// during linking. -abstract class ClassElementForLink extends Object +abstract class ClassElementForLink with ReferenceableElementForLink implements AbstractClassElementImpl { Map<String, ReferenceableElementForLink> _containedNames; @@ -800,6 +800,9 @@ String get name => _unlinkedClass.name; @override + AnalysisSession get session => enclosingUnit.session; + + @override List<InterfaceType> get superclassConstraints { if (_superclassConstraints == null) { if (isMixin) { @@ -1229,6 +1232,9 @@ ResynthesizerContext get resynthesizerContext => this; @override + AnalysisSession get session => library.session; + + @override List<TopLevelVariableElementForLink> get topLevelVariables { if (_topLevelVariables == null) { List<Expression> initializerExpressionsForInference; @@ -1908,6 +1914,7 @@ break; case UnlinkedExprOperation.makeUntypedList: case UnlinkedExprOperation.makeUntypedMap: + case UnlinkedExprOperation.makeUntypedSet: intPtr++; break; case UnlinkedExprOperation.assignToRef: @@ -1930,6 +1937,7 @@ refPtr += numTypeArguments; break; case UnlinkedExprOperation.makeTypedList: + case UnlinkedExprOperation.makeTypedSet: refPtr++; intPtr++; break; @@ -2221,7 +2229,7 @@ /// Base class for executable elements resynthesized from a summary during /// linking. -abstract class ExecutableElementForLink extends Object +abstract class ExecutableElementForLink with TypeParameterizedElementMixin, ParameterParentElementForLink implements ExecutableElementImpl { /// The unlinked representation of the method in the summary. @@ -2339,6 +2347,9 @@ } @override + AnalysisSession get session => compilationUnit.session; + + @override FunctionTypeImpl get type => _type ??= new FunctionTypeImpl(this); @override @@ -2722,7 +2733,7 @@ /// Element representing a function-typed parameter resynthesied from a summary /// during linking. -class FunctionElementForLink_FunctionTypedParam extends Object +class FunctionElementForLink_FunctionTypedParam with ParameterParentElementForLink implements FunctionElement { @override @@ -2775,7 +2786,7 @@ } /// Element representing the initializer expression of a variable. -class FunctionElementForLink_Initializer extends Object +class FunctionElementForLink_Initializer with ReferenceableElementForLink, TypeParameterizedElementMixin implements FunctionElementForLink_Local { /// The variable for which this element is the initializer. @@ -3086,7 +3097,7 @@ } /// Element representing a typedef resynthesized from a summary during linking. -class FunctionTypeAliasElementForLink extends Object +class FunctionTypeAliasElementForLink with TypeParameterizedElementMixin, ParameterParentElementForLink, @@ -3147,6 +3158,9 @@ enclosingElement.resolveTypeRef(this, _unlinkedTypedef.returnType); @override + AnalysisSession get session => enclosingElement.session; + + @override TypeParameterizedElementMixin get typeParameterContext => this; @override @@ -3198,7 +3212,7 @@ /// Element representing a generic function resynthesized from a summary during /// linking. -class GenericFunctionTypeElementForLink extends Object +class GenericFunctionTypeElementForLink with TypeParameterizedElementMixin, ParameterParentElementForLink, @@ -3262,6 +3276,9 @@ _returnType ??= enclosingUnit.resolveTypeRef(this, _unlinkedReturnType); @override + AnalysisSession get session => enclosingElement.session; + + @override FunctionType get type { return _type ??= new FunctionTypeImpl(this); } @@ -3278,7 +3295,7 @@ /// Element representing a generic typedef resynthesized from a summary during /// linking. -class GenericTypeAliasElementForLink extends Object +class GenericTypeAliasElementForLink with TypeParameterizedElementMixin, ParameterParentElementForLink, @@ -3342,6 +3359,9 @@ this, _unlinkedTypedef.returnType.syntheticReturnType); @override + AnalysisSession get session => enclosingElement.session; + + @override TypeParameterizedElementMixin get typeParameterContext => this; @override @@ -4075,8 +4095,7 @@ /// Accesses to a chain of non-static members separated by '.' are handled by /// creating a [NonstaticMemberElementForLink] that points to another /// [NonstaticMemberElementForLink], to whatever nesting level is necessary. -class NonstaticMemberElementForLink extends Object - with ReferenceableElementForLink { +class NonstaticMemberElementForLink with ReferenceableElementForLink { /// The [ReferenceableElementForLink] which is the target of the non-static /// reference. final ReferenceableElementForLink _target; @@ -4455,7 +4474,7 @@ /// Specialization of [PropertyAccessorElementForLink] for synthetic accessors /// implied by the synthetic fields of an enum declaration. -class PropertyAccessorElementForLink_EnumField extends Object +class PropertyAccessorElementForLink_EnumField with ReferenceableElementForLink implements PropertyAccessorElementForLink { @override @@ -4472,6 +4491,9 @@ Element get enclosingElement => variable.enclosingElement; @override + bool get isAbstract => false; + + @override bool get isGetter => true; @override @@ -4592,7 +4614,7 @@ /// Specialization of [PropertyAccessorElementForLink] for synthetic accessors /// implied by a field or variable declaration. -class PropertyAccessorElementForLink_Variable extends Object +class PropertyAccessorElementForLink_Variable with ReferenceableElementForLink implements PropertyAccessorElementForLink { @override @@ -4710,7 +4732,7 @@ /// Base class representing an element which can be the target of a reference. /// When used as a mixin, implements the default behavior shared by most /// elements. -abstract class ReferenceableElementForLink implements Element { +mixin ReferenceableElementForLink implements Element { /// If this element is a class reference, return it. Otherwise return `null`. ClassElementForLink get asClass => null; @@ -4989,8 +5011,7 @@ } /// Element used for references to special types such as `void`. -class SpecialTypeElementForLink extends Object - with ReferenceableElementForLink { +class SpecialTypeElementForLink with ReferenceableElementForLink { final Linker linker; final DartType type; @@ -5178,9 +5199,11 @@ break; case UnlinkedExprOperation.makeUntypedList: case UnlinkedExprOperation.makeUntypedMap: + case UnlinkedExprOperation.makeUntypedSet: intPtr++; break; case UnlinkedExprOperation.makeTypedList: + case UnlinkedExprOperation.makeTypedSet: refPtr++; intPtr++; break; @@ -5304,9 +5327,12 @@ InterfaceType _iterableType; InterfaceType _listType; InterfaceType _mapType; + InterfaceType _mapNullNullType; InterfaceType _nullType; InterfaceType _numType; InterfaceType _objectType; + InterfaceType _setType; + InterfaceType _setNullType; InterfaceType _stackTraceType; InterfaceType _streamDynamicType; InterfaceType _streamType; @@ -5375,6 +5401,10 @@ _listType ??= _buildInterfaceType(_linker.coreLibrary, 'List'); @override + InterfaceType get mapNullNullType => + _mapNullNullType ??= mapType.instantiate(<DartType>[nullType, nullType]); + + @override InterfaceType get mapType => _mapType ??= _buildInterfaceType(_linker.coreLibrary, 'Map'); @@ -5397,6 +5427,14 @@ _objectType ??= _buildInterfaceType(_linker.coreLibrary, 'Object'); @override + InterfaceType get setNullType => + _setNullType ??= setType.instantiate(<DartType>[nullType]); + + @override + InterfaceType get setType => + _setType ??= _buildInterfaceType(_linker.coreLibrary, 'Set'); + + @override InterfaceType get stackTraceType => _stackTraceType ??= _buildInterfaceType(_linker.coreLibrary, 'StackTrace'); @@ -5434,7 +5472,7 @@ } /// Singleton element used for unresolved references. -class UndefinedElementForLink extends Object with ReferenceableElementForLink { +class UndefinedElementForLink with ReferenceableElementForLink { static final UndefinedElementForLink instance = new UndefinedElementForLink._();
diff --git a/pkg/analyzer/lib/src/summary/package_bundle_reader.dart b/pkg/analyzer/lib/src/summary/package_bundle_reader.dart index 801ab29..dc9e818 100644 --- a/pkg/analyzer/lib/src/summary/package_bundle_reader.dart +++ b/pkg/analyzer/lib/src/summary/package_bundle_reader.dart
@@ -1,6 +1,7 @@ import 'dart:io' as io; import 'dart:math' show min; +import 'package:analyzer/dart/analysis/session.dart'; import 'package:analyzer/dart/element/element.dart'; import 'package:analyzer/file_system/file_system.dart'; import 'package:analyzer/src/context/cache.dart'; @@ -73,8 +74,9 @@ */ class InputPackagesResultProvider extends ResynthesizerResultProvider { InputPackagesResultProvider( - InternalAnalysisContext context, SummaryDataStore dataStore) - : super(context, dataStore) { + InternalAnalysisContext context, SummaryDataStore dataStore, + {AnalysisSession session}) + : super(context, session, dataStore) { createResynthesizer(); context.typeProvider = resynthesizer.typeProvider; resynthesizer.finishCoreAsyncLibraries(); @@ -167,11 +169,12 @@ */ abstract class ResynthesizerResultProvider extends ResultProvider { final InternalAnalysisContext context; + final AnalysisSession session; final SummaryDataStore _dataStore; StoreBasedSummaryResynthesizer _resynthesizer; - ResynthesizerResultProvider(this.context, this._dataStore); + ResynthesizerResultProvider(this.context, this.session, this._dataStore); SummaryResynthesizer get resynthesizer => _resynthesizer; @@ -317,7 +320,7 @@ */ void createResynthesizer() { _resynthesizer = new StoreBasedSummaryResynthesizer( - context, context.sourceFactory, true, _dataStore); + context, session, context.sourceFactory, true, _dataStore); } /** @@ -334,9 +337,13 @@ class StoreBasedSummaryResynthesizer extends SummaryResynthesizer { final SummaryDataStore _dataStore; - StoreBasedSummaryResynthesizer(AnalysisContext context, - SourceFactory sourceFactory, bool _, this._dataStore) - : super(context, sourceFactory, true); + StoreBasedSummaryResynthesizer( + AnalysisContext context, + AnalysisSession session, + SourceFactory sourceFactory, + bool _, + this._dataStore) + : super(context, session, sourceFactory, true); @override LinkedLibrary getLinkedSummary(String uri) {
diff --git a/pkg/analyzer/lib/src/summary/public_namespace_computer.dart b/pkg/analyzer/lib/src/summary/public_namespace_computer.dart index 4d78177..4c2e4db 100644 --- a/pkg/analyzer/lib/src/summary/public_namespace_computer.dart +++ b/pkg/analyzer/lib/src/summary/public_namespace_computer.dart
@@ -2,7 +2,8 @@ // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. -import 'package:analyzer/analyzer.dart'; +import 'package:analyzer/dart/ast/ast.dart'; +import 'package:analyzer/dart/ast/visitor.dart'; import 'package:analyzer/src/summary/format.dart'; import 'package:analyzer/src/summary/idl.dart';
diff --git a/pkg/analyzer/lib/src/summary/resynthesize.dart b/pkg/analyzer/lib/src/summary/resynthesize.dart index 2add257..6b7fa39 100644 --- a/pkg/analyzer/lib/src/summary/resynthesize.dart +++ b/pkg/analyzer/lib/src/summary/resynthesize.dart
@@ -4,6 +4,7 @@ import 'dart:collection'; +import 'package:analyzer/dart/analysis/session.dart'; import 'package:analyzer/dart/ast/ast.dart'; import 'package:analyzer/dart/element/element.dart'; import 'package:analyzer/dart/element/type.dart'; @@ -171,8 +172,9 @@ final Map<String, LibraryElement> _resynthesizedLibraries = <String, LibraryElement>{}; - SummaryResynthesizer(AnalysisContext context, this.sourceFactory, bool _) - : super(context) { + SummaryResynthesizer(AnalysisContext context, AnalysisSession session, + this.sourceFactory, bool _) + : super(context, session) { _buildTypeProvider(); } @@ -327,7 +329,7 @@ Source librarySource = _getSource(uri); if (serializedLibrary == null) { LibraryElementImpl libraryElement = - new LibraryElementImpl(context, '', -1, 0); + new LibraryElementImpl(context, session, '', -1, 0); libraryElement.isSynthetic = true; CompilationUnitElementImpl unitElement = new CompilationUnitElementImpl(); @@ -519,7 +521,7 @@ /// [UnitResynthesizerMixin] contains methods useful for implementing the /// [UnitResynthesizer] interface. -abstract class UnitResynthesizerMixin implements UnitResynthesizer { +mixin UnitResynthesizerMixin implements UnitResynthesizer { @override DartType createConstructorDefiningType(ElementImpl context, ReferenceInfo info, List<EntityRef> typeArgumentRefs) { @@ -579,6 +581,9 @@ @override ElementLocation get location => actualElement.location; + + @override + AnalysisSession get session => enclosingElement.session; } /// Specialization of [LibraryResynthesizer] for resynthesis from linked @@ -698,6 +703,7 @@ bool hasName = unlinkedUnits[0].libraryName.isNotEmpty; library = new LibraryElementImpl.forSerialized( summaryResynthesizer.context, + summaryResynthesizer.session, unlinkedUnits[0].libraryName, hasName ? unlinkedUnits[0].libraryNameOffset : -1, unlinkedUnits[0].libraryNameLength, @@ -1242,21 +1248,13 @@ if (constExpr == null) { // Invalid constant expression. } else if (constExpr is Identifier) { - var element = constExpr.staticElement; ArgumentList arguments = constExpr.getProperty(ExprBuilder.ARGUMENT_LIST); - if (element is PropertyAccessorElement && arguments == null) { - elementAnnotation.element = element; - elementAnnotation.annotationAst = AstTestFactory.annotation(constExpr); - } else if (element is ConstructorElement && arguments != null) { - elementAnnotation.element = element; - elementAnnotation.annotationAst = - AstTestFactory.annotation2(constExpr, null, arguments); - } else { - elementAnnotation.annotationAst = AstTestFactory.annotation( - AstTestFactory.identifier3(r'#invalidConst')); - } - } else if (constExpr is InstanceCreationExpression) { elementAnnotation.element = constExpr.staticElement; + elementAnnotation.annotationAst = + AstTestFactory.annotation2(constExpr, null, arguments); + } else if (constExpr is InstanceCreationExpression) { + var element = constExpr.staticElement; + elementAnnotation.element = element; Identifier typeName = constExpr.constructorName.type.name; SimpleIdentifier constructorName = constExpr.constructorName.name; if (typeName is SimpleIdentifier && constructorName != null) { @@ -1273,20 +1271,10 @@ var propertyName = constExpr.propertyName; var propertyElement = propertyName.staticElement; ArgumentList arguments = constExpr.getProperty(ExprBuilder.ARGUMENT_LIST); - if (propertyElement is PropertyAccessorElement && arguments == null) { - elementAnnotation.element = propertyElement; - elementAnnotation.annotationAst = - AstTestFactory.annotation2(target, propertyName, null) - ..element = propertyElement; - } else if (propertyElement is ConstructorElement && arguments != null) { - elementAnnotation.element = propertyElement; - elementAnnotation.annotationAst = - AstTestFactory.annotation2(target, propertyName, arguments) - ..element = propertyElement; - } else { - elementAnnotation.annotationAst = AstTestFactory.annotation( - AstTestFactory.identifier3(r'#invalidConst')); - } + elementAnnotation.element = propertyElement; + elementAnnotation.annotationAst = + AstTestFactory.annotation2(target, propertyName, arguments) + ..element = propertyElement; } else { throw new StateError( 'Unexpected annotation type: ${constExpr.runtimeType}');
diff --git a/pkg/analyzer/lib/src/summary/summarize_const_expr.dart b/pkg/analyzer/lib/src/summary/summarize_const_expr.dart index 6bb8870..3a1e036 100644 --- a/pkg/analyzer/lib/src/summary/summarize_const_expr.dart +++ b/pkg/analyzer/lib/src/summary/summarize_const_expr.dart
@@ -1,4 +1,4 @@ -// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file +// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. @@ -317,6 +317,8 @@ _serializeListLiteral(expr); } else if (expr is MapLiteral) { _serializeMapLiteral(expr); + } else if (expr is SetLiteral) { + _serializeSetLiteral(expr); } else if (expr is MethodInvocation) { _serializeMethodInvocation(expr); } else if (expr is BinaryExpression) { @@ -621,6 +623,23 @@ } } + void _serializeSetLiteral(SetLiteral expr) { + if (forConst || expr.typeArguments == null) { + List<Expression> elements = expr.elements; + elements.forEach(_serialize); + ints.add(elements.length); + } else { + ints.add(0); + } + if (expr.typeArguments != null && + expr.typeArguments.arguments.length == 1) { + references.add(serializeType(expr.typeArguments.arguments[0])); + operations.add(UnlinkedExprOperation.makeTypedSet); + } else { + operations.add(UnlinkedExprOperation.makeUntypedSet); + } + } + void _serializeString(StringLiteral expr) { if (expr is AdjacentStrings) { if (expr.strings.every((string) => string is SimpleStringLiteral)) {
diff --git a/pkg/analyzer/lib/src/summary/summarize_elements.dart b/pkg/analyzer/lib/src/summary/summarize_elements.dart index 9964703..ba4cc40 100644 --- a/pkg/analyzer/lib/src/summary/summarize_elements.dart +++ b/pkg/analyzer/lib/src/summary/summarize_elements.dart
@@ -26,7 +26,7 @@ * data that was previously not summarized), this value should be incremented * by 1. */ - static const int currentMinorVersion = 0; + static const int currentMinorVersion = 1; final List<String> _linkedLibraryUris = <String>[]; final List<LinkedLibraryBuilder> _linkedLibraries = <LinkedLibraryBuilder>[];
diff --git a/pkg/analyzer/lib/src/summary/summary_sdk.dart b/pkg/analyzer/lib/src/summary/summary_sdk.dart index 9fc486b..b60e627 100644 --- a/pkg/analyzer/lib/src/summary/summary_sdk.dart +++ b/pkg/analyzer/lib/src/summary/summary_sdk.dart
@@ -131,10 +131,13 @@ InterfaceType _iterableType; InterfaceType _listType; InterfaceType _mapType; + InterfaceType _mapNullNullType; DartObjectImpl _nullObject; InterfaceType _nullType; InterfaceType _numType; InterfaceType _objectType; + InterfaceType _setType; + InterfaceType _setNullType; InterfaceType _stackTraceType; InterfaceType _streamDynamicType; InterfaceType _streamType; @@ -247,6 +250,13 @@ } @override + InterfaceType get mapNullNullType { + assert(_coreLibrary != null); + return _mapNullNullType ??= + mapType.instantiate(<DartType>[nullType, nullType]); + } + + @override InterfaceType get mapType { assert(_coreLibrary != null); _mapType ??= _getType(_coreLibrary, "Map"); @@ -283,6 +293,18 @@ } @override + InterfaceType get setNullType { + assert(_coreLibrary != null); + return _setNullType ??= setType.instantiate(<DartType>[nullType]); + } + + @override + InterfaceType get setType { + assert(_coreLibrary != null); + return _setType ??= _getType(_coreLibrary, "Set"); + } + + @override InterfaceType get stackTraceType { assert(_coreLibrary != null); _stackTraceType ??= _getType(_coreLibrary, "StackTrace");
diff --git a/pkg/analyzer/lib/src/task/dart.dart b/pkg/analyzer/lib/src/task/dart.dart index 7e5c4bc..11d6dab 100644 --- a/pkg/analyzer/lib/src/task/dart.dart +++ b/pkg/analyzer/lib/src/task/dart.dart
@@ -1,4 +1,4 @@ -// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file +// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. @@ -1627,7 +1627,7 @@ // if (libraryElement == null) { libraryElement = - new LibraryElementImpl.forNode(owningContext, libraryNameNode); + new LibraryElementImpl.forNode(owningContext, null, libraryNameNode); libraryElement.isSynthetic = modificationTime < 0; libraryElement.definingCompilationUnit = definingCompilationUnitElement; libraryElement.entryPoint = entryPoint; @@ -3235,7 +3235,7 @@ "${variable.displayName} at $offset in $variableSource"); } VariableDeclaration declaration = - node.getAncestor((AstNode ancestor) => ancestor is VariableDeclaration); + node.thisOrAncestorOfType<VariableDeclaration>(); if (declaration == null || declaration.name != node) { Source variableSource = variable.source; Source unitSource = @@ -5452,8 +5452,7 @@ CodeChecker checker = new CodeChecker( typeProvider, new StrongTypeSystemImpl(typeProvider, - implicitCasts: options.implicitCasts, - declarationCasts: options.declarationCasts), + implicitCasts: options.implicitCasts), errorListener, options); checker.visitCompilationUnit(unit);
diff --git a/pkg/analyzer/lib/src/task/options.dart b/pkg/analyzer/lib/src/task/options.dart index c1c96b6..1032268 100644 --- a/pkg/analyzer/lib/src/task/options.dart +++ b/pkg/analyzer/lib/src/task/options.dart
@@ -1,12 +1,15 @@ -// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file +// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. import 'dart:collection'; -import 'package:analyzer/analyzer.dart'; +import 'package:analyzer/error/error.dart'; +import 'package:analyzer/error/listener.dart'; import 'package:analyzer/source/error_processor.dart'; import 'package:analyzer/src/analysis_options/analysis_options_provider.dart'; +import 'package:analyzer/src/analysis_options/error/option_codes.dart'; +import 'package:analyzer/src/dart/analysis/experiments.dart'; import 'package:analyzer/src/generated/engine.dart'; import 'package:analyzer/src/generated/java_engine.dart'; import 'package:analyzer/src/generated/source.dart'; @@ -42,6 +45,7 @@ static const String enableSuperMixins = 'enableSuperMixins'; static const String enablePreviewDart2 = 'enablePreviewDart2'; + static const String enableExperiment = 'enable-experiment'; static const String errors = 'errors'; static const String exclude = 'exclude'; static const String include = 'include'; @@ -69,6 +73,7 @@ /// Supported top-level `analyzer` options. static const List<String> topLevel = const [ + enableExperiment, errors, exclude, language, @@ -94,6 +99,7 @@ new TopLevelAnalyzerOptionsValidator(), new StrongModeOptionValueValidator(), new ErrorFilterOptionValidator(), + new EnabledExperimentsValidator(), new LanguageOptionValidator() ]); } @@ -109,6 +115,37 @@ validators.forEach((v) => v.validate(reporter, options)); } +/// Validates `analyzer` language configuration options. +class EnabledExperimentsValidator extends OptionsValidator { + ErrorBuilder builder = new ErrorBuilder(AnalyzerOptions.languageOptions); + ErrorBuilder trueOrFalseBuilder = new TrueOrFalseValueErrorBuilder(); + + @override + void validate(ErrorReporter reporter, YamlMap options) { + var analyzer = getValue(options, AnalyzerOptions.analyzer); + if (analyzer is YamlMap) { + var experimentNames = + getValue(analyzer, AnalyzerOptions.enableExperiment); + if (experimentNames is YamlList) { + for (var node in experimentNames.nodes) { + String experimentName = node.toString(); + if (!Experiments.activeExperimentNames.contains(experimentName)) { + reporter.reportErrorForSpan( + AnalysisOptionsWarningCode.UNSUPPORTED_OPTION_WITHOUT_VALUES, + node.span, + [experimentName, AnalyzerOptions.enableExperiment]); + } + } + } else if (experimentNames != null) { + reporter.reportErrorForSpan( + AnalysisOptionsWarningCode.INVALID_SECTION_FORMAT, + experimentNames.span, + [AnalyzerOptions.enableExperiment]); + } + } + } +} + /// Builds error reports with value proposals. class ErrorBuilder { String proposal; @@ -578,10 +615,24 @@ var strongMode = getValue(analyzer, AnalyzerOptions.strong_mode); _applyStrongOptions(options, strongMode); - // Set filters. + // Process filters. var filters = getValue(analyzer, AnalyzerOptions.errors); _applyProcessors(options, filters); + // Process enabled experiments. + var experimentNames = + getValue(analyzer, AnalyzerOptions.enableExperiment); + if (experimentNames is YamlList) { + List<String> enabledExperiments = <String>[]; + for (var element in experimentNames.nodes) { + String experimentName = _toString(element); + if (experimentName != null) { + enabledExperiments.add(experimentName); + } + } + options.enabledExperiments = enabledExperiments; + } + // Process language options. var language = getValue(analyzer, AnalyzerOptions.language); _applyLanguageOptions(options, language); @@ -661,9 +712,6 @@ AnalysisOptionsImpl options, String feature, Object value) { bool boolValue = toBool(value); if (boolValue != null) { - if (feature == AnalyzerOptions.declarationCasts) { - options.declarationCasts = boolValue; - } if (feature == AnalyzerOptions.implicitCasts) { options.implicitCasts = boolValue; }
diff --git a/pkg/analyzer/lib/src/task/strong/ast_properties.dart b/pkg/analyzer/lib/src/task/strong/ast_properties.dart index 7fd42485..d2fea4e 100644 --- a/pkg/analyzer/lib/src/task/strong/ast_properties.dart +++ b/pkg/analyzer/lib/src/task/strong/ast_properties.dart
@@ -1,4 +1,4 @@ -// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file +// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. @@ -6,17 +6,37 @@ /// /// These properties are not public, but provided by use of back-ends such as /// Dart Dev Compiler. -import 'package:analyzer/analyzer.dart'; +import 'package:analyzer/dart/ast/ast.dart'; import 'package:analyzer/dart/element/element.dart'; import 'package:analyzer/dart/element/type.dart'; -const String _hasImplicitCasts = '_hasImplicitCasts'; -const String _implicitOperationCast = '_implicitAssignmentCast'; -const String _implicitCast = '_implicitCast'; -const String _isDynamicInvoke = '_isDynamicInvoke'; const String _classCovariantParameters = '_classCovariantParameters'; -const String _superclassCovariantParameters = '_superclassCovariantParameters'; const String _covariantPrivateMembers = '_covariantPrivateMembers'; +const String _hasImplicitCasts = '_hasImplicitCasts'; +const String _implicitCast = '_implicitCast'; +const String _implicitOperationCast = '_implicitAssignmentCast'; +const String _isDynamicInvoke = '_isDynamicInvoke'; +const String _superclassCovariantParameters = '_superclassCovariantParameters'; + +/// Returns a list of parameters and method type parameters in this class +/// declaration that need a check at runtime to ensure soundness. +Set<Element> getClassCovariantParameters(Declaration node) { + return node.getProperty(_classCovariantParameters); +} + +/// Gets the private setters and methods that are accessed unsafely from +/// this compilation unit. +/// +/// These members will require a check. +Set<ExecutableElement> getCovariantPrivateMembers(CompilationUnit node) { + return node.getProperty(_covariantPrivateMembers); +} + +/// If this expression has an implicit cast, returns the type it is coerced to, +/// otherwise returns null. +DartType getImplicitCast(Expression node) { + return node.getProperty<DartType>(_implicitCast); +} /// If this expression needs an implicit cast on a subexpression that cannot be /// expressed anywhere else, returns the type it is coerced to. @@ -28,10 +48,11 @@ return node.getProperty<DartType>(_implicitOperationCast); } -/// If this expression has an implicit cast, returns the type it is coerced to, -/// otherwise returns null. -DartType getImplicitCast(Expression node) { - return node.getProperty<DartType>(_implicitCast); +/// Returns a list of parameters and method type parameters from mixins and +/// superclasses of this class that need a stub method to check their type at +/// runtime for soundness. +Set<Element> getSuperclassCovariantParameters(Declaration node) { + return node.getProperty(_superclassCovariantParameters); } /// True if this compilation unit has any implicit casts, otherwise false. @@ -47,59 +68,38 @@ return node.getProperty<bool>(_isDynamicInvoke) ?? false; } +/// Sets [getClassCovariantParameters] property for this class. +void setClassCovariantParameters(Declaration node, Set<Element> value) { + node.setProperty(_classCovariantParameters, value); +} + +/// Sets [getCovariantPrivateMembers] property for this compilation unit. +void setCovariantPrivateMembers( + CompilationUnit node, Set<ExecutableElement> value) { + node.setProperty(_covariantPrivateMembers, value); +} + /// Sets [hasImplicitCasts] property for this compilation unit. void setHasImplicitCasts(CompilationUnit node, bool value) { node.setProperty(_hasImplicitCasts, value == true ? true : null); } -/// Sets the result of [getImplicitOperationCast] for this node. -void setImplicitOperationCast(Expression node, DartType type) { - node.setProperty(_implicitOperationCast, type); -} - /// Sets the result of [getImplicitCast] for this node. void setImplicitCast(Expression node, DartType type) { node.setProperty(_implicitCast, type); } +/// Sets the result of [getImplicitOperationCast] for this node. +void setImplicitOperationCast(Expression node, DartType type) { + node.setProperty(_implicitOperationCast, type); +} + /// Sets [isDynamicInvoke] property for this expression. void setIsDynamicInvoke(Expression node, bool value) { node.setProperty(_isDynamicInvoke, value == true ? true : null); } -/// Returns a list of parameters and method type parameters in this class -/// declaration that need a check at runtime to ensure soundness. -Set<Element> getClassCovariantParameters(Declaration node) { - return node.getProperty(_classCovariantParameters); -} - -/// Sets [getClassCovariantParameters] property for this class. -void setClassCovariantParameters(Declaration node, Set<Element> value) { - node.setProperty(_classCovariantParameters, value); -} - -/// Returns a list of parameters and method type parameters from mixins and -/// superclasses of this class that need a stub method to check their type at -/// runtime for soundness. -Set<Element> getSuperclassCovariantParameters(Declaration node) { - return node.getProperty(_superclassCovariantParameters); -} - /// Sets [getSuperclassCovariantParameters] property for this class. void setSuperclassCovariantParameters(Declaration node, Set<Element> value) { node.setProperty(_superclassCovariantParameters, value); } - -/// Gets the private setters and methods that are accessed unsafely from -/// this compilation unit. -/// -/// These members will require a check. -Set<ExecutableElement> getCovariantPrivateMembers(CompilationUnit node) { - return node.getProperty(_covariantPrivateMembers); -} - -/// Sets [getCovariantPrivateMembers] property for this compilation unit. -void setCovariantPrivateMembers( - CompilationUnit node, Set<ExecutableElement> value) { - node.setProperty(_covariantPrivateMembers, value); -}
diff --git a/pkg/analyzer/lib/src/task/strong/checker.dart b/pkg/analyzer/lib/src/task/strong/checker.dart index a830600..6dce6f6 100644 --- a/pkg/analyzer/lib/src/task/strong/checker.dart +++ b/pkg/analyzer/lib/src/task/strong/checker.dart
@@ -6,7 +6,6 @@ // refactored to fit into analyzer. import 'dart:collection'; -import 'package:analyzer/analyzer.dart'; import 'package:analyzer/dart/ast/ast.dart'; import 'package:analyzer/dart/ast/standard_resolution_map.dart'; import 'package:analyzer/dart/ast/token.dart' show TokenType; @@ -14,6 +13,8 @@ import 'package:analyzer/dart/ast/visitor.dart'; import 'package:analyzer/dart/element/element.dart'; import 'package:analyzer/dart/element/type.dart'; +import 'package:analyzer/error/error.dart'; +import 'package:analyzer/error/listener.dart'; import 'package:analyzer/source/error_processor.dart' show ErrorProcessor; import 'package:analyzer/src/dart/element/element.dart'; import 'package:analyzer/src/dart/element/member.dart'; @@ -156,34 +157,17 @@ checkForCast(expr, type); } - void checkDeclarationCast(Expression expr, DartType type) { - checkForCast(expr, type, isDeclarationCast: true); - } - - void checkForCast(Expression expr, DartType type, - {bool isDeclarationCast = false}) { - if (expr is ParenthesizedExpression) { - checkForCast(expr.expression, type); - } else { - _checkImplicitCast(expr, type, isDeclarationCast: isDeclarationCast); - } - } - /// Analyzer checks boolean conversions, but we need to check too, because /// it uses the default assignability rules that allow `dynamic` and `Object` /// to be assigned to bool with no message. void checkBoolean(Expression expr) => checkAssignment(expr, typeProvider.boolType); - void _checkFunctionApplication(InvocationExpression node) { - var ft = _getTypeAsCaller(node); - - if (_isDynamicCall(node, ft)) { - // If f is Function and this is a method invocation, we should have - // gotten an analyzer error, so no need to issue another error. - _recordDynamicInvoke(node, node.function); + void checkForCast(Expression expr, DartType type) { + if (expr is ParenthesizedExpression) { + checkForCast(expr.expression, type); } else { - checkArgumentList(node.argumentList, ft); + _checkImplicitCast(expr, type); } } @@ -305,7 +289,6 @@ } } - // Check invocations @override void visitConstructorFieldInitializer(ConstructorFieldInitializer node) { var field = node.fieldName; @@ -315,6 +298,7 @@ node.visitChildren(this); } + // Check invocations @override void visitDefaultFormalParameter(DefaultFormalParameter node) { // Check that defaults have the proper subtype. @@ -391,7 +375,7 @@ // Insert a cast from the sequence's element type to the loop variable's // if needed. _checkImplicitCast(loopVariable, _getExpressionType(loopVariable), - from: elementType, isDeclarationCast: true); + from: elementType); } } @@ -517,7 +501,9 @@ visitMethodInvocation(MethodInvocation node) { var target = node.realTarget; var element = node.methodName.staticElement; - if (element == null && !typeProvider.isObjectMethod(node.methodName.name)) { + if (element == null && + !typeProvider.isObjectMethod(node.methodName.name) && + node.methodName.name != FunctionElement.CALL_METHOD_NAME) { _recordDynamicInvoke(node, target); // Mark the tear-off as being dynamic, too. This lets us distinguish @@ -630,11 +616,11 @@ void visitVariableDeclarationList(VariableDeclarationList node) { TypeAnnotation type = node.type; - for (VariableDeclaration variable in node.variables) { - var initializer = variable.initializer; - if (initializer != null) { - if (type != null) { - checkDeclarationCast(initializer, type.type); + if (type != null) { + for (VariableDeclaration variable in node.variables) { + var initializer = variable.initializer; + if (initializer != null) { + checkForCast(initializer, type.type); } } } @@ -702,6 +688,49 @@ node.visitChildren(this); } + void _checkFunctionApplication(InvocationExpression node) { + var ft = _getTypeAsCaller(node); + + if (_isDynamicCall(node, ft)) { + // If f is Function and this is a method invocation, we should have + // gotten an analyzer error, so no need to issue another error. + _recordDynamicInvoke(node, node.function); + } else { + checkArgumentList(node.argumentList, ft); + } + } + + /// Given an expression [expr] of type [fromType], returns true if an implicit + /// downcast is required, false if it is not, or null if the types are + /// unrelated. + bool _checkFunctionTypeCasts( + Expression expr, FunctionType to, DartType fromType) { + bool callTearoff = false; + FunctionType from; + if (fromType is FunctionType) { + from = fromType; + } else if (fromType is InterfaceType) { + from = rules.getCallMethodType(fromType); + callTearoff = true; + } + if (from == null) { + return null; // unrelated + } + + if (rules.isSubtypeOf(from, to)) { + // Sound subtype. + // However we may still need cast if we have a call tearoff. + return callTearoff; + } + + if (rules.isSubtypeOf(to, from)) { + // Assignable, but needs cast. + return true; + } + + return null; + } + /// Checks if an implicit cast of [expr] from [from] type to [to] type is /// needed, and if so records it. /// @@ -710,76 +739,14 @@ /// If [expr] does not require an implicit cast because it is not related to /// [to] or is already a subtype of it, does nothing. void _checkImplicitCast(Expression expr, DartType to, - {DartType from, bool opAssign: false, bool isDeclarationCast: false}) { + {DartType from, bool opAssign: false}) { from ??= _getExpressionType(expr); - if (_needsImplicitCast(expr, to, - from: from, isDeclarationCast: isDeclarationCast) == - true) { + if (_needsImplicitCast(expr, to, from: from) == true) { _recordImplicitCast(expr, to, from: from, opAssign: opAssign); } } - void _checkReturnOrYield(Expression expression, AstNode node, - {bool yieldStar: false}) { - FunctionBody body = node.getAncestor((n) => n is FunctionBody); - var type = _getExpectedReturnType(body, yieldStar: yieldStar); - if (type == null) { - // We have a type mismatch: the async/async*/sync* modifier does - // not match the return or yield type. We should have already gotten an - // analyzer error in this case. - return; - } - // TODO(vsm): Enforce void or dynamic (to void?) when expression is null. - if (expression != null) checkAssignment(expression, type); - } - - void _checkRuntimeTypeCheck(AstNode node, TypeAnnotation annotation) { - var type = getAnnotatedType(annotation); - if (!rules.isGroundType(type)) { - _recordMessage(node, StrongModeCode.NON_GROUND_TYPE_CHECK_INFO, [type]); - } - } - - void _checkUnary(Expression operand, Token op, MethodElement element) { - bool isIncrementAssign = - op.type == TokenType.PLUS_PLUS || op.type == TokenType.MINUS_MINUS; - if (op.isUserDefinableOperator || isIncrementAssign) { - if (element == null) { - _recordDynamicInvoke(operand.parent, operand); - } else if (isIncrementAssign) { - // For ++ and --, even if it is not dynamic, we still need to check - // that the user defined method accepts an `int` as the RHS. - // - // We assume Analyzer has done this already (in ErrorVerifier). - // - // However, we also need to check the return type. - - // Refine the return type. - var functionType = element.type; - var rhsType = typeProvider.intType; - var lhsType = _getExpressionType(operand); - var returnType = rules.refineBinaryExpressionType( - lhsType, TokenType.PLUS, rhsType, functionType.returnType); - - // Skip the argument check - `int` cannot be downcast. - // - // Check the return type for an implicit cast. - // - // If needed, mark the assignment to indicate a down cast when we assign - // back to it. So these two implicit casts are equivalent: - // - // y = /*implicit cast*/(y + 1); - // /*implicit assignment cast*/y++; - // - _checkImplicitCast(operand, lhsType, from: returnType, opAssign: true); - } - } - } - - DartType _getExpressionType(Expression expr) => - getExpressionType(expr, rules, typeProvider); - /// If we're calling into [member] through the [target], we may need to /// insert a caller side check for soundness on the result of the expression /// [node]. @@ -862,57 +829,61 @@ } } - /// Returns true if we can safely skip the covariance checks because [target] - /// has known type arguments, such as `this` `super` or a non-factory `new`. - /// - /// For example: - /// - /// class C<T> { - /// T _t; - /// } - /// class D<T> extends C<T> { - /// method<S extends T>(T t, C<T> c) { - /// // implicit cast: t as T; - /// // implicit cast: c as C<T>; - /// - /// // These do not need further checks. The type parameter `T` for - /// // `this` must be the same as our `T` - /// this._t = t; - /// super._t = t; - /// new C<T>()._t = t; // non-factory - /// - /// // This needs further checks. The type of `c` could be `C<S>` for - /// // some `S <: T`. - /// c._t = t; - /// // factory statically returns `C<T>`, dynamically returns `C<S>`. - /// new F<T, S>()._t = t; - /// } - /// } - /// class F<T, S extends T> extends C<T> { - /// factory F() => new C<S>(); - /// } - /// - bool _targetHasKnownGenericTypeArguments(Expression target) { - return target == null || // implicit this - target is ThisExpression || - target is SuperExpression || - target is InstanceCreationExpression && - target.staticElement?.isFactory == false; + void _checkReturnOrYield(Expression expression, AstNode node, + {bool yieldStar: false}) { + FunctionBody body = node.thisOrAncestorOfType<FunctionBody>(); + var type = _getExpectedReturnType(body, yieldStar: yieldStar); + if (type == null) { + // We have a type mismatch: the async/async*/sync* modifier does + // not match the return or yield type. We should have already gotten an + // analyzer error in this case. + return; + } + // TODO(vsm): Enforce void or dynamic (to void?) when expression is null. + if (expression != null) checkAssignment(expression, type); } - bool _isInstanceMember(ExecutableElement e) => - !e.isStatic && - (e is MethodElement || - e is PropertyAccessorElement && e.variable is FieldElement); + void _checkRuntimeTypeCheck(AstNode node, TypeAnnotation annotation) { + var type = getAnnotatedType(annotation); + if (!rules.isGroundType(type)) { + _recordMessage(node, StrongModeCode.NON_GROUND_TYPE_CHECK_INFO, [type]); + } + } - ExecutableElement _lookUpMember(InterfaceType type, ExecutableElement e) { - var name = e.name; - var library = e.library; - return e is PropertyAccessorElement - ? (e.isGetter - ? type.lookUpInheritedGetter(name, library: library) - : type.lookUpInheritedSetter(name, library: library)) - : type.lookUpInheritedMethod(name, library: library); + void _checkUnary(Expression operand, Token op, MethodElement element) { + bool isIncrementAssign = + op.type == TokenType.PLUS_PLUS || op.type == TokenType.MINUS_MINUS; + if (op.isUserDefinableOperator || isIncrementAssign) { + if (element == null) { + _recordDynamicInvoke(operand.parent, operand); + } else if (isIncrementAssign) { + // For ++ and --, even if it is not dynamic, we still need to check + // that the user defined method accepts an `int` as the RHS. + // + // We assume Analyzer has done this already (in ErrorVerifier). + // + // However, we also need to check the return type. + + // Refine the return type. + var functionType = element.type; + var rhsType = typeProvider.intType; + var lhsType = _getExpressionType(operand); + var returnType = rules.refineBinaryExpressionType( + lhsType, TokenType.PLUS, rhsType, functionType.returnType); + + // Skip the argument check - `int` cannot be downcast. + // + // Check the return type for an implicit cast. + // + // If needed, mark the assignment to indicate a down cast when we assign + // back to it. So these two implicit casts are equivalent: + // + // y = /*implicit cast*/(y + 1); + // /*implicit assignment cast*/y++; + // + _checkImplicitCast(operand, lhsType, from: returnType, opAssign: true); + } + } } /// Gets the expected return type of the given function [body], either from @@ -971,6 +942,9 @@ } } + DartType _getExpressionType(Expression expr) => + getExpressionType(expr, rules, typeProvider); + /// Given an expression, return its type assuming it is /// in the caller position of a call (that is, accounting /// for the possibility of a call method). Returns null @@ -991,35 +965,28 @@ return ft == null; } - /// Given an expression [expr] of type [fromType], returns true if an implicit - /// downcast is required, false if it is not, or null if the types are - /// unrelated. - bool _checkFunctionTypeCasts( - Expression expr, FunctionType to, DartType fromType) { - bool callTearoff = false; - FunctionType from; - if (fromType is FunctionType) { - from = fromType; - } else if (fromType is InterfaceType) { - from = rules.getCallMethodType(fromType); - callTearoff = true; - } - if (from == null) { - return null; // unrelated - } + bool _isInstanceMember(ExecutableElement e) => + !e.isStatic && + (e is MethodElement || + e is PropertyAccessorElement && e.variable is FieldElement); - if (rules.isSubtypeOf(from, to)) { - // Sound subtype. - // However we may still need cast if we have a call tearoff. - return callTearoff; - } + ExecutableElement _lookUpMember(InterfaceType type, ExecutableElement e) { + var name = e.name; + var library = e.library; + return e is PropertyAccessorElement + ? (e.isGetter + ? type.lookUpInheritedGetter(name, library: library) + : type.lookUpInheritedSetter(name, library: library)) + : type.lookUpInheritedMethod(name, library: library); + } - if (rules.isSubtypeOf(to, from)) { - // Assignable, but needs cast. - return true; + void _markImplicitCast(Expression expr, DartType to, {bool opAssign: false}) { + if (opAssign) { + setImplicitOperationCast(expr, to); + } else { + setImplicitCast(expr, to); } - - return null; + _hasImplicitCasts = true; } /// Returns true if we need an implicit cast of [expr] from [from] type to @@ -1029,8 +996,7 @@ /// downcast implicitly). /// /// If [from] is omitted, uses the static type of [expr] - bool _needsImplicitCast(Expression expr, DartType to, - {DartType from, bool isDeclarationCast: false}) { + bool _needsImplicitCast(Expression expr, DartType to, {DartType from}) { from ??= _getExpressionType(expr); // Void is considered Top, but may only be *explicitly* cast. @@ -1047,7 +1013,7 @@ } // Down cast or legal sideways cast, coercion needed. - if (rules.isAssignableTo(from, to, isDeclarationCast: isDeclarationCast)) { + if (rules.isAssignableTo(from, to)) { return true; } @@ -1074,15 +1040,6 @@ if (target != null) setIsDynamicInvoke(target, true); } - void _markImplicitCast(Expression expr, DartType to, {bool opAssign: false}) { - if (opAssign) { - setImplicitOperationCast(expr, to); - } else { - setImplicitCast(expr, to); - } - _hasImplicitCasts = true; - } - /// Records an implicit cast for the [expr] from [from] to [to]. /// /// This will emit the appropriate error/warning/hint message as well as mark @@ -1109,6 +1066,9 @@ } else if (expr is MapLiteral) { _recordMessage( expr, StrongModeCode.INVALID_CAST_LITERAL_MAP, [from, to]); + } else if (expr is SetLiteral) { + _recordMessage( + expr, StrongModeCode.INVALID_CAST_LITERAL_SET, [from, to]); } else { _recordMessage( expr, StrongModeCode.INVALID_CAST_LITERAL, [expr, from, to]); @@ -1207,6 +1167,44 @@ } } + /// Returns true if we can safely skip the covariance checks because [target] + /// has known type arguments, such as `this` `super` or a non-factory `new`. + /// + /// For example: + /// + /// class C<T> { + /// T _t; + /// } + /// class D<T> extends C<T> { + /// method<S extends T>(T t, C<T> c) { + /// // implicit cast: t as T; + /// // implicit cast: c as C<T>; + /// + /// // These do not need further checks. The type parameter `T` for + /// // `this` must be the same as our `T` + /// this._t = t; + /// super._t = t; + /// new C<T>()._t = t; // non-factory + /// + /// // This needs further checks. The type of `c` could be `C<S>` for + /// // some `S <: T`. + /// c._t = t; + /// // factory statically returns `C<T>`, dynamically returns `C<S>`. + /// new F<T, S>()._t = t; + /// } + /// } + /// class F<T, S extends T> extends C<T> { + /// factory F() => new C<S>(); + /// } + /// + bool _targetHasKnownGenericTypeArguments(Expression target) { + return target == null || // implicit this + target is ThisExpression || + target is SuperExpression || + target is InstanceCreationExpression && + target.staticElement?.isFactory == false; + } + void _validateTopLevelInitializer(String name, Expression n) { n.accept(new _TopLevelInitializerValidator(this, name)); } @@ -1229,6 +1227,36 @@ _checkForCovariantGenerics(node, element); } + /// Visits each member on the class [node] and calls [checkMember] with the + /// corresponding instance element and AST node (for error reporting). + /// + /// See also [_checkTypeMembers], which is used when the class AST node is not + /// available. + void _checkClassMembers(Declaration node, + void checkMember(ExecutableElement member, ClassMember location)) { + for (var member in _classMembers(node)) { + if (member is FieldDeclaration) { + if (member.isStatic) { + continue; + } + for (var variable in member.fields.variables) { + var element = variable.declaredElement as PropertyInducingElement; + checkMember(element.getter, member); + if (!variable.isFinal && !variable.isConst) { + checkMember(element.setter, member); + } + } + } else if (member is MethodDeclaration) { + if (member.isStatic) { + continue; + } + checkMember(member.declaredElement, member); + } else { + assert(member is ConstructorDeclaration); + } + } + } + /// Finds implicit casts that we need on parameters and type formals to /// ensure soundness of covariant generics, and records them on the [node]. /// @@ -1273,86 +1301,24 @@ setSuperclassCovariantParameters(node, checks); } - /// For each member of this class and non-overridden inherited member, we - /// check to see if any generic super interface permits an unsound call to the - /// concrete member. For example: + /// Visits the [type] and calls [checkMember] for each instance member. /// - /// We must check non-overridden inherited members because this class could - /// contain a new interface that permits unsound access to that member. In - /// those cases, the class is expected to insert stub that checks the type - /// before calling `super`. For example: - /// - /// class C<T> { - /// add(T t) {} - /// } - /// class D { - /// add(int t) {} - /// } - /// class E extends D implements C<int> { - /// // C<Object>.add is unsafe, and D.m is marked for a check. - /// // - /// // one way to implement this is to generate a stub method: - /// // add(t) => super.add(t as int); - /// } - /// - Set<Element> _findSuperclassCovariantChecks(ClassElement element, - Set<ClassElement> allCovariant, HashSet<String> seenConcreteMembers) { - var visited = new HashSet<ClassElement>()..add(element); - var superChecks = _createCovariantCheckSet(); - var existingChecks = _createCovariantCheckSet(); - - void visitImmediateSuper(InterfaceType type) { - // For members of mixins/supertypes, check them against new interfaces, - // and also record any existing checks they already had. - var oldCovariant = _findAllGenericInterfaces(type); - var newCovariant = allCovariant.difference(oldCovariant); - if (newCovariant.isEmpty) return; - - void visitSuper(InterfaceType type) { - var element = type.element; - if (visited.add(element)) { - var members = _getConcreteMembers(type, seenConcreteMembers); - _findCovariantChecks(members, newCovariant, superChecks); - _findCovariantChecks(members, oldCovariant, existingChecks); - element.mixins.reversed.forEach(visitSuper); - var s = element.supertype; - if (s != null) visitSuper(s); - } - } - - visitSuper(type); + /// See also [_checkClassMembers], which should be used when the class AST + /// node is available to allow for better error locations + void _checkTypeMembers( + InterfaceType type, void checkMember(ExecutableElement member)) { + void checkHelper(ExecutableElement e) { + if (!e.isStatic) checkMember(e); } - element.mixins.reversed.forEach(visitImmediateSuper); - var s = element.supertype; - if (s != null) visitImmediateSuper(s); - - superChecks.removeAll(existingChecks); - return superChecks; + type.methods.forEach(checkHelper); + type.accessors.forEach(checkHelper); } - /// Gets all concrete instance members declared on this type, skipping already - /// [seenConcreteMembers] and adding any found ones to it. - /// - /// By tracking the set of seen members, we can visit superclasses and mixins - /// and ultimately collect every most-derived member exposed by a given type. - static List<ExecutableElement> _getConcreteMembers( - InterfaceType type, HashSet<String> seenConcreteMembers) { - var members = <ExecutableElement>[]; - for (var declaredMembers in [type.accessors, type.methods]) { - for (var member in declaredMembers) { - // We only visit each most derived concrete member. - // To avoid visiting an overridden superclass member, we skip members - // we've seen, and visit starting from the class, then mixins in - // reverse order, then superclasses. - if (!member.isStatic && - !member.isAbstract && - seenConcreteMembers.add(member.name)) { - members.add(member); - } - } - } - return members; + /// If node is a [ClassDeclaration] returns its members, otherwise if node is + /// a [ClassTypeAlias] this returns an empty list. + Iterable<ClassMember> _classMembers(Declaration node) { + return node is ClassDeclaration ? node.members : []; } /// Find all covariance checks on parameters/type parameters needed for @@ -1453,6 +1419,64 @@ }); } + /// For each member of this class and non-overridden inherited member, we + /// check to see if any generic super interface permits an unsound call to the + /// concrete member. For example: + /// + /// We must check non-overridden inherited members because this class could + /// contain a new interface that permits unsound access to that member. In + /// those cases, the class is expected to insert stub that checks the type + /// before calling `super`. For example: + /// + /// class C<T> { + /// add(T t) {} + /// } + /// class D { + /// add(int t) {} + /// } + /// class E extends D implements C<int> { + /// // C<Object>.add is unsafe, and D.m is marked for a check. + /// // + /// // one way to implement this is to generate a stub method: + /// // add(t) => super.add(t as int); + /// } + /// + Set<Element> _findSuperclassCovariantChecks(ClassElement element, + Set<ClassElement> allCovariant, HashSet<String> seenConcreteMembers) { + var visited = new HashSet<ClassElement>()..add(element); + var superChecks = _createCovariantCheckSet(); + var existingChecks = _createCovariantCheckSet(); + + void visitImmediateSuper(InterfaceType type) { + // For members of mixins/supertypes, check them against new interfaces, + // and also record any existing checks they already had. + var oldCovariant = _findAllGenericInterfaces(type); + var newCovariant = allCovariant.difference(oldCovariant); + if (newCovariant.isEmpty) return; + + void visitSuper(InterfaceType type) { + var element = type.element; + if (visited.add(element)) { + var members = _getConcreteMembers(type, seenConcreteMembers); + _findCovariantChecks(members, newCovariant, superChecks); + _findCovariantChecks(members, oldCovariant, existingChecks); + element.mixins.reversed.forEach(visitSuper); + var s = element.supertype; + if (s != null) visitSuper(s); + } + } + + visitSuper(type); + } + + element.mixins.reversed.forEach(visitImmediateSuper); + var s = element.supertype; + if (s != null) visitImmediateSuper(s); + + superChecks.removeAll(existingChecks); + return superChecks; + } + static Set<Element> _createCovariantCheckSet() { return new LinkedHashSet( equals: _equalMemberElements, hashCode: _hashCodeMemberElements); @@ -1468,11 +1492,6 @@ return x == y; } - static int _hashCodeMemberElements(Element x) { - x = x is Member ? x.baseElement : x; - return x.hashCode; - } - /// Find all generic interfaces that are implemented by [type], including /// [type] itself if it is generic. /// @@ -1503,54 +1522,33 @@ return genericSupertypes; } - /// Visits each member on the class [node] and calls [checkMember] with the - /// corresponding instance element and AST node (for error reporting). + /// Gets all concrete instance members declared on this type, skipping already + /// [seenConcreteMembers] and adding any found ones to it. /// - /// See also [_checkTypeMembers], which is used when the class AST node is not - /// available. - void _checkClassMembers(Declaration node, - void checkMember(ExecutableElement member, ClassMember location)) { - for (var member in _classMembers(node)) { - if (member is FieldDeclaration) { - if (member.isStatic) { - continue; + /// By tracking the set of seen members, we can visit superclasses and mixins + /// and ultimately collect every most-derived member exposed by a given type. + static List<ExecutableElement> _getConcreteMembers( + InterfaceType type, HashSet<String> seenConcreteMembers) { + var members = <ExecutableElement>[]; + for (var declaredMembers in [type.accessors, type.methods]) { + for (var member in declaredMembers) { + // We only visit each most derived concrete member. + // To avoid visiting an overridden superclass member, we skip members + // we've seen, and visit starting from the class, then mixins in + // reverse order, then superclasses. + if (!member.isStatic && + !member.isAbstract && + seenConcreteMembers.add(member.name)) { + members.add(member); } - for (var variable in member.fields.variables) { - var element = variable.declaredElement as PropertyInducingElement; - checkMember(element.getter, member); - if (!variable.isFinal && !variable.isConst) { - checkMember(element.setter, member); - } - } - } else if (member is MethodDeclaration) { - if (member.isStatic) { - continue; - } - checkMember(member.declaredElement, member); - } else { - assert(member is ConstructorDeclaration); } } + return members; } - /// Visits the [type] and calls [checkMember] for each instance member. - /// - /// See also [_checkClassMembers], which should be used when the class AST - /// node is available to allow for better error locations - void _checkTypeMembers( - InterfaceType type, void checkMember(ExecutableElement member)) { - void checkHelper(ExecutableElement e) { - if (!e.isStatic) checkMember(e); - } - - type.methods.forEach(checkHelper); - type.accessors.forEach(checkHelper); - } - - /// If node is a [ClassDeclaration] returns its members, otherwise if node is - /// a [ClassTypeAlias] this returns an empty list. - Iterable<ClassMember> _classMembers(Declaration node) { - return node is ClassDeclaration ? node.members : []; + static int _hashCodeMemberElements(Element x) { + x = x is Member ? x.baseElement : x; + return x.hashCode; } }
diff --git a/pkg/analyzer_plugin/test/support/mock_sdk.dart b/pkg/analyzer/lib/src/test_utilities/mock_sdk.dart similarity index 82% rename from pkg/analyzer_plugin/test/support/mock_sdk.dart rename to pkg/analyzer/lib/src/test_utilities/mock_sdk.dart index f76516c4..b48d3c49 100644 --- a/pkg/analyzer_plugin/test/support/mock_sdk.dart +++ b/pkg/analyzer/lib/src/test_utilities/mock_sdk.dart
@@ -1,9 +1,9 @@ -// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. -import 'package:analyzer/file_system/file_system.dart' as resource; -import 'package:analyzer/file_system/memory_file_system.dart' as resource; +import 'package:analyzer/file_system/file_system.dart'; +import 'package:analyzer/file_system/memory_file_system.dart'; import 'package:analyzer/src/context/cache.dart'; import 'package:analyzer/src/context/context.dart'; import 'package:analyzer/src/generated/engine.dart' show AnalysisEngine; @@ -11,6 +11,7 @@ import 'package:analyzer/src/generated/source.dart'; import 'package:analyzer/src/summary/idl.dart' show PackageBundle; import 'package:analyzer/src/summary/summary_file_builder.dart'; +import 'package:meta/meta.dart'; const String librariesContent = r''' const Map<String, LibraryInfo> libraries = const { @@ -42,11 +43,10 @@ factory Future.microtask(FutureOr<T> computation()) => null; factory Future.value([FutureOr<T> result]) => null; - static Future<List<T>> wait<T>( - Iterable<Future<T>> futures) => null; Future<R> then<R>(FutureOr<R> onValue(T value)) => null; - Future<T> whenComplete(action()); + + static Future<List<T>> wait<T>(Iterable<Future<T>> futures) => null; } class FutureOr<T> {} @@ -60,12 +60,9 @@ bool get isCompleted; } -class _StreamIterator<T> implements StreamIterator<T> {} -class _AsyncStarStreamController {} -Function _asyncThenWrapperHelper(continuation) {} -Function _asyncErrorWrapperHelper(continuation) {} -Future _awaitHelper( - object, Function thenCallback, Function errorCallback, var awaiter) {} +abstract class Timer { + static void run(void callback()) {} +} ''', const <String, String>{ '$sdkRoot/lib/async/stream.dart': r''' part of dart.async; @@ -108,6 +105,7 @@ library dart.collection; abstract class HashMap<K, V> implements Map<K, V> {} +abstract class LinkedHashMap<K, V> implements Map<K, V> {} '''); const _MockSdkLibrary _LIB_CONVERT = const _MockSdkLibrary( @@ -124,104 +122,34 @@ const _MockSdkLibrary('dart:core', '$sdkRoot/lib/core/core.dart', ''' library dart.core; -import 'dart:async'; -import 'dart:_internal'; +import 'dart:async'; // ignore: unused_import -class Object { - const Object(); - bool operator ==(other) => identical(this, other); - String toString() => 'a string'; - int get hashCode => 0; - Type get runtimeType => null; - dynamic noSuchMethod(Invocation invocation) => null; +export 'dart:async' show Future, Stream; + +const deprecated = const Deprecated("next release"); + +const override = const _Override(); + +const proxy = const _Proxy(); + +external bool identical(Object a, Object b); + +void print(Object object) {} + +class bool extends Object { + external const factory bool.fromEnvironment(String name, + {bool defaultValue: false}); } -class Function {} -class StackTrace {} - -class Symbol { - const factory Symbol(String name) = _SymbolImpl; -} - -class _SymbolImpl { - const _SymbolImpl(String name); -} - -class Type {} - abstract class Comparable<T> { int compareTo(T other); } -abstract class Pattern {} -abstract class String implements Comparable<String>, Pattern { - external factory String.fromCharCodes(Iterable<int> charCodes, - [int start = 0, int end]); - String operator +(String other) => null; - bool operator ==(Object other); - bool get isEmpty => false; - bool get isNotEmpty => false; - int get length => 0; - int codeUnitAt(int index); - String substring(int len) => null; - String toLowerCase(); - String toUpperCase(); - List<int> get codeUnits; -} -abstract class RegExp implements Pattern { - external factory RegExp(String source); -} +class DateTime extends Object {} -class bool extends Object { - external const factory bool.fromEnvironment(String name, - {bool defaultValue: false}); -} - -abstract class Invocation {} - -abstract class num implements Comparable<num> { - bool operator ==(Object other); - bool operator <(num other); - bool operator <=(num other); - bool operator >(num other); - bool operator >=(num other); - num operator +(num other); - num operator -(num other); - num operator *(num other); - double operator /(num other); - int operator ^(int other); - int operator |(int other); - int operator <<(int other); - int operator >>(int other); - int operator ~/(num other); - num operator %(num other); - int operator ~(); - num operator -(); - int toInt(); - double toDouble(); - num abs(); - int round(); -} -abstract class int extends num { - external const factory int.fromEnvironment(String name, {int defaultValue}); - - bool get isNegative; - bool get isEven => false; - - int operator &(int other); - int operator |(int other); - int operator ^(int other); - int operator ~(); - int operator <<(int shiftAmount); - int operator >>(int shiftAmount); - - int operator -(); - - external static int parse(String source, - { int radix, - int onError(String source) }); - - String toString(); +class Deprecated extends Object { + final String expires; + const Deprecated(this.expires); } abstract class double extends num { @@ -231,89 +159,25 @@ static const double MIN_POSITIVE = 5e-324; static const double MAX_FINITE = 1.7976931348623157e+308; - double remainder(num other); + double get sign; + double operator %(num other); + double operator *(num other); double operator +(num other); double operator -(num other); - double operator *(num other); - double operator %(num other); - double operator /(num other); - int operator ~/(num other); double operator -(); + double operator /(num other); double abs(); - double get sign; - int round(); - int floor(); int ceil(); - int truncate(); - double roundToDouble(); - double floorToDouble(); double ceilToDouble(); + int floor(); + double floorToDouble(); + double remainder(num other); + int round(); + double roundToDouble(); + int truncate(); double truncateToDouble(); - external static double parse(String source, - [double onError(String source)]); -} - -class DateTime extends Object {} - -class Null extends Object { - factory Null._uninstantiable() => null; -} - -class Deprecated extends Object { - final String expires; - const Deprecated(this.expires); -} -const Object deprecated = const Deprecated("next release"); - -class Iterator<E> { - bool moveNext(); - E get current; -} - -abstract class Iterable<E> { - Iterator<E> get iterator; - bool get isEmpty; - E get first; - int get length; - - Iterable<R> map<R>(R f(E e)); - - R fold<R>(R initialValue, - R combine(R previousValue, E element)) => null; - - Iterable<T> expand<T>(Iterable<T> f(E element)); - - Iterable<E> where(bool test(E element)); - - void forEach(void f(E element)); - - List<E> toList(); -} - -class List<E> implements Iterable<E> { - List([int length]); - factory List.from(Iterable elements, {bool growable: true}) => null; - void add(E value) {} - void addAll(Iterable<E> iterable) {} - E operator [](int index) => null; - void operator []=(int index, E value) {} - Iterator<E> get iterator => null; - void clear() {} - - bool get isEmpty => false; - E get first => null; - E get last => null; - -} - -class Map<K, V> extends Object { - Iterable<K> get keys => null; - int get length; - Iterable<V> get values; - V operator [](K key) => null; - void operator []=(K key, V value) {} - Map<RK, RV> cast<RK, RV>(); - bool containsKey(Object key); + int operator ~/(num other); + external static double parse(String source, [double onError(String source)]); } class Duration implements Comparable<Duration> {} @@ -322,36 +186,166 @@ factory Exception([var message]) => null; } -external bool identical(Object a, Object b); +class Function {} -void print(Object object) {} +abstract class int extends num { + external const factory int.fromEnvironment(String name, {int defaultValue}); -class _Proxy { const _Proxy(); } -const Object proxy = const _Proxy(); + bool get isEven => false; + bool get isNegative; -class _Override { const _Override(); } -const Object override = const _Override(); + int operator &(int other); + int operator -(); + int operator <<(int shiftAmount); + int operator >>(int shiftAmount); + int operator ^(int other); + String toString(); -class _CompileTimeError { - final String _errorMsg; - _CompileTimeError(this._errorMsg); + int operator |(int other); + + int operator ~(); + + external static int parse(String source, + {int radix, int onError(String source)}); } -class AbstractClassInstantiationError { - AbstractClassInstantiationError(String className); +abstract class Invocation {} + +abstract class Iterable<E> { + E get first; + bool get isEmpty; + Iterator<E> get iterator; + int get length; + + Iterable<T> expand<T>(Iterable<T> f(E element)); + + R fold<R>(R initialValue, R combine(R previousValue, E element)) => null; + + void forEach(void f(E element)); + + Iterable<R> map<R>(R f(E e)); + + List<E> toList(); + + Iterable<E> where(bool test(E element)); } -class FallThroughError { - FallThroughError(); - FallThroughError._create(String url, int line); +abstract class Iterator<E> { + E get current; + bool moveNext(); } -abstract class _SyncIterable implements Iterable {} -class _InvocationMirror { - _InvocationMirror._withoutType( - String _functionName, List<Type> _typeArguments, - List _positionalArguments, Map<Symbol, dynamic>_namedArguments, - bool _isSuperInvocation); +class List<E> implements Iterable<E> { + List([int length]); + factory List.from(Iterable elements, {bool growable: true}) => null; + + E get last => null; + E operator [](int index) => null; + void operator []=(int index, E value) {} + + void add(E value) {} + void addAll(Iterable<E> iterable) {} + void clear() {} + + noSuchMethod(Invocation invocation) => null; +} + +class Map<K, V> { + Iterable<K> get keys => null; + int get length => 0; + Iterable<V> get values => null; + V operator [](K key) => null; + void operator []=(K key, V value) {} + Map<RK, RV> cast<RK, RV>() => null; + bool containsKey(Object key) => false; +} + +class Null extends Object { + factory Null._uninstantiable() => null; +} + +abstract class num implements Comparable<num> { + num operator %(num other); + num operator *(num other); + num operator +(num other); + num operator -(num other); + num operator -(); + double operator /(num other); + bool operator <(num other); + int operator <<(int other); + bool operator <=(num other); + bool operator ==(Object other); + bool operator >(num other); + bool operator >=(num other); + int operator >>(int other); + int operator ^(int other); + num abs(); + int round(); + double toDouble(); + int toInt(); + int operator |(int other); + int operator ~(); + int operator ~/(num other); +} + +class Object { + const Object(); + int get hashCode => 0; + Type get runtimeType => null; + bool operator ==(other) => identical(this, other); + dynamic noSuchMethod(Invocation invocation) => null; + String toString() => 'a string'; +} + +abstract class Pattern {} + +abstract class RegExp implements Pattern { + external factory RegExp(String source); +} + +abstract class Set<E> implements Iterable<E> { + Set<R> cast<R>(); +} + +class StackTrace {} + +abstract class String implements Comparable<String>, Pattern { + external factory String.fromCharCodes(Iterable<int> charCodes, + [int start = 0, int end]); + List<int> get codeUnits; + bool get isEmpty => false; + bool get isNotEmpty => false; + int get length => 0; + String operator +(String other) => null; + bool operator ==(Object other); + int codeUnitAt(int index); + String substring(int len) => null; + String toLowerCase(); + String toUpperCase(); +} + +class Symbol { + const factory Symbol(String name) = _SymbolImpl; +} + +class Type {} + +class Uri { + static List<int> parseIPv6Address(String host, [int start = 0, int end]) { + return null; + } +} + +class _Override { + const _Override(); +} + +class _Proxy { + const _Proxy(); +} + +class _SymbolImpl { + const _SymbolImpl(String name); } '''); @@ -470,7 +464,7 @@ "dart:math": "$sdkRoot/lib/math/math.dart" }; - final resource.MemoryResourceProvider provider; + final MemoryResourceProvider resourceProvider; final Map<String, String> uriMap = {}; @@ -487,33 +481,30 @@ */ PackageBundle _bundle; - MockSdk( - {bool generateSummaryFiles: false, - resource.MemoryResourceProvider resourceProvider}) - : provider = resourceProvider ?? new resource.MemoryResourceProvider() { + MockSdk({bool generateSummaryFiles: false, @required this.resourceProvider}) { _URI_MAP.forEach((uri, path) { - uriMap[uri] = provider.convertPath(path); + uriMap[uri] = resourceProvider.convertPath(path); }); for (_MockSdkLibrary library in _LIBRARIES) { - var convertedLibrary = library._toProvider(provider); + var convertedLibrary = library._toProvider(resourceProvider); sdkLibraries.add(convertedLibrary); } for (_MockSdkLibrary library in sdkLibraries) { - provider.newFile(library.path, library.content); + resourceProvider.newFile(library.path, library.content); library.parts.forEach((String path, String content) { - provider.newFile(path, content); + resourceProvider.newFile(path, content); }); } - provider.newFile( - provider.convertPath( + resourceProvider.newFile( + resourceProvider.convertPath( '$sdkRoot/lib/_internal/sdk_library_metadata/lib/libraries.dart'), librariesContent); if (generateSummaryFiles) { List<int> bytes = _computeLinkedBundleBytes(); - provider.newFileWithBytes( - provider.convertPath('/lib/_internal/strong.sum'), bytes); + resourceProvider.newFileWithBytes( + resourceProvider.convertPath('/lib/_internal/strong.sum'), bytes); } } @@ -536,28 +527,29 @@ @override Source fromFileUri(Uri uri) { - String filePath = provider.pathContext.fromUri(uri); - if (!filePath.startsWith(provider.convertPath('$sdkRoot/lib/'))) { + String filePath = resourceProvider.pathContext.fromUri(uri); + if (!filePath.startsWith(resourceProvider.convertPath('$sdkRoot/lib/'))) { return null; } for (SdkLibrary library in sdkLibraries) { String libraryPath = library.path; if (filePath == libraryPath) { try { - resource.File file = provider.getResource(filePath); + File file = resourceProvider.getResource(filePath); Uri dartUri = Uri.parse(library.shortName); return file.createSource(dartUri); } catch (exception) { return null; } } - String libraryRootPath = provider.pathContext.dirname(libraryPath) + - provider.pathContext.separator; + String libraryRootPath = + resourceProvider.pathContext.dirname(libraryPath) + + resourceProvider.pathContext.separator; if (filePath.startsWith(libraryRootPath)) { String pathInLibrary = filePath.substring(libraryRootPath.length); String uriStr = '${library.shortName}/$pathInLibrary'; try { - resource.File file = provider.getResource(filePath); + File file = resourceProvider.getResource(filePath); Uri dartUri = Uri.parse(uriStr); return file.createSource(dartUri); } catch (exception) { @@ -571,8 +563,8 @@ @override PackageBundle getLinkedBundle() { if (_bundle == null) { - resource.File summaryFile = - provider.getFile(provider.convertPath('/lib/_internal/strong.sum')); + File summaryFile = resourceProvider + .getFile(resourceProvider.convertPath('/lib/_internal/strong.sum')); List<int> bytes; if (summaryFile.exists) { bytes = summaryFile.readAsBytesSync(); @@ -598,7 +590,7 @@ Source mapDartUri(String dartUri) { String path = uriMap[dartUri]; if (path != null) { - resource.File file = provider.getResource(path); + File file = resourceProvider.getResource(path); Uri uri = new Uri(scheme: 'dart', path: dartUri.substring(5)); return file.createSource(uri); } @@ -619,14 +611,9 @@ } class _MockSdkLibrary implements SdkLibrary { - @override final String shortName; - - @override final String path; - final String content; - final Map<String, String> parts; const _MockSdkLibrary(this.shortName, this.path, this.content, @@ -653,7 +640,7 @@ @override bool get isVmLibrary => throw new UnimplementedError(); - _MockSdkLibrary _toProvider(resource.MemoryResourceProvider provider) { + _MockSdkLibrary _toProvider(MemoryResourceProvider provider) { return new _MockSdkLibrary( shortName, provider.convertPath(path),
diff --git a/pkg/analyzer/lib/src/test_utilities/resource_provider_mixin.dart b/pkg/analyzer/lib/src/test_utilities/resource_provider_mixin.dart index a24767d..b5f666d2 100644 --- a/pkg/analyzer/lib/src/test_utilities/resource_provider_mixin.dart +++ b/pkg/analyzer/lib/src/test_utilities/resource_provider_mixin.dart
@@ -13,16 +13,14 @@ * for manipulating the file system. The utility methods all take a posix style * path and convert it as appropriate for the actual platform. */ -class ResourceProviderMixin { +mixin ResourceProviderMixin { MemoryResourceProvider resourceProvider = new MemoryResourceProvider(); - String convertPath(String path) => resourceProvider.convertPath(path); - /// Convert the given [path] to be a valid import uri for this provider's path context. /// The URI will use forward slashes on all platforms and absolute paths on Windows /// will be formatted as /X:/path/file.dart String convertAbsolutePathToUri(String path) { - path = resourceProvider.convertPath(path); + path = convertPath(path); // On Windows, absolute import paths are not quite the same as a normal fs path. // C:\test.dart must be imported as one of: @@ -38,23 +36,25 @@ return path.replaceAll(r'\', '/'); } + String convertPath(String path) => resourceProvider.convertPath(path); + void deleteFile(String path) { - String convertedPath = resourceProvider.convertPath(path); + String convertedPath = convertPath(path); resourceProvider.deleteFile(convertedPath); } void deleteFolder(String path) { - String convertedPath = resourceProvider.convertPath(path); + String convertedPath = convertPath(path); resourceProvider.deleteFolder(convertedPath); } File getFile(String path) { - String convertedPath = resourceProvider.convertPath(path); + String convertedPath = convertPath(path); return resourceProvider.getFile(convertedPath); } Folder getFolder(String path) { - String convertedPath = resourceProvider.convertPath(path); + String convertedPath = convertPath(path); return resourceProvider.getFolder(convertedPath); } @@ -70,32 +70,37 @@ .join(part1, part2, part3, part4, part5, part6, part7, part8); void modifyFile(String path, String content) { - String convertedPath = resourceProvider.convertPath(path); + String convertedPath = convertPath(path); resourceProvider.modifyFile(convertedPath, content); } File newFile(String path, {String content = ''}) { - String convertedPath = resourceProvider.convertPath(path); + String convertedPath = convertPath(path); return resourceProvider.newFile(convertedPath, content); } File newFileWithBytes(String path, List<int> bytes) { - String convertedPath = resourceProvider.convertPath(path); + String convertedPath = convertPath(path); return resourceProvider.newFileWithBytes(convertedPath, bytes); } Folder newFolder(String path) { - String convertedPath = resourceProvider.convertPath(path); + String convertedPath = convertPath(path); return resourceProvider.newFolder(convertedPath); } File newOptionsFile(String directoryPath) { - return newFile(resourceProvider.pathContext - .join(directoryPath, ContextLocatorImpl.ANALYSIS_OPTIONS_NAME)); + String path = join(directoryPath, ContextLocatorImpl.ANALYSIS_OPTIONS_NAME); + return newFile(path); } File newPackagesFile(String directoryPath) { - return newFile(resourceProvider.pathContext - .join(directoryPath, ContextLocatorImpl.PACKAGES_FILE_NAME)); + String path = join(directoryPath, ContextLocatorImpl.PACKAGES_FILE_NAME); + return newFile(path); + } + + Uri toUri(String path) { + path = convertPath(path); + return resourceProvider.pathContext.toUri(path); } }
diff --git a/pkg/analyzer/lib/src/workspace/basic.dart b/pkg/analyzer/lib/src/workspace/basic.dart new file mode 100644 index 0000000..2dfddcf --- /dev/null +++ b/pkg/analyzer/lib/src/workspace/basic.dart
@@ -0,0 +1,85 @@ +// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:analyzer/file_system/file_system.dart'; +import 'package:analyzer/src/context/builder.dart'; +import 'package:analyzer/src/generated/sdk.dart'; +import 'package:analyzer/src/generated/source.dart'; +import 'package:analyzer/src/source/package_map_resolver.dart'; +import 'package:analyzer/src/summary/package_bundle_reader.dart'; +import 'package:analyzer/src/workspace/workspace.dart'; +import 'package:package_config/packages.dart'; +import 'package:path/path.dart'; + +/** + * Information about a default Dart workspace. + */ +class BasicWorkspace extends Workspace { + /** + * The [ResourceProvider] by which paths are converted into [Resource]s. + */ + final ResourceProvider provider; + + /** + * The absolute workspace root path. + */ + final String root; + + final ContextBuilder _builder; + + Map<String, List<Folder>> _packageMap; + + Packages _packages; + + BasicWorkspace._(this.provider, this.root, this._builder); + + @override + Map<String, List<Folder>> get packageMap { + _packageMap ??= _builder.convertPackagesToMap(packages); + return _packageMap; + } + + Packages get packages { + _packages ??= _builder.createPackageMap(root); + return _packages; + } + + @override + UriResolver get packageUriResolver => + new PackageMapUriResolver(provider, packageMap); + + @override + SourceFactory createSourceFactory(DartSdk sdk, SummaryDataStore summaryData) { + if (summaryData != null) { + throw new UnsupportedError( + 'Summary files are not supported in a basic workspace.'); + } + List<UriResolver> resolvers = <UriResolver>[]; + if (sdk != null) { + resolvers.add(new DartUriResolver(sdk)); + } + resolvers.add(packageUriResolver); + resolvers.add(new ResourceUriResolver(provider)); + return new SourceFactory(resolvers, packages, provider); + } + + /** + * Find the basic workspace that contains the given [path]. + */ + static BasicWorkspace find( + ResourceProvider provider, String path, ContextBuilder builder) { + Context context = provider.pathContext; + + // Ensure that the path is absolute and normalized. + if (!context.isAbsolute(path)) { + throw new ArgumentError('not absolute: $path'); + } + path = context.normalize(path); + Resource resource = provider.getResource(path); + if (resource is File) { + path = resource.parent.path; + } + return new BasicWorkspace._(provider, path, builder); + } +}
diff --git a/pkg/analyzer/lib/src/generated/bazel.dart b/pkg/analyzer/lib/src/workspace/bazel.dart similarity index 85% rename from pkg/analyzer/lib/src/generated/bazel.dart rename to pkg/analyzer/lib/src/workspace/bazel.dart index 68e19fb..c4e6c21 100644 --- a/pkg/analyzer/lib/src/generated/bazel.dart +++ b/pkg/analyzer/lib/src/workspace/bazel.dart
@@ -10,9 +10,10 @@ import 'package:analyzer/src/generated/sdk.dart'; import 'package:analyzer/src/generated/source.dart'; import 'package:analyzer/src/generated/source_io.dart'; -import 'package:analyzer/src/generated/workspace.dart'; +import 'package:analyzer/src/summary/package_bundle_reader.dart'; import 'package:analyzer/src/util/uri.dart'; -import 'package:path/path.dart'; +import 'package:analyzer/src/workspace/workspace.dart'; +import 'package:path/path.dart' as path; /** * Instances of the class `BazelFileUriResolver` resolve `file` URI's by first @@ -31,8 +32,8 @@ if (!ResourceUriResolver.isFileUri(uri)) { return null; } - String path = fileUriToNormalizedPath(provider.pathContext, uri); - File file = workspace.findFile(path); + String filePath = fileUriToNormalizedPath(provider.pathContext, uri); + File file = workspace.findFile(filePath); if (file != null) { return file.createSource(actualUri ?? uri); } @@ -45,7 +46,7 @@ */ class BazelPackageUriResolver extends UriResolver { final BazelWorkspace _workspace; - final Context _context; + final path.Context _context; /** * The cache of absolute [Uri]s to [Source]s mappings. @@ -75,15 +76,15 @@ String filePath = fileUriPart.replaceAll('/', _context.separator); if (packageName.indexOf('.') == -1) { - String path = _context.join(_workspace.root, 'third_party', 'dart', - packageName, 'lib', filePath); - File file = _workspace.findFile(path); + String fullFilePath = _context.join(_workspace.root, 'third_party', + 'dart', packageName, 'lib', filePath); + File file = _workspace.findFile(fullFilePath); return file?.createSource(uri); } else { String packagePath = packageName.replaceAll('.', _context.separator); - String path = + String fullFilePath = _context.join(_workspace.root, packagePath, 'lib', filePath); - File file = _workspace.findFile(path); + File file = _workspace.findFile(fullFilePath); return file?.createSource(uri); } }); @@ -91,12 +92,12 @@ @override Uri restoreAbsolute(Source source) { - Context context = _workspace.provider.pathContext; - String path = source.fullName; + path.Context context = _workspace.provider.pathContext; + String filePath = source.fullName; - Uri restore(String root, String path) { - if (root != null && context.isWithin(root, path)) { - String relative = context.relative(path, from: root); + Uri restore(String root, String filePath) { + if (root != null && context.isWithin(root, filePath)) { + String relative = context.relative(filePath, from: root); List<String> components = context.split(relative); if (components.length > 4 && components[0] == 'third_party' && @@ -126,7 +127,7 @@ _workspace.readonly, _workspace.root ]) { - Uri uri = restore(root, path); + Uri uri = restore(root, filePath); if (uri != null) { return uri; } @@ -185,13 +186,16 @@ UriResolver get packageUriResolver => new BazelPackageUriResolver(this); @override - SourceFactory createSourceFactory(DartSdk sdk) { + SourceFactory createSourceFactory(DartSdk sdk, SummaryDataStore summaryData) { List<UriResolver> resolvers = <UriResolver>[]; if (sdk != null) { resolvers.add(new DartUriResolver(sdk)); } resolvers.add(packageUriResolver); resolvers.add(new BazelFileUriResolver(this)); + if (summaryData != null) { + resolvers.add(InSummaryUriResolver(provider, summaryData)); + } return new SourceFactory(resolvers, null, provider); } @@ -203,7 +207,7 @@ * not in the workspace [root]. */ File findFile(String absolutePath) { - Context context = provider.pathContext; + path.Context context = provider.pathContext; try { String relative = context.relative(absolutePath, from: root); if (relative == '.') { @@ -255,16 +259,12 @@ * folder, but there is corresponding folder 'foo' in `READONLY`, i.e. the * corresponding readonly workspace root. */ - static BazelWorkspace find(ResourceProvider provider, String path) { - Context context = provider.pathContext; + static BazelWorkspace find(ResourceProvider provider, String filePath) { + path.Context context = provider.pathContext; + assert(context.isAbsolute(filePath), 'Not an absolute path: $filePath'); + filePath = context.normalize(filePath); - // Ensure that the path is absolute and normalized. - if (!context.isAbsolute(path)) { - throw new ArgumentError('not absolute: $path'); - } - path = context.normalize(path); - - Folder folder = provider.getFolder(path); + Folder folder = provider.getFolder(filePath); while (true) { Folder parent = folder.parent; if (parent == null) { @@ -317,7 +317,7 @@ * exists. */ static String _findSymlinkPrefix(ResourceProvider provider, String root) { - Context context = provider.pathContext; + path.Context context = provider.pathContext; if (provider.getFolder(context.join(root, 'blaze-genfiles')).exists) { return 'blaze'; }
diff --git a/pkg/analyzer/lib/src/generated/gn.dart b/pkg/analyzer/lib/src/workspace/gn.dart similarity index 78% rename from pkg/analyzer/lib/src/generated/gn.dart rename to pkg/analyzer/lib/src/workspace/gn.dart index abbed00..50731c5 100644 --- a/pkg/analyzer/lib/src/generated/gn.dart +++ b/pkg/analyzer/lib/src/workspace/gn.dart
@@ -10,13 +10,14 @@ import 'package:analyzer/src/generated/sdk.dart'; import 'package:analyzer/src/generated/source.dart'; import 'package:analyzer/src/generated/source_io.dart'; -import 'package:analyzer/src/generated/workspace.dart'; import 'package:analyzer/src/source/package_map_resolver.dart'; +import 'package:analyzer/src/summary/package_bundle_reader.dart'; import 'package:analyzer/src/util/uri.dart'; +import 'package:analyzer/src/workspace/workspace.dart'; import 'package:package_config/packages.dart'; import 'package:package_config/packages_file.dart'; import 'package:package_config/src/packages_impl.dart'; -import 'package:path/path.dart'; +import 'package:path/path.dart' as path; /** * Information about a Gn workspace. @@ -70,7 +71,11 @@ new PackageMapUriResolver(provider, packageMap); @override - SourceFactory createSourceFactory(DartSdk sdk) { + SourceFactory createSourceFactory(DartSdk sdk, SummaryDataStore summaryData) { + if (summaryData != null) { + throw new UnsupportedError( + 'Summary files are not supported in a GN workspace.'); + } List<UriResolver> resolvers = <UriResolver>[]; if (sdk != null) { resolvers.add(new DartUriResolver(sdk)); @@ -81,21 +86,6 @@ } /** - * Return the file with the given [absolutePath]. - * - * Return `null` if the given [absolutePath] is not in the workspace [root]. - */ - File findFile(String absolutePath) { - try { - File writableFile = provider.getFile(absolutePath); - if (writableFile.exists) { - return writableFile; - } - } catch (_) {} - return null; - } - - /** * Creates an alternate representation for available packages. */ Map<String, List<Folder>> _convertPackagesToMap(Packages packages) { @@ -103,8 +93,8 @@ if (packages != null && packages != Packages.noPackages) { var pathContext = provider.pathContext; packages.asMap().forEach((String packageName, Uri uri) { - String path = fileUriToNormalizedPath(pathContext, uri); - folderMap[packageName] = [provider.getFolder(path)]; + String filePath = fileUriToNormalizedPath(pathContext, uri); + folderMap[packageName] = [provider.getFolder(filePath)]; }); } return folderMap; @@ -114,8 +104,8 @@ * Loads the packages from the .packages file. */ Packages _createPackages() { - Map<String, Uri> map = _packagesFilePaths.map((String path) { - File configFile = provider.getFile(path); + Map<String, Uri> map = _packagesFilePaths.map((String filePath) { + File configFile = provider.getFile(filePath); List<int> bytes = configFile.readAsBytesSync(); return parse(bytes, configFile.toUri()); }).reduce((mapOne, mapTwo) { @@ -142,10 +132,10 @@ * replacing the values in the map. */ void _resolveSymbolicLinks(Map<String, Uri> map) { - Context pathContext = provider.pathContext; + path.Context pathContext = provider.pathContext; for (String packageName in map.keys) { - String path = fileUriToNormalizedPath(pathContext, map[packageName]); - Folder folder = provider.getFolder(path); + String filePath = fileUriToNormalizedPath(pathContext, map[packageName]); + Folder folder = provider.getFolder(filePath); String folderPath = _resolveSymbolicLink(folder); // Add a '.' so that the URI is suitable for resolving relative URI's // against it. @@ -155,22 +145,18 @@ } /** - * Find the GN workspace that contains the given [path]. + * Find the GN workspace that contains the given [filePath]. * * Return `null` if a workspace could not be found. For a workspace to be * found, both a `.jiri_root` file must be found, and at least one "packages" - * file must be found in [path]'s output directory. + * file must be found in [filePath]'s output directory. */ - static GnWorkspace find(ResourceProvider provider, String path) { - Context context = provider.pathContext; + static GnWorkspace find(ResourceProvider provider, String filePath) { + path.Context context = provider.pathContext; + assert(context.isAbsolute(filePath), 'Not an absolute path: $filePath'); + filePath = context.normalize(filePath); - // Ensure that the path is absolute and normalized. - if (!context.isAbsolute(path)) { - throw new ArgumentError('Not an absolute path: $path'); - } - path = context.normalize(path); - - Folder folder = provider.getFolder(path); + Folder folder = provider.getFolder(filePath); while (true) { Folder parent = folder.parent; if (parent == null) { @@ -180,7 +166,8 @@ // Found the .jiri_root file, must be a non-git workspace. if (folder.getChildAssumingFolder(_jiriRootName).exists) { String root = folder.path; - List<String> packagesFiles = _findPackagesFile(provider, root, path); + List<String> packagesFiles = + _findPackagesFile(provider, root, filePath); if (packagesFiles.isEmpty) { return null; } @@ -204,10 +191,10 @@ static List<String> _findPackagesFile( ResourceProvider provider, String root, - String path, + String filePath, ) { - Context pathContext = provider.pathContext; - String sourceDirectory = pathContext.relative(path, from: root); + path.Context pathContext = provider.pathContext; + String sourceDirectory = pathContext.relative(filePath, from: root); Folder outDirectory = _getOutDirectory(root, provider); if (outDirectory == null) { return const <String>[]; @@ -234,7 +221,7 @@ * that file cannot be found, looks for standard output directory locations. */ static Folder _getOutDirectory(String root, ResourceProvider provider) { - Context pathContext = provider.pathContext; + path.Context pathContext = provider.pathContext; File config = provider.getFile(pathContext.join(root, '.config')); if (config.exists) { String content = config.readAsStringSync(); @@ -242,11 +229,11 @@ new RegExp(r'^FUCHSIA_BUILD_DIR=["\x27](.+)["\x27]$', multiLine: true) .firstMatch(content); if (match != null) { - String path = match.group(1); - if (pathContext.isRelative(path)) { - path = pathContext.join(root, path); + String buildDirPath = match.group(1); + if (pathContext.isRelative(buildDirPath)) { + buildDirPath = pathContext.join(root, buildDirPath); } - return provider.getFolder(path); + return provider.getFolder(buildDirPath); } } Folder outDirectory = provider.getFolder(pathContext.join(root, 'out'));
diff --git a/pkg/analyzer/lib/src/generated/package_build.dart b/pkg/analyzer/lib/src/workspace/package_build.dart similarity index 80% rename from pkg/analyzer/lib/src/generated/package_build.dart rename to pkg/analyzer/lib/src/workspace/package_build.dart index 8effaf9..49e0485 100644 --- a/pkg/analyzer/lib/src/generated/package_build.dart +++ b/pkg/analyzer/lib/src/workspace/package_build.dart
@@ -11,11 +11,12 @@ import 'package:analyzer/src/generated/sdk.dart'; import 'package:analyzer/src/generated/source.dart'; import 'package:analyzer/src/generated/source_io.dart'; -import 'package:analyzer/src/generated/workspace.dart'; import 'package:analyzer/src/source/package_map_resolver.dart'; +import 'package:analyzer/src/summary/package_bundle_reader.dart'; import 'package:analyzer/src/util/uri.dart'; +import 'package:analyzer/src/workspace/workspace.dart'; import 'package:package_config/packages.dart'; -import 'package:path/path.dart'; +import 'package:path/path.dart' as path; import 'package:yaml/yaml.dart'; /** @@ -35,8 +36,8 @@ if (!ResourceUriResolver.isFileUri(uri)) { return null; } - String path = fileUriToNormalizedPath(provider.pathContext, uri); - File file = workspace.findFile(path); + String filePath = fileUriToNormalizedPath(provider.pathContext, uri); + File file = workspace.findFile(filePath); if (file != null) { return file.createSource(actualUri ?? uri); } @@ -50,7 +51,7 @@ class PackageBuildPackageUriResolver extends UriResolver { final PackageBuildWorkspace _workspace; final UriResolver _normalUriResolver; - final Context _context; + final path.Context _context; /** * The cache of absolute [Uri]s to [Source]s mappings. @@ -98,12 +99,11 @@ @override Uri restoreAbsolute(Source source) { - Context context = _workspace.provider.pathContext; - String path = source.fullName; + String filePath = source.fullName; - if (context.isWithin(_workspace.root, path)) { - String relative = context.relative(path, from: _workspace.root); - List<String> components = context.split(relative); + if (_context.isWithin(_workspace.root, filePath)) { + String relative = _context.relative(filePath, from: _workspace.root); + List<String> components = _context.split(relative); if (components.length > 4 && components[0] == 'build' && components[1] == 'generated' && @@ -205,9 +205,10 @@ if (!packageMap.containsKey(packageName)) { return null; } - String path = context.join( + path.Context context = provider.pathContext; + String fullBuiltPath = context.join( root, _dartToolRootName, 'build', 'generated', packageName, builtPath); - return provider.getFile(path); + return provider.getFile(fullBuiltPath); } /** @@ -217,13 +218,18 @@ * `bin/`, `web/`, and `test/` etc can all be built as well. This method * exists to give a name to that prefix processing step. */ - String builtPackageSourcePath(String path) { - assert(context.isRelative(path)); - return context.join('lib', path); + String builtPackageSourcePath(String filePath) { + path.Context context = provider.pathContext; + assert(context.isRelative(filePath), 'Not a relative path: $filePath'); + return context.join('lib', filePath); } @override - SourceFactory createSourceFactory(DartSdk sdk) { + SourceFactory createSourceFactory(DartSdk sdk, SummaryDataStore summaryData) { + if (summaryData != null) { + throw new UnsupportedError( + 'Summary files are not supported in a package:build workspace.'); + } List<UriResolver> resolvers = <UriResolver>[]; if (sdk != null) { resolvers.add(new DartUriResolver(sdk)); @@ -234,44 +240,40 @@ } /** - * Return the file with the given [path], looking first into directories for + * Return the file with the given [filePath], looking first into directories for * source files, and then in the generated directory * `.dart_tool/build/generated/$projectPackageName/$FILE`. The file in the * workspace root is returned even if it does not exist. Return `null` if the - * given [path] is not in the workspace [root]. + * given [filePath] is not in the workspace [root]. */ - File findFile(String path) { - assert(context.isAbsolute(path)); + File findFile(String filePath) { + path.Context context = provider.pathContext; + assert(context.isAbsolute(filePath), 'Not an absolute path: $filePath'); try { - final String builtPath = context.relative(path, from: root); + final String builtPath = context.relative(filePath, from: root); final File file = builtFile(builtPath, projectPackageName); if (file.exists) { return file; } - return provider.getFile(path); + return provider.getFile(filePath); } catch (_) { return null; } } /** - * Find the package:build workspace that contains the given [path]. + * Find the package:build workspace that contains the given [filePath]. * - * Return `null` if the path is not in a package:build workspace. + * Return `null` if the filePath is not in a package:build workspace. */ static PackageBuildWorkspace find( - ResourceProvider provider, String path, ContextBuilder builder) { - Context context = provider.pathContext; - - // Ensure that the path is absolute and normalized. - if (!context.isAbsolute(path)) { - throw new ArgumentError('Not an absolute path: $path'); - } - path = context.normalize(path); - - Folder folder = provider.getFolder(path); + ResourceProvider provider, String filePath, ContextBuilder builder) { + path.Context context = provider.pathContext; + assert(context.isAbsolute(filePath), 'Not an absolute path: $filePath'); + filePath = context.normalize(filePath); + Folder folder = provider.getFolder(filePath); while (true) { Folder parent = folder.parent; if (parent == null) {
diff --git a/pkg/analyzer/lib/src/generated/workspace.dart b/pkg/analyzer/lib/src/workspace/workspace.dart similarity index 76% rename from pkg/analyzer/lib/src/generated/workspace.dart rename to pkg/analyzer/lib/src/workspace/workspace.dart index c122845..efd55f8 100644 --- a/pkg/analyzer/lib/src/generated/workspace.dart +++ b/pkg/analyzer/lib/src/workspace/workspace.dart
@@ -5,6 +5,7 @@ import 'package:analyzer/file_system/file_system.dart'; import 'package:analyzer/src/generated/sdk.dart'; import 'package:analyzer/src/generated/source.dart'; +import 'package:analyzer/src/summary/package_bundle_reader.dart'; /** * Abstract superclass of classes that provide information about the workspace @@ -28,8 +29,8 @@ UriResolver get packageUriResolver; /** - * Create the [SourceFactory] for resolving Uris to [Source]s. - * The [sdk] may be `null`. + * Create the source factory that should be used to resolve Uris to [Source]s. + * The [sdk] may be `null`. The [summaryData] can also be `null`. */ - SourceFactory createSourceFactory(DartSdk sdk); + SourceFactory createSourceFactory(DartSdk sdk, SummaryDataStore summaryData); }
diff --git a/pkg/analyzer/pubspec.yaml b/pkg/analyzer/pubspec.yaml index d6cd53d..62eb471 100644 --- a/pkg/analyzer/pubspec.yaml +++ b/pkg/analyzer/pubspec.yaml
@@ -1,5 +1,5 @@ name: analyzer -version: 0.33.6+1-dev +version: 0.34.0 author: Dart Team <misc@dartlang.org> description: Static analyzer for Dart. homepage: https://github.com/dart-lang/sdk/tree/master/pkg/analyzer @@ -11,10 +11,10 @@ collection: ^1.10.1 convert: ^2.0.0 crypto: '>=1.1.1 <3.0.0' - front_end: 0.1.6+8 + front_end: 0.1.7 glob: ^1.0.3 html: '>=0.12.0 <1.14.0' - kernel: 0.3.6+8 + kernel: 0.3.7 meta: ^1.0.2 package_config: '>=0.1.5 <2.0.0' path: '>=0.9.0 <2.0.0'
diff --git a/pkg/analyzer/test/dart/ast/visitor_test.dart b/pkg/analyzer/test/dart/ast/visitor_test.dart index f246a06..94457e0 100644 --- a/pkg/analyzer/test/dart/ast/visitor_test.dart +++ b/pkg/analyzer/test/dart/ast/visitor_test.dart
@@ -40,7 +40,7 @@ }'''; CompilationUnit unit = parseCompilationUnit(source); List<AstNode> nodes = new List<AstNode>(); - BreadthFirstVisitor<Object> visitor = + _BreadthFirstVisitorTestHelper visitor = new _BreadthFirstVisitorTestHelper(nodes); visitor.visitAllNodes(unit); expect(nodes, hasLength(59)); @@ -64,14 +64,14 @@ * A helper class used to collect the nodes that were visited and to preserve * the order in which they were visited. */ -class _BreadthFirstVisitorTestHelper extends BreadthFirstVisitor<Object> { +class _BreadthFirstVisitorTestHelper extends BreadthFirstVisitor<void> { List<AstNode> nodes; _BreadthFirstVisitorTestHelper(this.nodes) : super(); @override - Object visitNode(AstNode node) { + void visitNode(AstNode node) { nodes.add(node); - return super.visitNode(node); + super.visitNode(node); } }
diff --git a/pkg/analyzer/test/dart/element/builder_test.dart b/pkg/analyzer/test/dart/element/builder_test.dart index f460cfc..4b6a746 100644 --- a/pkg/analyzer/test/dart/element/builder_test.dart +++ b/pkg/analyzer/test/dart/element/builder_test.dart
@@ -1207,7 +1207,7 @@ * It is used to test the [ApiElementBuilder] itself, and its usage by * [ElementBuilder]. */ -abstract class _ApiElementBuilderTestMixin { +mixin _ApiElementBuilderTestMixin { CompilationUnit get compilationUnit; void set isMixinSupportEnabled(bool value);
diff --git a/pkg/analyzer/test/file_system/resource_uri_resolver_test.dart b/pkg/analyzer/test/file_system/resource_uri_resolver_test.dart index 4bb689e..4f0a866 100644 --- a/pkg/analyzer/test/file_system/resource_uri_resolver_test.dart +++ b/pkg/analyzer/test/file_system/resource_uri_resolver_test.dart
@@ -2,9 +2,9 @@ // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. -import 'package:analyzer/file_system/memory_file_system.dart'; import 'package:analyzer/src/file_system/file_system.dart'; import 'package:analyzer/src/generated/source.dart'; +import 'package:analyzer/src/test_utilities/resource_provider_mixin.dart'; import 'package:test/test.dart'; import 'package:test_reflective_loader/test_reflective_loader.dart'; @@ -15,36 +15,34 @@ } @reflectiveTest -class ResourceUriResolverTest { - MemoryResourceProvider provider; +class ResourceUriResolverTest with ResourceProviderMixin { ResourceUriResolver resolver; void setUp() { - provider = new MemoryResourceProvider(); - resolver = new ResourceUriResolver(provider); - provider.newFile(provider.convertPath('/test.dart'), ''); - provider.newFolder(provider.convertPath('/folder')); + resolver = new ResourceUriResolver(resourceProvider); + newFile('/test.dart'); + newFolder('/folder'); } void test_creation() { - expect(provider, isNotNull); + expect(resourceProvider, isNotNull); expect(resolver, isNotNull); } void test_resolveAbsolute_file() { - var uri = provider.pathContext.toUri(provider.convertPath('/test.dart')); + var uri = toUri('/test.dart'); Source source = resolver.resolveAbsolute(uri); expect(source, isNotNull); expect(source.exists(), isTrue); - expect(source.fullName, provider.convertPath('/test.dart')); + expect(source.fullName, convertPath('/test.dart')); } void test_resolveAbsolute_folder() { - var uri = provider.pathContext.toUri(provider.convertPath('/folder')); + var uri = toUri('/folder'); Source source = resolver.resolveAbsolute(uri); expect(source, isNotNull); expect(source.exists(), isFalse); - expect(source.fullName, provider.convertPath('/folder')); + expect(source.fullName, convertPath('/folder')); } void test_resolveAbsolute_notFile_dartUri() { @@ -60,7 +58,7 @@ } void test_restoreAbsolute() { - var uri = provider.pathContext.toUri(provider.convertPath('/test.dart')); + var uri = toUri('/test.dart'); Source source = resolver.resolveAbsolute(uri); expect(source, isNotNull); expect(resolver.restoreAbsolute(source), uri);
diff --git a/pkg/analyzer/test/generated/all_the_rest_test.dart b/pkg/analyzer/test/generated/all_the_rest_test.dart index 4ac956a..49a4b02 100644 --- a/pkg/analyzer/test/generated/all_the_rest_test.dart +++ b/pkg/analyzer/test/generated/all_the_rest_test.dart
@@ -1,4 +1,4 @@ -// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file +// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. @@ -150,16 +150,14 @@ void test_restoreAbsolute_library() { _SourceMock source = new _SourceMock(); - Uri fileUri = resourceProvider.pathContext.toUri(coreCorePath); - source.uri = fileUri; + source.uri = toUri('/sdk/lib/core/core.dart'); Uri dartUri = resolver.restoreAbsolute(source); expect(dartUri.toString(), 'dart:core'); } void test_restoreAbsolute_part() { _SourceMock source = new _SourceMock(); - Uri fileUri = resourceProvider.pathContext.toUri(coreIntPath); - source.uri = fileUri; + source.uri = toUri('/sdk/lib/core/int.dart'); Uri dartUri = resolver.restoreAbsolute(source); expect(dartUri.toString(), 'dart:core/int.dart'); } @@ -220,7 +218,7 @@ A.bar() {} }'''); ConstructorDeclaration declaration = - id.getAncestor((node) => node is ConstructorDeclaration); + id.thisOrAncestorOfType<ConstructorDeclaration>(); Element element = ElementLocator.locate(declaration); EngineTestCase.assertInstanceOf( (obj) => obj is ConstructorElement, ConstructorElement, element); @@ -236,7 +234,7 @@ test_locate_FunctionDeclaration() async { AstNode id = await _findNodeIn("f", "int f() => 3;"); FunctionDeclaration declaration = - id.getAncestor((node) => node is FunctionDeclaration); + id.thisOrAncestorOfType<FunctionDeclaration>(); Element element = ElementLocator.locate(declaration); EngineTestCase.assertInstanceOf( (obj) => obj is FunctionElement, FunctionElement, element); @@ -397,7 +395,7 @@ void m() {} }'''); MethodDeclaration declaration = - id.getAncestor((node) => node is MethodDeclaration); + id.thisOrAncestorOfType<MethodDeclaration>(); Element element = ElementLocator.locate(declaration); EngineTestCase.assertInstanceOf( (obj) => obj is MethodElement, MethodElement, element); @@ -425,8 +423,7 @@ CompilationUnit cu = await _resolveContents(code); int offset = code.indexOf('foo(0)'); AstNode node = new NodeLocator(offset).searchWithin(cu); - MethodInvocation invocation = - node.getAncestor((n) => n is MethodInvocation); + MethodInvocation invocation = node.thisOrAncestorOfType<MethodInvocation>(); Element element = ElementLocator.locate(invocation); EngineTestCase.assertInstanceOf( (obj) => obj is FunctionElement, FunctionElement, element); @@ -460,7 +457,7 @@ import 'dart:core' as core; core.int value;'''); PrefixedIdentifier identifier = - id.getAncestor((node) => node is PrefixedIdentifier); + id.thisOrAncestorOfType<PrefixedIdentifier>(); Element element = ElementLocator.locate(identifier); EngineTestCase.assertInstanceOf( (obj) => obj is ClassElement, ClassElement, element); @@ -508,7 +505,7 @@ test_locate_VariableDeclaration() async { AstNode id = await _findNodeIn("x", "var x = 'abc';"); VariableDeclaration declaration = - id.getAncestor((node) => node is VariableDeclaration); + id.thisOrAncestorOfType<VariableDeclaration>(); Element element = ElementLocator.locate(declaration); EngineTestCase.assertInstanceOf((obj) => obj is TopLevelVariableElement, TopLevelVariableElement, element); @@ -2053,31 +2050,27 @@ } } -class _SimpleDartSdkTest extends Object with ResourceProviderMixin { - String coreCorePath; - String coreIntPath; +class _SimpleDartSdkTest with ResourceProviderMixin { DartSdk sdk; void setUp() { - Folder sdkFolder = - resourceProvider.newFolder(resourceProvider.convertPath('/sdk')); - resourceProvider.newFile( - resourceProvider.convertPath( - '/sdk/lib/_internal/sdk_library_metadata/lib/libraries.dart'), - ''' + newFile('/sdk/lib/_internal/sdk_library_metadata/lib/libraries.dart', + content: ''' const Map<String, LibraryInfo> libraries = const { "core": const LibraryInfo("core/core.dart") }; '''); - coreCorePath = resourceProvider.convertPath('/sdk/lib/core/core.dart'); - resourceProvider.newFile(coreCorePath, ''' + + newFile('/sdk/lib/core/core.dart', content: ''' library dart.core; part 'int.dart'; '''); - coreIntPath = resourceProvider.convertPath('/sdk/lib/core/int.dart'); - resourceProvider.newFile(coreIntPath, ''' + + newFile('/sdk/lib/core/int.dart', content: ''' part of dart.core; '''); + + Folder sdkFolder = newFolder('/sdk'); sdk = new FolderBasedDartSdk(resourceProvider, sdkFolder); } }
diff --git a/pkg/analyzer/test/generated/analysis_context_factory.dart b/pkg/analyzer/test/generated/analysis_context_factory.dart index 0226a04..1185adf 100644 --- a/pkg/analyzer/test/generated/analysis_context_factory.dart +++ b/pkg/analyzer/test/generated/analysis_context_factory.dart
@@ -130,6 +130,7 @@ objectClassElement, overrideClassElement, proxyClassElement, + provider.setType.element, provider.stackTraceType.element, provider.stringType.element, provider.symbolType.element, @@ -173,13 +174,15 @@ proxyTopLevelVariableElt ]; LibraryElementImpl coreLibrary = new LibraryElementImpl.forNode( - coreContext, AstTestFactory.libraryIdentifier2(["dart", "core"])); + coreContext, null, AstTestFactory.libraryIdentifier2(["dart", "core"])); coreLibrary.definingCompilationUnit = coreUnit; // // dart:async // LibraryElementImpl asyncLibrary = new LibraryElementImpl.forNode( - coreContext, AstTestFactory.libraryIdentifier2(["dart", "async"])); + coreContext, + null, + AstTestFactory.libraryIdentifier2(["dart", "async"])); CompilationUnitElementImpl asyncUnit = new CompilationUnitElementImpl(); Source asyncSource = sourceFactory.forUri(DartSdk.DART_ASYNC); coreContext.setContents(asyncSource, ""); @@ -329,7 +332,7 @@ htmlUnit.topLevelVariables = <TopLevelVariableElement>[document]; htmlUnit.accessors = <PropertyAccessorElement>[document.getter]; LibraryElementImpl htmlLibrary = new LibraryElementImpl.forNode(coreContext, - AstTestFactory.libraryIdentifier2(["dart", "dom", "html"])); + null, AstTestFactory.libraryIdentifier2(["dart", "dom", "html"])); htmlLibrary.definingCompilationUnit = htmlUnit; // // dart:math @@ -390,7 +393,7 @@ ]; mathUnit.types = <ClassElement>[randomElement]; LibraryElementImpl mathLibrary = new LibraryElementImpl.forNode( - coreContext, AstTestFactory.libraryIdentifier2(["dart", "math"])); + coreContext, null, AstTestFactory.libraryIdentifier2(["dart", "math"])); mathLibrary.definingCompilationUnit = mathUnit; // // Set empty sources for the rest of the libraries.
diff --git a/pkg/analyzer/test/generated/checked_mode_compile_time_error_code_driver_test.dart b/pkg/analyzer/test/generated/checked_mode_compile_time_error_code_driver_test.dart index b8d01e9..a21ef51 100644 --- a/pkg/analyzer/test/generated/checked_mode_compile_time_error_code_driver_test.dart +++ b/pkg/analyzer/test/generated/checked_mode_compile_time_error_code_driver_test.dart
@@ -17,4 +17,8 @@ extends CheckedModeCompileTimeErrorCodeTest { @override bool get enableNewAnalysisDriver => true; + + test_setElementTypeNotAssignable() async { + await super.test_setElementTypeNotAssignable(); + } }
diff --git a/pkg/analyzer/test/generated/checked_mode_compile_time_error_code_test.dart b/pkg/analyzer/test/generated/checked_mode_compile_time_error_code_test.dart index 32623b2..52ed142 100644 --- a/pkg/analyzer/test/generated/checked_mode_compile_time_error_code_test.dart +++ b/pkg/analyzer/test/generated/checked_mode_compile_time_error_code_test.dart
@@ -28,8 +28,7 @@ var v = const A(3, 2); '''); await computeAnalysisResult(source); - assertErrors( - source, [CheckedModeCompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION]); + assertErrors(source, [CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION]); verify([source]); } @@ -634,8 +633,18 @@ } var v = const A.a1(0);'''); await computeAnalysisResult(source); - assertErrors( - source, [CheckedModeCompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION]); + assertErrors(source, [CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION]); + verify([source]); + } + + @failingTest + test_setElementTypeNotAssignable() async { + Source source = addSource("var v = const <String>{42};"); + await computeAnalysisResult(source); + assertErrors(source, [ + CheckedModeCompileTimeErrorCode.SET_ELEMENT_TYPE_NOT_ASSIGNABLE, + StaticWarningCode.SET_ELEMENT_TYPE_NOT_ASSIGNABLE + ]); verify([source]); } @@ -651,8 +660,7 @@ const f = const D('0.0'); '''); await computeAnalysisResult(source); - assertErrors( - source, [CheckedModeCompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION]); + assertErrors(source, [CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION]); verify([source]); }
diff --git a/pkg/analyzer/test/generated/compile_time_error_code_driver_test.dart b/pkg/analyzer/test/generated/compile_time_error_code_driver_test.dart index e2ad9cf..c8acd25 100644 --- a/pkg/analyzer/test/generated/compile_time_error_code_driver_test.dart +++ b/pkg/analyzer/test/generated/compile_time_error_code_driver_test.dart
@@ -31,12 +31,6 @@ @override @failingTest - test_genericFunctionTypeArgument_typedef() { - return super.test_genericFunctionTypeArgument_typedef(); - } - - @override - @failingTest test_invalidIdentifierInAsync_async() { return super.test_invalidIdentifierInAsync_async(); }
diff --git a/pkg/analyzer/test/generated/compile_time_error_code_test.dart b/pkg/analyzer/test/generated/compile_time_error_code_test.dart index a04cda9..1a74c98 100644 --- a/pkg/analyzer/test/generated/compile_time_error_code_test.dart +++ b/pkg/analyzer/test/generated/compile_time_error_code_test.dart
@@ -38,8 +38,32 @@ @override @failingTest - test_genericFunctionTypeArgument_typedef() { - return super.test_genericFunctionTypeArgument_typedef(); + test_constSetElementTypeImplementsEquals_constField() async { + return super.test_constSetElementTypeImplementsEquals_constField(); + } + + @override + @failingTest + test_constSetElementTypeImplementsEquals_direct() async { + return super.test_constSetElementTypeImplementsEquals_direct(); + } + + @override + @failingTest + test_constSetElementTypeImplementsEquals_dynamic() async { + return super.test_constSetElementTypeImplementsEquals_dynamic(); + } + + @override + @failingTest + test_constSetElementTypeImplementsEquals_factory() async { + return super.test_constSetElementTypeImplementsEquals_factory(); + } + + @override + @failingTest + test_constSetElementTypeImplementsEquals_super() async { + return super.test_constSetElementTypeImplementsEquals_super(); } @override @@ -61,6 +85,12 @@ } @override + @failingTest + test_invalidTypeArgumentInConstSet() async { + return super.test_invalidTypeArgumentInConstSet(); + } + + @override @failingTest // Does not work with old task model test_mixinInference_recursiveSubtypeCheck_new_syntax() { return super.test_mixinInference_recursiveSubtypeCheck_new_syntax(); @@ -74,6 +104,24 @@ @override @failingTest + test_nonConstSetElement() async { + return super.test_nonConstSetElement(); + } + + @override + @failingTest + test_nonConstSetElementFromDeferredLibrary() async { + return super.test_nonConstSetElementFromDeferredLibrary(); + } + + @override + @failingTest + test_nonConstSetElementFromDeferredLibrary_nested() async { + return super.test_nonConstSetElementFromDeferredLibrary_nested(); + } + + @override + @failingTest test_objectCannotExtendAnotherClass() { return super.test_objectCannotExtendAnotherClass(); } @@ -1235,9 +1283,9 @@ } test_constEvalTypeInt_binary() async { - await _check_constEvalTypeInt_withParameter_binary("p ^ ''"); - await _check_constEvalTypeInt_withParameter_binary("p & ''"); - await _check_constEvalTypeInt_withParameter_binary("p | ''"); + await _check_constEvalTypeBoolOrInt_withParameter_binary("p ^ ''"); + await _check_constEvalTypeBoolOrInt_withParameter_binary("p & ''"); + await _check_constEvalTypeBoolOrInt_withParameter_binary("p | ''"); await _check_constEvalTypeInt_withParameter_binary("p >> ''"); await _check_constEvalTypeInt_withParameter_binary("p << ''"); } @@ -1439,6 +1487,100 @@ verify([source]); } + test_constSetElementTypeImplementsEquals_constField() async { + Source source = addSource(r''' +class A { + static const a = const A(); + const A(); + operator ==(other) => false; +} +main() { + const {A.a}; +} +'''); + await computeAnalysisResult(source); + assertErrors(source, + [CompileTimeErrorCode.CONST_SET_ELEMENT_TYPE_IMPLEMENTS_EQUALS]); + verify([source]); + } + + test_constSetElementTypeImplementsEquals_direct() async { + Source source = addSource(r''' +class A { + const A(); + operator ==(other) => false; +} +main() { + const {const A()}; +} +'''); + await computeAnalysisResult(source); + assertErrors(source, + [CompileTimeErrorCode.CONST_SET_ELEMENT_TYPE_IMPLEMENTS_EQUALS]); + verify([source]); + } + + test_constSetElementTypeImplementsEquals_dynamic() async { + // Note: static type of B.a is "dynamic", but actual type of the const + // object is A. We need to make sure we examine the actual type when + // deciding whether there is a problem with operator==. + Source source = addSource(r''' +class A { + const A(); + operator ==(other) => false; +} +class B { + static const a = const A(); +} +main() { + const {B.a}; +} +'''); + await computeAnalysisResult(source); + assertErrors(source, + [CompileTimeErrorCode.CONST_SET_ELEMENT_TYPE_IMPLEMENTS_EQUALS]); + verify([source]); + } + + test_constSetElementTypeImplementsEquals_factory() async { + Source source = addSource(r''' +class A { const factory A() = B; } + +class B implements A { + const B(); + + operator ==(o) => true; +} + +main() { + var m = const {const A()}; +} +'''); + await computeAnalysisResult(source); + assertErrors(source, + [CompileTimeErrorCode.CONST_SET_ELEMENT_TYPE_IMPLEMENTS_EQUALS]); + verify([source]); + } + + test_constSetElementTypeImplementsEquals_super() async { + Source source = addSource(r''' +class A { + const A(); + operator ==(other) => false; +} +class B extends A { + const B(); +} +main() { + const {const B()}; +} +'''); + await computeAnalysisResult(source); + assertErrors(source, + [CompileTimeErrorCode.CONST_SET_ELEMENT_TYPE_IMPLEMENTS_EQUALS]); + verify([source]); + } + test_constWithInvalidTypeParameters() async { Source source = addSource(r''' class A { @@ -2406,36 +2548,6 @@ verify([source]); } - test_genericFunctionTypeArgument_class() async { - Source source = addSource(r''' -class C<T> {} -C<T Function<T>(T)> c;'''); - await computeAnalysisResult(source); - assertErrors(source, - [CompileTimeErrorCode.GENERIC_FUNCTION_CANNOT_BE_TYPE_ARGUMENT]); - verify([source]); - } - - test_genericFunctionTypeArgument_function() async { - Source source = addSource(r''' -T f<T>(T) => null; -main() { f<S Function<S>(S)>(null); }'''); - await computeAnalysisResult(source); - assertErrors(source, - [CompileTimeErrorCode.GENERIC_FUNCTION_CANNOT_BE_TYPE_ARGUMENT]); - verify([source]); - } - - test_genericFunctionTypeArgument_functionType() async { - Source source = addSource(r''' -T Function<T>(T) f; -main() { f<S Function<S>(S)>(null); }'''); - await computeAnalysisResult(source); - assertErrors(source, - [CompileTimeErrorCode.GENERIC_FUNCTION_CANNOT_BE_TYPE_ARGUMENT]); - verify([source]); - } - test_genericFunctionTypeArgument_inference_function() async { Source source = addSource(r''' T f<T>(T t) => null; @@ -2465,29 +2577,6 @@ verify([source]); } - test_genericFunctionTypeArgument_method() async { - Source source = addSource(r''' -class C { - T f<T>(T) => null; -} -main() { new C().f<S Function<S>(S)>(null); }'''); - await computeAnalysisResult(source); - assertErrors(source, - [CompileTimeErrorCode.GENERIC_FUNCTION_CANNOT_BE_TYPE_ARGUMENT]); - verify([source]); - } - - test_genericFunctionTypeArgument_typedef() async { - // TODO(mfairhurst) diagnose these parse errors to give the correct error - Source source = addSource(r''' -typedef T f<T>(T t); -final T<Function<S>(int)> x = null;'''); - await computeAnalysisResult(source); - assertErrors(source, - [CompileTimeErrorCode.GENERIC_FUNCTION_CANNOT_BE_TYPE_ARGUMENT]); - verify([source]); - } - test_genericFunctionTypeAsBound_class() async { Source source = addSource(r''' class C<T extends S Function<S>(S)> { @@ -3670,6 +3759,19 @@ verify([source]); } + test_invalidTypeArgumentInConstSet() async { + Source source = addSource(r''' +class A<E> { + m() { + return const <E>{}; + } +}'''); + await computeAnalysisResult(source); + assertErrors( + source, [CompileTimeErrorCode.INVALID_TYPE_ARGUMENT_IN_CONST_SET]); + verify([source]); + } + test_invalidUri_export() async { Source source = addSource("export 'ht:';"); await computeAnalysisResult(source); @@ -4672,6 +4774,48 @@ ]); } + test_nonConstSetElement() async { + Source source = addSource(r''' +f(a) { + return const {a}; +}'''); + await computeAnalysisResult(source); + assertErrors(source, [CompileTimeErrorCode.NON_CONSTANT_SET_ELEMENT]); + verify([source]); + } + + test_nonConstSetElementFromDeferredLibrary() async { + await resolveWithErrors(<String>[ + r''' +library lib1; +const int c = 1;''', + r''' +library root; +import 'lib1.dart' deferred as a; +f() { + return const {a.c}; +}''' + ], [ + CompileTimeErrorCode.NON_CONSTANT_SET_ELEMENT_FROM_DEFERRED_LIBRARY + ]); + } + + test_nonConstSetElementFromDeferredLibrary_nested() async { + await resolveWithErrors(<String>[ + r''' +library lib1; +const int c = 1;''', + r''' +library root; +import 'lib1.dart' deferred as a; +f() { + return const {a.c + 1}; +}''' + ], [ + CompileTimeErrorCode.NON_CONSTANT_SET_ELEMENT_FROM_DEFERRED_LIBRARY + ]); + } + test_nonConstValueInInitializer_assert_condition() async { Source source = addSource(r''' class A { @@ -4730,7 +4874,7 @@ }'''); await computeAnalysisResult(source); assertErrors(source, [ - CompileTimeErrorCode.CONST_EVAL_TYPE_INT, + CompileTimeErrorCode.CONST_EVAL_TYPE_BOOL_INT, StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE ]); verify([source]); @@ -5076,23 +5220,6 @@ verify([source]); } - test_prefix_conditionalPropertyAccess_call() async { - addNamedSource('/lib.dart', ''' -library lib; -g() {} -'''); - Source source = addSource(''' -import 'lib.dart' as p; -f() { - p?.g(); -} -'''); - await computeAnalysisResult(source); - assertErrors( - source, [CompileTimeErrorCode.PREFIX_IDENTIFIER_NOT_FOLLOWED_BY_DOT]); - verify([source]); - } - test_prefix_conditionalPropertyAccess_call_loadLibrary() async { addNamedSource('/lib.dart', ''' library lib; @@ -5175,36 +5302,6 @@ verify([source]); } - test_prefix_unqualified_invocation_in_method() async { - addNamedSource('/lib.dart', 'librarylib;'); - Source source = addSource(''' -import 'lib.dart' as p; -class C { - f() { - p(); - } -} -'''); - await computeAnalysisResult(source); - assertErrors( - source, [CompileTimeErrorCode.PREFIX_IDENTIFIER_NOT_FOLLOWED_BY_DOT]); - verify([source]); - } - - test_prefix_unqualified_invocation_not_in_method() async { - addNamedSource('/lib.dart', 'librarylib;'); - Source source = addSource(''' -import 'lib.dart' as p; -f() { - p(); -} -'''); - await computeAnalysisResult(source); - assertErrors( - source, [CompileTimeErrorCode.PREFIX_IDENTIFIER_NOT_FOLLOWED_BY_DOT]); - verify([source]); - } - test_prefixCollidesWithTopLevelMembers_functionTypeAlias() async { addNamedSource("/lib.dart", r''' library lib; @@ -5423,9 +5520,9 @@ } test_recursiveCompileTimeConstant_fromMapLiteral() async { - resourceProvider.newFile( - resourceProvider.convertPath('/constants.dart'), - r''' + newFile( + '/constants.dart', + content: r''' const int x = y; const int y = x; ''', @@ -6334,7 +6431,7 @@ assertErrors(test, [HintCode.UNUSED_IMPORT]); // Remove the overlay in the same way as AnalysisServer. - resourceProvider.deleteFile(target.fullName); + deleteFile(target.fullName); if (enableNewAnalysisDriver) { driver.removeFile(target.fullName); } else { @@ -6352,7 +6449,7 @@ await computeAnalysisResult(source); assertErrors(source, [CompileTimeErrorCode.URI_DOES_NOT_EXIST]); - String targetPath = resourceProvider.convertPath('/target.dart'); + String targetPath = convertPath('/target.dart'); if (enableNewAnalysisDriver) { // Add an overlay in the same way as AnalysisServer. fileContentOverlay[targetPath] = ''; @@ -6617,6 +6714,21 @@ verify([source]); } + Future<Null> _check_constEvalTypeBoolOrInt_withParameter_binary( + String expr) async { + Source source = addSource(''' +class A { + final a; + const A(int p) : a = $expr; +}'''); + await computeAnalysisResult(source); + assertErrors(source, [ + CompileTimeErrorCode.CONST_EVAL_TYPE_BOOL_INT, + StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE + ]); + verify([source]); + } + Future<Null> _check_constEvalTypeInt_withParameter_binary(String expr) async { Source source = addSource(''' class A {
diff --git a/pkg/analyzer/test/generated/element_resolver_test.dart b/pkg/analyzer/test/generated/element_resolver_test.dart index 75e534a..e553c30 100644 --- a/pkg/analyzer/test/generated/element_resolver_test.dart +++ b/pkg/analyzer/test/generated/element_resolver_test.dart
@@ -1,4 +1,4 @@ -// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file +// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. @@ -829,31 +829,6 @@ _listener.assertNoErrors(); } - test_visitMethodInvocation_namedParameter() async { - ClassElementImpl classA = ElementFactory.classElement2("A"); - String methodName = "m"; - String parameterName = "p"; - MethodElementImpl method = ElementFactory.methodElement(methodName, null); - ParameterElement parameter = ElementFactory.namedParameter(parameterName); - method.parameters = <ParameterElement>[parameter]; - classA.methods = <MethodElement>[method]; - SimpleIdentifier left = AstTestFactory.identifier3("i"); - left.staticType = classA.type; - MethodInvocation invocation = AstTestFactory.methodInvocation( - left, methodName, [ - AstTestFactory.namedExpression2(parameterName, AstTestFactory.integer(0)) - ]); - _resolveNode(invocation); - expect(invocation.methodName.staticElement, same(method)); - expect( - (invocation.argumentList.arguments[0] as NamedExpression) - .name - .label - .staticElement, - same(parameter)); - _listener.assertNoErrors(); - } - test_visitPostfixExpression() async { InterfaceType numType = _typeProvider.numType; SimpleIdentifier operand = AstTestFactory.identifier3("i"); @@ -1290,8 +1265,7 @@ @override void setUp() { - AnalysisOptionsImpl options = new AnalysisOptionsImpl() - ..previewDart2 = true; + AnalysisOptionsImpl options = new AnalysisOptionsImpl(); resetWith(options: options); }
diff --git a/pkg/analyzer/test/generated/hint_code_test.dart b/pkg/analyzer/test/generated/hint_code_test.dart index bcf3bad..18e26cc 100644 --- a/pkg/analyzer/test/generated/hint_code_test.dart +++ b/pkg/analyzer/test/generated/hint_code_test.dart
@@ -1,4 +1,4 @@ -// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file +// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. @@ -106,11 +106,7 @@ n(void f(int i)) {} }'''); await computeAnalysisResult(source); - if (previewDart2) { - assertErrors(source, [StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE]); - } else { - assertErrors(source, [HintCode.ARGUMENT_TYPE_NOT_ASSIGNABLE]); - } + assertErrors(source, [StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE]); verify([source]); } @@ -129,11 +125,7 @@ } n(int i) {}'''); await computeAnalysisResult(source); - if (previewDart2) { - assertErrors(source, [StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE]); - } else { - assertErrors(source, [HintCode.ARGUMENT_TYPE_NOT_ASSIGNABLE]); - } + assertErrors(source, [StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE]); verify([source]); } @@ -1099,11 +1091,7 @@ var v = (x / y).toInt(); }'''); await computeAnalysisResult(source); - if (previewDart2) { - assertNoErrors(source); - } else { - assertErrors(source, [HintCode.DIVISION_OPTIMIZATION]); - } + assertNoErrors(source); verify([source]); } @@ -1395,11 +1383,7 @@ } }'''); await computeAnalysisResult(source); - if (previewDart2) { - assertErrors(source, [StaticTypeWarningCode.INVALID_ASSIGNMENT]); - } else { - assertErrors(source, [HintCode.INVALID_ASSIGNMENT]); - } + assertErrors(source, [StaticTypeWarningCode.INVALID_ASSIGNMENT]); verify([source]); } @@ -1411,11 +1395,7 @@ } }'''); await computeAnalysisResult(source); - if (previewDart2) { - assertErrors(source, [StaticTypeWarningCode.INVALID_ASSIGNMENT]); - } else { - assertErrors(source, [HintCode.INVALID_ASSIGNMENT]); - } + assertErrors(source, [StaticTypeWarningCode.INVALID_ASSIGNMENT]); verify([source]); } @@ -1437,11 +1417,7 @@ } }'''); await computeAnalysisResult(source); - if (previewDart2) { - assertErrors(source, [StaticTypeWarningCode.INVALID_ASSIGNMENT]); - } else { - assertErrors(source, [HintCode.INVALID_ASSIGNMENT]); - } + assertErrors(source, [StaticTypeWarningCode.INVALID_ASSIGNMENT]); verify([source]); } @@ -1461,11 +1437,7 @@ int n = p1 + p2; }'''); await computeAnalysisResult(source); - if (previewDart2) { - assertErrors(source, [StaticTypeWarningCode.INVALID_ASSIGNMENT]); - } else { - assertErrors(source, [HintCode.INVALID_ASSIGNMENT]); - } + assertErrors(source, [StaticTypeWarningCode.INVALID_ASSIGNMENT]); verify([source]); } @@ -3931,11 +3903,7 @@ } }'''); await computeAnalysisResult(source); - if (previewDart2) { - assertErrors(source, [StaticTypeWarningCode.UNDEFINED_GETTER]); - } else { - assertErrors(source, [HintCode.UNDEFINED_GETTER]); - } + assertErrors(source, [StaticTypeWarningCode.UNDEFINED_GETTER]); } test_undefinedIdentifier_exportHide() async { @@ -3980,38 +3948,6 @@ verify([source]); } - test_undefinedMethod() async { - Source source = addSource(r''' -f() { - var a = 'str'; - a.notAMethodOnString(); -}'''); - await computeAnalysisResult(source); - if (previewDart2) { - assertErrors(source, [StaticTypeWarningCode.UNDEFINED_METHOD]); - } else { - assertErrors(source, [HintCode.UNDEFINED_METHOD]); - } - } - - test_undefinedMethod_assignmentExpression() async { - Source source = addSource(r''' -class A {} -class B { - f(var a, var a2) { - a = new A(); - a2 = new A(); - a += a2; - } -}'''); - await computeAnalysisResult(source); - if (previewDart2) { - assertNoErrors(source); - } else { - assertErrors(source, [HintCode.UNDEFINED_METHOD]); - } - } - test_undefinedOperator_binaryExpression() async { Source source = addSource(r''' class A {} @@ -4021,11 +3957,7 @@ } }'''); await computeAnalysisResult(source); - if (previewDart2) { - assertErrors(source, [StaticTypeWarningCode.UNDEFINED_OPERATOR]); - } else { - assertErrors(source, [HintCode.UNDEFINED_OPERATOR]); - } + assertErrors(source, [StaticTypeWarningCode.UNDEFINED_OPERATOR]); } test_undefinedOperator_indexBoth() async { @@ -4037,11 +3969,10 @@ } }'''); await computeAnalysisResult(source); - if (previewDart2) { - assertErrors(source, [StaticTypeWarningCode.UNDEFINED_OPERATOR]); - } else { - assertErrors(source, [HintCode.UNDEFINED_OPERATOR]); - } + assertErrors(source, [ + StaticTypeWarningCode.UNDEFINED_OPERATOR, + StaticTypeWarningCode.UNDEFINED_OPERATOR, + ]); } test_undefinedOperator_indexGetter() async { @@ -4053,11 +3984,7 @@ } }'''); await computeAnalysisResult(source); - if (previewDart2) { - assertErrors(source, [StaticTypeWarningCode.UNDEFINED_OPERATOR]); - } else { - assertErrors(source, [HintCode.UNDEFINED_OPERATOR]); - } + assertErrors(source, [StaticTypeWarningCode.UNDEFINED_OPERATOR]); } test_undefinedOperator_indexSetter() async { @@ -4069,11 +3996,7 @@ } }'''); await computeAnalysisResult(source); - if (previewDart2) { - assertErrors(source, [StaticTypeWarningCode.UNDEFINED_OPERATOR]); - } else { - assertErrors(source, [HintCode.UNDEFINED_OPERATOR]); - } + assertErrors(source, [StaticTypeWarningCode.UNDEFINED_OPERATOR]); } test_undefinedOperator_postfixExpression() async { @@ -4085,11 +4008,7 @@ } }'''); await computeAnalysisResult(source); - if (previewDart2) { - assertNoErrors(source); - } else { - assertErrors(source, [HintCode.UNDEFINED_OPERATOR]); - } + assertNoErrors(source); } test_undefinedOperator_prefixExpression() async { @@ -4101,11 +4020,7 @@ } }'''); await computeAnalysisResult(source); - if (previewDart2) { - assertNoErrors(source); - } else { - assertErrors(source, [HintCode.UNDEFINED_OPERATOR]); - } + assertNoErrors(source); } test_undefinedSetter() async { @@ -4117,11 +4032,7 @@ } }'''); await computeAnalysisResult(source); - if (previewDart2) { - assertErrors(source, [StaticTypeWarningCode.UNDEFINED_SETTER]); - } else { - assertErrors(source, [HintCode.UNDEFINED_SETTER]); - } + assertErrors(source, [StaticTypeWarningCode.UNDEFINED_SETTER]); } test_unnecessaryCast_type_supertype() async {
diff --git a/pkg/analyzer/test/generated/inheritance_manager_test.dart b/pkg/analyzer/test/generated/inheritance_manager_test.dart index fa5b0d4..d6def33 100644 --- a/pkg/analyzer/test/generated/inheritance_manager_test.dart +++ b/pkg/analyzer/test/generated/inheritance_manager_test.dart
@@ -28,7 +28,7 @@ } @reflectiveTest -class InheritanceManagerTest extends Object with ResourceProviderMixin { +class InheritanceManagerTest with ResourceProviderMixin { /** * The type provider used to access the types. */
diff --git a/pkg/analyzer/test/generated/non_error_resolver_driver_test.dart b/pkg/analyzer/test/generated/non_error_resolver_driver_test.dart index c524c9c..da8d07c 100644 --- a/pkg/analyzer/test/generated/non_error_resolver_driver_test.dart +++ b/pkg/analyzer/test/generated/non_error_resolver_driver_test.dart
@@ -31,12 +31,6 @@ @override @failingTest - test_null_callMethod() { - return super.test_null_callMethod(); - } - - @override - @failingTest test_null_callOperator() { return super.test_null_callOperator(); }
diff --git a/pkg/analyzer/test/generated/non_error_resolver_test.dart b/pkg/analyzer/test/generated/non_error_resolver_test.dart index 25ce0a7..2b881c0 100644 --- a/pkg/analyzer/test/generated/non_error_resolver_test.dart +++ b/pkg/analyzer/test/generated/non_error_resolver_test.dart
@@ -1,4 +1,4 @@ -// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file +// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. @@ -16,7 +16,6 @@ import 'package:test_reflective_loader/test_reflective_loader.dart'; import 'resolver_test_case.dart'; -import 'test_support.dart'; main() { defineReflectiveSuite(() { @@ -76,12 +75,6 @@ @override @failingTest - test_null_callMethod() { - return super.test_null_callMethod(); - } - - @override - @failingTest test_null_callOperator() { return super.test_null_callOperator(); } @@ -307,7 +300,7 @@ } test_argumentTypeNotAssignable_optionalNew() async { - resetWith(options: new AnalysisOptionsImpl()..previewDart2 = true); + resetWith(options: new AnalysisOptionsImpl()); Source source = addSource(r''' class Widget { } @@ -978,220 +971,6 @@ expect(classC.documentationComment, isNotNull); } - test_commentReference_beforeConstructor() async { - String code = r''' -abstract class A { - /// [p] - A(int p) {} -}'''; - Source source = addSource(code); - TestAnalysisResult analysisResult = await computeAnalysisResult(source); - assertNoErrors(source); - verify([source]); - CompilationUnit unit = analysisResult.unit; - { - SimpleIdentifier ref = - EngineTestCase.findSimpleIdentifier(unit, code, "p]"); - expect(ref.staticElement, new TypeMatcher<ParameterElement>()); - } - } - - test_commentReference_beforeEnum() async { - String code = r''' -/// This is the [Samurai] kind. -enum Samurai { - /// Use [int]. - WITH_SWORD, - /// Like [WITH_SWORD], but only without one. - WITHOUT_SWORD -}'''; - Source source = addSource(code); - TestAnalysisResult analysisResult = await computeAnalysisResult(source); - assertNoErrors(source); - verify([source]); - CompilationUnit unit = analysisResult.unit; - { - SimpleIdentifier ref = - EngineTestCase.findSimpleIdentifier(unit, code, 'Samurai]'); - ClassElement refElement = ref.staticElement; - expect(refElement, isNotNull); - expect(refElement.name, 'Samurai'); - } - { - SimpleIdentifier ref = - EngineTestCase.findSimpleIdentifier(unit, code, 'int]'); - ClassElement refElement = ref.staticElement; - expect(refElement, isNotNull); - expect(refElement.name, 'int'); - } - { - SimpleIdentifier ref = - EngineTestCase.findSimpleIdentifier(unit, code, 'WITH_SWORD]'); - PropertyAccessorElement refElement = ref.staticElement; - expect(refElement, isNotNull); - expect(refElement.name, 'WITH_SWORD'); - } - } - - test_commentReference_beforeFunction_blockBody() async { - String code = r''' -/// [p] -foo(int p) { -}'''; - Source source = addSource(code); - TestAnalysisResult analysisResult = await computeAnalysisResult(source); - assertNoErrors(source); - verify([source]); - CompilationUnit unit = analysisResult.unit; - SimpleIdentifier ref = - EngineTestCase.findSimpleIdentifier(unit, code, 'p]'); - expect(ref.staticElement, new TypeMatcher<ParameterElement>()); - } - - test_commentReference_beforeFunction_expressionBody() async { - String code = r''' -/// [p] -foo(int p) => null;'''; - Source source = addSource(code); - TestAnalysisResult analysisResult = await computeAnalysisResult(source); - assertNoErrors(source); - verify([source]); - CompilationUnit unit = analysisResult.unit; - SimpleIdentifier ref = - EngineTestCase.findSimpleIdentifier(unit, code, 'p]'); - expect(ref.staticElement, new TypeMatcher<ParameterElement>()); - } - - test_commentReference_beforeFunctionTypeAlias() async { - String code = r''' -/// [p] -typedef Foo(int p); -'''; - Source source = addSource(code); - TestAnalysisResult analysisResult = await computeAnalysisResult(source); - assertNoErrors(source); - verify([source]); - CompilationUnit unit = analysisResult.unit; - SimpleIdentifier ref = - EngineTestCase.findSimpleIdentifier(unit, code, 'p]'); - expect(ref.staticElement, new TypeMatcher<ParameterElement>()); - } - - test_commentReference_beforeGenericTypeAlias() async { - String code = r''' -/// Can resolve [T], [S], and [p]. -typedef Foo<T> = Function<S>(int p); -'''; - Source source = addSource(code); - TestAnalysisResult analysisResult = await computeAnalysisResult(source); - assertNoErrors(source); - verify([source]); - CompilationUnit unit = analysisResult.unit; - - Element getElement(String search) { - return EngineTestCase.findSimpleIdentifier(unit, code, search) - .staticElement; - } - - expect(getElement('T]'), new TypeMatcher<TypeParameterElement>()); - expect(getElement('S]'), new TypeMatcher<TypeParameterElement>()); - expect(getElement('p]'), new TypeMatcher<ParameterElement>()); - } - - test_commentReference_beforeGetter() async { - String code = r''' -abstract class A { - /// [int] - get g => null; -}'''; - Source source = addSource(code); - TestAnalysisResult analysisResult = await computeAnalysisResult(source); - assertNoErrors(source); - verify([source]); - CompilationUnit unit = analysisResult.unit; - { - SimpleIdentifier ref = - EngineTestCase.findSimpleIdentifier(unit, code, 'int]'); - expect(ref.staticElement, isNotNull); - } - } - - test_commentReference_beforeMethod() async { - String code = r''' -abstract class A { - /// [p1] - ma(int p1) {} - /// [p2] - mb(int p2); - /// [p3] and [p4] - mc(int p3, p4()); - /// [p5] - md(int p5, {int p6}); -}'''; - Source source = addSource(code); - TestAnalysisResult analysisResult = await computeAnalysisResult(source); - assertNoErrors(source); - verify([source]); - CompilationUnit unit = analysisResult.unit; - assertIsParameter(String search) { - SimpleIdentifier ref = - EngineTestCase.findSimpleIdentifier(unit, code, search); - expect(ref.staticElement, new TypeMatcher<ParameterElement>()); - } - - assertIsParameter('p1'); - assertIsParameter('p2'); - assertIsParameter('p3'); - assertIsParameter('p4'); - assertIsParameter('p5'); - assertIsParameter('p6'); - } - - test_commentReference_class() async { - String code = r''' -/// [foo] -class A { - foo() {} -}'''; - Source source = addSource(code); - TestAnalysisResult analysisResult = await computeAnalysisResult(source); - assertNoErrors(source); - verify([source]); - CompilationUnit unit = analysisResult.unit; - SimpleIdentifier ref = - EngineTestCase.findSimpleIdentifier(unit, code, 'foo]'); - expect(ref.staticElement, new TypeMatcher<MethodElement>()); - } - - test_commentReference_setter() async { - String code = r''' -class A { - /// [x] in A - mA() {} - set x(value) {} -} -class B extends A { - /// [x] in B - mB() {} -} -'''; - Source source = addSource(code); - TestAnalysisResult analysisResult = await computeAnalysisResult(source); - assertNoErrors(source); - verify([source]); - CompilationUnit unit = analysisResult.unit; - { - SimpleIdentifier ref = - EngineTestCase.findSimpleIdentifier(unit, code, "x] in A"); - expect(ref.staticElement, new TypeMatcher<PropertyAccessorElement>()); - } - { - SimpleIdentifier ref = - EngineTestCase.findSimpleIdentifier(unit, code, 'x] in B'); - expect(ref.staticElement, new TypeMatcher<PropertyAccessorElement>()); - } - } - test_concreteClassWithAbstractMember() async { Source source = addSource(r''' abstract class A { @@ -2864,7 +2643,6 @@ } test_intLiteralInDoubleContext_const_exact() async { - // TODO(mfairhurst): get the commented out assertions to pass. Source source = addSource(r''' class C { const C(double x) @@ -3450,86 +3228,6 @@ verify([source]); } - test_invocationOfNonFunction_dynamic() async { - Source source = addSource(r''' -class A { - var f; -} -class B extends A { - g() { - f(); - } -}'''); - await computeAnalysisResult(source); - assertNoErrors(source); - verify([source]); - } - - test_invocationOfNonFunction_functionTypeTypeParameter() async { - Source source = addSource(r''' -typedef void Action<T>(T x); -class C<T, U extends Action<T>> { - T value; - U action; - C(this.value, [this.action]); - void act() { - action(value); - } -} -'''); - await computeAnalysisResult(source); - assertNoErrors(source); - verify([source]); - } - - test_invocationOfNonFunction_getter() async { - Source source = addSource(r''' -class A { - var g; -} -f() { - A a; - a.g(); -}'''); - await computeAnalysisResult(source); - assertNoErrors(source); - verify([source]); - } - - test_invocationOfNonFunction_localVariable() async { - Source source = addSource(r''' -f() { - var g; - g(); -}'''); - await computeAnalysisResult(source); - assertNoErrors(source); - verify([source]); - } - - test_invocationOfNonFunction_localVariable_dynamic() async { - Source source = addSource(r''' -f() {} -main() { - var v = f; - v(); -}'''); - await computeAnalysisResult(source); - assertNoErrors(source); - verify([source]); - } - - test_invocationOfNonFunction_Object() async { - Source source = addSource(r''' -main() { - Object v = null; - v(); -}'''); - await computeAnalysisResult(source); - assertErrors(source, [StaticTypeWarningCode.INVOCATION_OF_NON_FUNCTION]); - verify([source]); - } - Future test_issue32114() async { addNamedSource('/a.dart', ''' class O {} @@ -4795,15 +4493,6 @@ verify([source]); } - test_null_callMethod() async { - Source source = addSource(r''' -main() { - null.m(); -}'''); - await computeAnalysisResult(source); - assertErrors(source, [StaticTypeWarningCode.UNDEFINED_METHOD]); - } - test_null_callOperator() async { Source source = addSource(r''' main() { @@ -4819,7 +4508,7 @@ } test_optionalNew_rewrite() async { - resetWith(options: new AnalysisOptionsImpl()..previewDart2 = true); + resetWith(options: new AnalysisOptionsImpl()); Source source = addSource(r''' import 'b.dart'; main() { @@ -4859,7 +4548,7 @@ } test_optionalNew_rewrite_instantiatesToBounds() async { - resetWith(options: new AnalysisOptionsImpl()..previewDart2 = true); + resetWith(options: new AnalysisOptionsImpl()); Source source = addSource(r''' import 'b.dart'; @@ -5156,6 +4845,16 @@ verify([source]); } + test_regress34906() async { + Source source = addSource(r''' +typedef G<X, Y extends Function(X)> = X Function(Function(Y)); +G<dynamic, Function(Null)> superBoundedG; +'''); + await computeAnalysisResult(source); + assertNoErrors(source); + verify([source]); + } + test_rethrowOutsideCatch() async { Source source = addSource(r''' class A { @@ -6078,20 +5777,6 @@ verify([source]); } - test_unqualifiedReferenceToNonLocalStaticMember_fromComment_new() async { - Source source = addSource(r''' -class A { - A() {} - A.named() {} -} -/// [new A] or [new A.named] -main() { -}'''); - await computeAnalysisResult(source); - assertNoErrors(source); - verify([source]); - } - test_unusedShownName_unresolved() async { Source source = addSource(r''' import 'dart:math' show max, FooBar;
diff --git a/pkg/analyzer/test/generated/non_hint_code_test.dart b/pkg/analyzer/test/generated/non_hint_code_test.dart index b6053b6..962865a 100644 --- a/pkg/analyzer/test/generated/non_hint_code_test.dart +++ b/pkg/analyzer/test/generated/non_hint_code_test.dart
@@ -700,14 +700,10 @@ int c; }'''); await computeAnalysisResult(source); - if (previewDart2) { - assertErrors( - source, - [CompileTimeErrorCode.INVALID_OVERRIDE], - ); - } else { - assertNoErrors(source); - } + assertErrors( + source, + [CompileTimeErrorCode.INVALID_OVERRIDE], + ); verify([source]); } @@ -727,14 +723,10 @@ int c; }'''); await computeAnalysisResult(source); - if (previewDart2) { - assertErrors( - source, - [CompileTimeErrorCode.INVALID_OVERRIDE], - ); - } else { - assertNoErrors(source); - } + assertErrors( + source, + [CompileTimeErrorCode.INVALID_OVERRIDE], + ); verify([source]); } @@ -943,11 +935,7 @@ } }'''); await computeAnalysisResult(source); - if (previewDart2) { - assertErrors(source, [StaticTypeWarningCode.UNDEFINED_GETTER]); - } else { - assertNoErrors(source); - } + assertErrors(source, [StaticTypeWarningCode.UNDEFINED_GETTER]); } test_undefinedMethod_assignmentExpression_inSubtype() async { @@ -975,24 +963,6 @@ assertNoErrors(source); } - test_undefinedMethod_inSubtype() async { - Source source = addSource(r''' -class A {} -class B extends A { - b() {} -} -f() { - var a = new A(); - a.b(); -}'''); - await computeAnalysisResult(source); - if (previewDart2) { - assertErrors(source, [StaticTypeWarningCode.UNDEFINED_METHOD]); - } else { - assertNoErrors(source); - } - } - test_undefinedMethod_unionType_all() async { Source source = addSource(r''' class A { @@ -1045,11 +1015,7 @@ } }'''); await computeAnalysisResult(source); - if (previewDart2) { - assertErrors(source, [StaticTypeWarningCode.UNDEFINED_OPERATOR]); - } else { - assertNoErrors(source); - } + assertErrors(source, [StaticTypeWarningCode.UNDEFINED_OPERATOR]); } test_undefinedOperator_indexBoth_inSubtype() async { @@ -1064,11 +1030,10 @@ } }'''); await computeAnalysisResult(source); - if (previewDart2) { - assertErrors(source, [StaticTypeWarningCode.UNDEFINED_OPERATOR]); - } else { - assertNoErrors(source); - } + assertErrors(source, [ + StaticTypeWarningCode.UNDEFINED_OPERATOR, + StaticTypeWarningCode.UNDEFINED_OPERATOR, + ]); } test_undefinedOperator_indexGetter_inSubtype() async { @@ -1083,11 +1048,7 @@ } }'''); await computeAnalysisResult(source); - if (previewDart2) { - assertErrors(source, [StaticTypeWarningCode.UNDEFINED_OPERATOR]); - } else { - assertNoErrors(source); - } + assertErrors(source, [StaticTypeWarningCode.UNDEFINED_OPERATOR]); } test_undefinedOperator_indexSetter_inSubtype() async { @@ -1102,11 +1063,7 @@ } }'''); await computeAnalysisResult(source); - if (previewDart2) { - assertErrors(source, [StaticTypeWarningCode.UNDEFINED_OPERATOR]); - } else { - assertNoErrors(source); - } + assertErrors(source, [StaticTypeWarningCode.UNDEFINED_OPERATOR]); } test_undefinedOperator_postfixExpression() async { @@ -1151,11 +1108,7 @@ } }'''); await computeAnalysisResult(source); - if (previewDart2) { - assertErrors(source, [StaticTypeWarningCode.UNDEFINED_SETTER]); - } else { - assertNoErrors(source); - } + assertErrors(source, [StaticTypeWarningCode.UNDEFINED_SETTER]); } test_unnecessaryCast_13855_parameter_A() async { @@ -1236,7 +1189,7 @@ (c ? f(): new Future.value(0) as Future<int>).then((int value) {}); }'''); await computeAnalysisResult(source); - if (previewDart2 && enableNewAnalysisDriver) { + if (enableNewAnalysisDriver) { assertErrors(source, [HintCode.UNNECESSARY_CAST]); } else { assertNoErrors(source);
diff --git a/pkg/analyzer/test/generated/package_test.dart b/pkg/analyzer/test/generated/package_test.dart deleted file mode 100644 index 1921f63..0000000 --- a/pkg/analyzer/test/generated/package_test.dart +++ /dev/null
@@ -1,261 +0,0 @@ -// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file -// for details. All rights reserved. Use of this source code is governed by a -// BSD-style license that can be found in the LICENSE file. - -import 'package:analyzer/exception/exception.dart'; -import 'package:analyzer/file_system/file_system.dart'; -import 'package:analyzer/src/generated/engine.dart'; -import 'package:analyzer/src/generated/package.dart'; -import 'package:analyzer/src/generated/sdk.dart'; -import 'package:analyzer/src/generated/source.dart'; -import 'package:package_config/packages.dart'; -import 'package:test/test.dart'; -import 'package:test_reflective_loader/test_reflective_loader.dart'; - -import '../src/context/mock_sdk.dart'; -import 'resolver_test_case.dart'; - -main() { - defineReflectiveSuite(() { - defineReflectiveTests(DependencyFinderTest); - defineReflectiveTests(PackageDescriptionTest); - defineReflectiveTests(PackageManagerTest); - }); -} - -/** - * The name of the pubspec.yaml file. - */ -const String pubspecName = 'pubspec.yaml'; - -@reflectiveTest -class DependencyFinderTest extends ResolverTestCase { - void test_transitiveDependenciesFor_circularDependencies() { - var pathContext = resourceProvider.pathContext; - String packageA = resourceProvider.convertPath('/pub-cache/a-1.0'); - String packageB = resourceProvider.convertPath('/pub-cache/b-1.0'); - String packageC = resourceProvider.convertPath('/pub-cache/c-1.0'); - resourceProvider.newFile(pathContext.join(packageA, pubspecName), ''' - dependencies: - b: any - '''); - resourceProvider.newFile(pathContext.join(packageB, pubspecName), ''' - dependencies: - c: any - '''); - resourceProvider.newFile(pathContext.join(packageC, pubspecName), ''' - dependencies: - a: any - '''); - Map<String, List<Folder>> packageMap = <String, List<Folder>>{ - 'a': <Folder>[resourceProvider.getFolder(packageA)], - 'b': <Folder>[resourceProvider.getFolder(packageB)], - 'c': <Folder>[resourceProvider.getFolder(packageC)], - }; - - DependencyFinder finder = new DependencyFinder(resourceProvider); - List<String> result = - finder.transitiveDependenciesFor(packageMap, packageA); - expect(result, unorderedEquals([packageB, packageC])); - } - - void test_transitiveDependenciesFor_missingPubspec() { - String packagePath = resourceProvider.convertPath('/pub-cache/a-1.0'); - Map<String, List<Folder>> packageMap = <String, List<Folder>>{ - 'a': <Folder>[resourceProvider.getFolder(packagePath)] - }; - - DependencyFinder finder = new DependencyFinder(resourceProvider); - expect(() => finder.transitiveDependenciesFor(packageMap, packagePath), - throwsA(new TypeMatcher<AnalysisException>())); - } - - void test_transitiveDependenciesFor_noDependencies() { - var pathContext = resourceProvider.pathContext; - String packagePath = resourceProvider.convertPath('/pub-cache/a-1.0'); - resourceProvider.newFile(pathContext.join(packagePath, pubspecName), ''); - Map<String, List<Folder>> packageMap = <String, List<Folder>>{ - 'a': <Folder>[resourceProvider.getFolder(packagePath)] - }; - - DependencyFinder finder = new DependencyFinder(resourceProvider); - List<String> result = - finder.transitiveDependenciesFor(packageMap, packagePath); - expect(result, hasLength(0)); - } - - void test_transitiveDependenciesFor_overlappingDependencies() { - var pathContext = resourceProvider.pathContext; - String packageA = resourceProvider.convertPath('/pub-cache/a-1.0'); - String packageB = resourceProvider.convertPath('/pub-cache/b-1.0'); - String packageC = resourceProvider.convertPath('/pub-cache/c-1.0'); - String packageD = resourceProvider.convertPath('/pub-cache/d-1.0'); - resourceProvider.newFile(pathContext.join(packageA, pubspecName), ''' - dependencies: - b: any - c: any - '''); - resourceProvider.newFile(pathContext.join(packageB, pubspecName), ''' - dependencies: - d: any - '''); - resourceProvider.newFile(pathContext.join(packageC, pubspecName), ''' - dependencies: - d: any - '''); - resourceProvider.newFile(pathContext.join(packageD, pubspecName), ''); - Map<String, List<Folder>> packageMap = <String, List<Folder>>{ - 'a': <Folder>[resourceProvider.getFolder(packageA)], - 'b': <Folder>[resourceProvider.getFolder(packageB)], - 'c': <Folder>[resourceProvider.getFolder(packageC)], - 'd': <Folder>[resourceProvider.getFolder(packageD)], - }; - - DependencyFinder finder = new DependencyFinder(resourceProvider); - List<String> result = - finder.transitiveDependenciesFor(packageMap, packageA); - expect(result, unorderedEquals([packageB, packageC, packageD])); - } - - void test_transitiveDependenciesFor_simpleDependencies() { - var pathContext = resourceProvider.pathContext; - String packageA = resourceProvider.convertPath('/pub-cache/a-1.0'); - String packageB = resourceProvider.convertPath('/pub-cache/b-1.0'); - String packageC = resourceProvider.convertPath('/pub-cache/c-1.0'); - resourceProvider.newFile(pathContext.join(packageA, pubspecName), ''' - dependencies: - b: any - c: any - '''); - resourceProvider.newFile(pathContext.join(packageB, pubspecName), ''); - resourceProvider.newFile(pathContext.join(packageC, pubspecName), ''); - Map<String, List<Folder>> packageMap = <String, List<Folder>>{ - 'a': <Folder>[resourceProvider.getFolder(packageA)], - 'b': <Folder>[resourceProvider.getFolder(packageB)], - 'c': <Folder>[resourceProvider.getFolder(packageC)], - }; - - DependencyFinder finder = new DependencyFinder(resourceProvider); - List<String> result = - finder.transitiveDependenciesFor(packageMap, packageA); - expect(result, unorderedEquals([packageB, packageC])); - } -} - -@reflectiveTest -class PackageDescriptionTest extends ResolverTestCase { - void test_equal_false_differentOptions() { - String packageId = 'path1;path2'; - DartSdk sdk = new MockSdk(); - AnalysisOptionsImpl options1 = new AnalysisOptionsImpl(); - AnalysisOptionsImpl options2 = new AnalysisOptionsImpl(); - options2.enableLazyAssignmentOperators = - !options1.enableLazyAssignmentOperators; - PackageDescription first = new PackageDescription(packageId, sdk, options1); - PackageDescription second = - new PackageDescription(packageId, sdk, options2); - expect(first == second, isFalse); - } - - void test_equal_false_differentPaths() { - String packageId1 = 'path1;path2'; - String packageId2 = 'path1;path3'; - DartSdk sdk = new MockSdk(); - AnalysisOptions options = new AnalysisOptionsImpl(); - PackageDescription first = new PackageDescription(packageId1, sdk, options); - PackageDescription second = - new PackageDescription(packageId2, sdk, options); - expect(first == second, isFalse); - } - - void test_equal_false_differentSdks() { - String packageId = 'path1;path2'; - DartSdk sdk1 = new MockSdk(); - DartSdk sdk2 = new MockSdk(); - AnalysisOptions options = new AnalysisOptionsImpl(); - PackageDescription first = new PackageDescription(packageId, sdk1, options); - PackageDescription second = - new PackageDescription(packageId, sdk2, options); - expect(first == second, isFalse); - } - - void test_equal_true() { - String packageId = 'path1;path2'; - DartSdk sdk = new MockSdk(); - AnalysisOptions options = new AnalysisOptionsImpl(); - PackageDescription first = new PackageDescription(packageId, sdk, options); - PackageDescription second = new PackageDescription(packageId, sdk, options); - expect(first == second, isTrue); - } -} - -@reflectiveTest -class PackageManagerTest extends ResolverTestCase { - void test_getContext() { - var pathContext = resourceProvider.pathContext; - String packageA = resourceProvider.convertPath('/pub-cache/a-1.0'); - String packageB1 = resourceProvider.convertPath('/pub-cache/b-1.0'); - String packageB2 = resourceProvider.convertPath('/pub-cache/b-2.0'); - String packageC = resourceProvider.convertPath('/pub-cache/c-1.0'); - resourceProvider.newFile(pathContext.join(packageA, pubspecName), ''' - dependencies: - b: any - c: any - '''); - resourceProvider.newFile(pathContext.join(packageB1, pubspecName), ''); - resourceProvider.newFile(pathContext.join(packageB2, pubspecName), ''); - resourceProvider.newFile(pathContext.join(packageC, pubspecName), ''); - - Packages packages1 = new _MockPackages(<String, Uri>{ - 'a': pathContext.toUri(packageA), - 'b': pathContext.toUri(packageB1), - 'c': pathContext.toUri(packageC), - }); - DartUriResolver resolver = new DartUriResolver(new MockSdk()); - AnalysisOptions options = new AnalysisOptionsImpl(); - // - // Verify that we can compute a context for a package. - // - PackageManager manager = new PackageManager(resourceProvider); - AnalysisContext context1 = - manager.getContext(packageA, packages1, resolver, options); - expect(context1, isNotNull); - // - // Verify that if we have the same package map we get the same context. - // - AnalysisContext context2 = - manager.getContext(packageA, packages1, resolver, options); - expect(context2, same(context1)); - // - // Verify that if we have a different package map we get a different context. - // - Packages packages3 = new _MockPackages(<String, Uri>{ - 'a': pathContext.toUri(packageA), - 'b': pathContext.toUri(packageB2), - 'c': pathContext.toUri(packageC), - }); - AnalysisContext context3 = - manager.getContext(packageA, packages3, resolver, options); - expect(context3, isNot(same(context1))); - } -} - -/** - * An implementation of [Packages] used for testing. - */ -class _MockPackages implements Packages { - final Map<String, Uri> map; - - _MockPackages(this.map); - - @override - Iterable<String> get packages => map.keys; - - @override - Map<String, Uri> asMap() => map; - - @override - Uri resolve(Uri packageUri, {Uri notFound(Uri packageUri)}) { - fail('Unexpected invocation of resolve'); - } -}
diff --git a/pkg/analyzer/test/generated/parser_fasta_test.dart b/pkg/analyzer/test/generated/parser_fasta_test.dart index 2e121cc..055692f 100644 --- a/pkg/analyzer/test/generated/parser_fasta_test.dart +++ b/pkg/analyzer/test/generated/parser_fasta_test.dart
@@ -1,4 +1,4 @@ -// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file +// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. @@ -14,9 +14,9 @@ import 'package:analyzer/src/generated/parser.dart' as analyzer; import 'package:analyzer/src/generated/utilities_dart.dart'; import 'package:analyzer/src/string_source.dart'; +import 'package:front_end/src/fasta/parser/parser.dart' as fasta; import 'package:front_end/src/fasta/scanner.dart' show ScannerResult, scanString; -import 'package:front_end/src/fasta/parser/parser.dart' as fasta; import 'package:front_end/src/fasta/scanner/error_token.dart' show ErrorToken; import 'package:front_end/src/fasta/scanner/string_scanner.dart'; import 'package:front_end/src/scanner/errors.dart' show translateErrorToken; @@ -190,13 +190,140 @@ // Actual: TokenType:<MINUS_MINUS> super.test_parseUnaryExpression_decrement_super_withComment(); } + + void test_mapLiteral() { + MapLiteral map = parseExpression('{3: 6}', parseSetLiterals: true); + expect(map.constKeyword, isNull); + expect(map.typeArguments, isNull); + expect(map.entries, hasLength(1)); + MapLiteralEntry entry = map.entries[0]; + IntegerLiteral key = entry.key; + expect(key.value, 3); + IntegerLiteral value = entry.value; + expect(value.value, 6); + } + + void test_mapLiteral_const() { + MapLiteral map = parseExpression('const {3: 6}', parseSetLiterals: true); + expect(map.constKeyword, isNotNull); + expect(map.typeArguments, isNull); + expect(map.entries, hasLength(1)); + MapLiteralEntry entry = map.entries[0]; + IntegerLiteral key = entry.key; + expect(key.value, 3); + IntegerLiteral value = entry.value; + expect(value.value, 6); + } + + void test_setLiteral() { + SetLiteral set = parseExpression('{3}', parseSetLiterals: true); + expect(set.constKeyword, isNull); + expect(set.typeArguments, isNull); + expect(set.elements, hasLength(1)); + IntegerLiteral value = set.elements[0]; + expect(value.value, 3); + } + + void test_setLiteral_const() { + SetLiteral set = parseExpression('const {3, 6}', parseSetLiterals: true); + expect(set.constKeyword, isNotNull); + expect(set.typeArguments, isNull); + expect(set.elements, hasLength(2)); + IntegerLiteral value1 = set.elements[0]; + expect(value1.value, 3); + IntegerLiteral value2 = set.elements[1]; + expect(value2.value, 6); + } + + void test_setLiteral_const_typeArgument() { + SetLiteral set = parseExpression('const <int>{3}', parseSetLiterals: true); + expect(set.constKeyword, isNotNull); + expect(set.typeArguments.arguments, hasLength(1)); + NamedType typeArg = set.typeArguments.arguments[0]; + expect(typeArg.name.name, 'int'); + expect(set.elements.length, 1); + IntegerLiteral value = set.elements[0]; + expect(value.value, 3); + } + + void test_setLiteral_invalid_map_entry() { + parseExpression('<int>{1: 1}', parseSetLiterals: true, errors: [ + expectedError(ParserErrorCode.EXPECTED_TOKEN, 7, 1), + ]); + } + + @failingTest + void test_setLiteral_invalid_too_many_type_arguments1() { + parseExpression('<int, int, int>{}', parseSetLiterals: true, errors: [ + // TODO(danrubel): Currently the resolver reports invalid number of + // type arguments, but the parser could report this. + expectedError( + /* ParserErrorCode.EXPECTED_ONE_TYPE_VARIABLE */ + ParserErrorCode.EXPECTED_TOKEN, + 15, + 1), + ]); + } + + @failingTest + void test_setLiteral_invalid_too_many_type_arguments2() { + parseExpression('<int, int, int>{1}', parseSetLiterals: true, errors: [ + // TODO(danrubel): Currently the resolver reports invalid number of + // type arguments, but the parser could report this. + expectedError( + /* ParserErrorCode.EXPECTED_ONE_TYPE_VARIABLE */ + ParserErrorCode.EXPECTED_TOKEN, + 15, + 1), + ]); + } + + @failingTest + void test_setLiteral_invalid_too_many_type_arguments3() { + parseExpression('<int, int>{1}', parseSetLiterals: true, errors: [ + // TODO(danrubel): Currently the resolver reports invalid number of + // type arguments, but the parser could report this. + expectedError( + /* ParserErrorCode.EXPECTED_ONE_TYPE_VARIABLE */ + ParserErrorCode.EXPECTED_TOKEN, + 10, + 1), + ]); + } + + void test_setLiteral_nested_typeArgument() { + SetLiteral set = parseExpression('<Set<int>>{{3}}', parseSetLiterals: true); + expect(set.constKeyword, isNull); + expect(set.typeArguments.arguments, hasLength(1)); + NamedType typeArg1 = set.typeArguments.arguments[0]; + expect(typeArg1.name.name, 'Set'); + expect(typeArg1.typeArguments.arguments, hasLength(1)); + NamedType typeArg2 = typeArg1.typeArguments.arguments[0]; + expect(typeArg2.name.name, 'int'); + expect(set.elements.length, 1); + SetLiteral intSet = set.elements[0]; + expect(intSet.elements, hasLength(1)); + IntegerLiteral value = intSet.elements[0]; + expect(value.value, 3); + } + + void test_setLiteral_typeArgument() { + SetLiteral set = parseExpression('<int>{3}', parseSetLiterals: true); + expect(set.constKeyword, isNull); + expect(set.typeArguments.arguments, hasLength(1)); + NamedType typeArg = set.typeArguments.arguments[0]; + expect(typeArg.name.name, 'int'); + expect(set.elements.length, 1); + IntegerLiteral value = set.elements[0]; + expect(value.value, 3); + } } /** * Implementation of [AbstractParserTestCase] specialized for testing the * Fasta parser. */ -class FastaParserTestCase extends Object +class FastaParserTestCase with ParserTestHelpers implements AbstractParserTestCase { static final List<ErrorCode> NO_ERROR_COMPARISON = <ErrorCode>[]; @@ -446,8 +573,10 @@ Expression parseExpression(String source, {List<ErrorCode> codes, List<ExpectedError> errors, - int expectedEndOffset}) { + int expectedEndOffset, + bool parseSetLiterals = false}) { createParser(source, expectedEndOffset: expectedEndOffset); + _parserProxy.fastaParser.parseSetLiterals = parseSetLiterals; Expression result = _parserProxy.parseExpression2(); assertErrors(codes: codes, errors: errors); return result; @@ -900,6 +1029,15 @@ @reflectiveTest class RecoveryParserTest_Fasta extends FastaParserTestCase with RecoveryParserTestMixin { + @override + void test_equalityExpression_precedence_relational_right() { + parseExpression("== is", codes: [ + ParserErrorCode.EXPECTED_TYPE_NAME, + ParserErrorCode.MISSING_IDENTIFIER, + ParserErrorCode.MISSING_IDENTIFIER + ]); + } + void test_invalidTypeParameters_super() { parseCompilationUnit('class C<X super Y> {}', errors: [ // TODO(danrubel): Improve recovery. @@ -916,15 +1054,6 @@ } @override - void test_equalityExpression_precedence_relational_right() { - parseExpression("== is", codes: [ - ParserErrorCode.EXPECTED_TYPE_NAME, - ParserErrorCode.MISSING_IDENTIFIER, - ParserErrorCode.MISSING_IDENTIFIER - ]); - } - - @override void test_relationalExpression_missing_LHS_RHS() { parseExpression("is", codes: [ ParserErrorCode.EXPECTED_TYPE_NAME,
diff --git a/pkg/analyzer/test/generated/parser_test.dart b/pkg/analyzer/test/generated/parser_test.dart index db03ec1..2c4ce93 100644 --- a/pkg/analyzer/test/generated/parser_test.dart +++ b/pkg/analyzer/test/generated/parser_test.dart
@@ -251,7 +251,7 @@ * Instances of the class `AstValidator` are used to validate the correct construction of an * AST structure. */ -class AstValidator extends UnifyingAstVisitor<Object> { +class AstValidator extends UnifyingAstVisitor<void> { /** * A list containing the errors found while traversing the AST structure. */ @@ -274,9 +274,9 @@ } @override - Object visitNode(AstNode node) { + void visitNode(AstNode node) { _validate(node); - return super.visitNode(node); + super.visitNode(node); } /** @@ -335,7 +335,7 @@ /** * Tests which exercise the parser using a class member. */ -abstract class ClassMemberParserTestMixin implements AbstractParserTestCase { +mixin ClassMemberParserTestMixin implements AbstractParserTestCase { void test_parseAwaitExpression_asStatement_inAsync() { createParser('m() async { await x; }'); ClassMember member = parser.parseClassMember('C'); @@ -1771,7 +1771,7 @@ * * Simpler tests should be defined in the class [SimpleParserTest]. */ -abstract class ComplexParserTestMixin implements AbstractParserTestCase { +mixin ComplexParserTestMixin implements AbstractParserTestCase { void test_additiveExpression_normal() { BinaryExpression expression = parseExpression("x + y - z"); EngineTestCase.assertInstanceOf((obj) => obj is BinaryExpression, @@ -2260,7 +2260,7 @@ } } -abstract class ErrorParserTestMixin implements AbstractParserTestCase { +mixin ErrorParserTestMixin implements AbstractParserTestCase { void test_abstractClassMember_constructor() { createParser('abstract C.c();'); ClassMember member = parser.parseClassMember('C'); @@ -5733,7 +5733,7 @@ class ExpressionParserTest extends ParserTestCase with ExpressionParserTestMixin {} -abstract class ExpressionParserTestMixin implements AbstractParserTestCase { +mixin ExpressionParserTestMixin implements AbstractParserTestCase { void test_namedArgument() { var invocation = parseExpression('m(a: 1, b: 2)') as MethodInvocation; List<Expression> arguments = invocation.argumentList.arguments; @@ -8048,8 +8048,7 @@ * The class [FormalParameterParserTestMixin] defines parser tests that test * the parsing of formal parameters. */ -abstract class FormalParameterParserTestMixin - implements AbstractParserTestCase { +mixin FormalParameterParserTestMixin implements AbstractParserTestCase { void test_parseConstructorParameter_this() { parseCompilationUnit(''' class C { @@ -9943,7 +9942,7 @@ * * Intended to be mixed in to parser test case classes. */ -class ParserTestHelpers { +mixin ParserTestHelpers { void expectCommentText(Comment comment, String expectedText) { expect(comment.beginToken, same(comment.endToken)); expect(comment.beginToken.lexeme, expectedText); @@ -9972,7 +9971,7 @@ * invalid code sequences to ensure that the correct recovery steps are taken in * the parser. */ -abstract class RecoveryParserTestMixin implements AbstractParserTestCase { +mixin RecoveryParserTestMixin implements AbstractParserTestCase { void test_additiveExpression_missing_LHS() { BinaryExpression expression = parseExpression("+ y", codes: [ParserErrorCode.MISSING_IDENTIFIER]); @@ -12540,7 +12539,7 @@ * * More complex tests should be defined in the class [ComplexParserTest]. */ -abstract class SimpleParserTestMixin implements AbstractParserTestCase { +mixin SimpleParserTestMixin implements AbstractParserTestCase { ConstructorName parseConstructorName(String name) { createParser('new $name();'); Statement statement = parser.parseStatement2(); @@ -14494,7 +14493,7 @@ * The class [FormalParameterParserTestMixin] defines parser tests that test * the parsing statements. */ -abstract class StatementParserTestMixin implements AbstractParserTestCase { +mixin StatementParserTestMixin implements AbstractParserTestCase { void test_invalid_typeParamAnnotation() { parseCompilationUnit('main() { C<@Foo T> v; }', errors: usingFastaParser @@ -15870,7 +15869,7 @@ * Tests which exercise the parser using a complete compilation unit or * compilation unit member. */ -abstract class TopLevelParserTestMixin implements AbstractParserTestCase { +mixin TopLevelParserTestMixin implements AbstractParserTestCase { void test_function_literal_allowed_at_toplevel() { parseCompilationUnit("var x = () {};"); }
diff --git a/pkg/analyzer/test/generated/resolver_test.dart b/pkg/analyzer/test/generated/resolver_test.dart index 2c0bdfd..0558400 100644 --- a/pkg/analyzer/test/generated/resolver_test.dart +++ b/pkg/analyzer/test/generated/resolver_test.dart
@@ -413,7 +413,7 @@ * Instances of the class `StaticTypeVerifier` verify that all of the nodes in an AST * structure that should have a static type associated with them do have a static type. */ -class StaticTypeVerifier extends GeneralizingAstVisitor<Object> { +class StaticTypeVerifier extends GeneralizingAstVisitor<void> { /** * A list containing all of the AST Expression nodes that were not resolved. */ @@ -479,19 +479,19 @@ } @override - Object visitBreakStatement(BreakStatement node) => null; + void visitBreakStatement(BreakStatement node) {} @override - Object visitCommentReference(CommentReference node) => null; + void visitCommentReference(CommentReference node) {} @override - Object visitContinueStatement(ContinueStatement node) => null; + void visitContinueStatement(ContinueStatement node) {} @override - Object visitExportDirective(ExportDirective node) => null; + void visitExportDirective(ExportDirective node) {} @override - Object visitExpression(Expression node) { + void visitExpression(Expression node) { node.visitChildren(this); DartType staticType = node.staticType; if (staticType == null) { @@ -499,66 +499,65 @@ } else { _resolvedExpressionCount++; } - return null; } @override - Object visitImportDirective(ImportDirective node) => null; + void visitImportDirective(ImportDirective node) {} @override - Object visitLabel(Label node) => null; + void visitLabel(Label node) {} @override - Object visitLibraryIdentifier(LibraryIdentifier node) => null; + void visitLibraryIdentifier(LibraryIdentifier node) {} @override - Object visitPrefixedIdentifier(PrefixedIdentifier node) { + void visitPrefixedIdentifier(PrefixedIdentifier node) { // In cases where we have a prefixed identifier where the prefix is dynamic, // we don't want to assert that the node will have a type. if (node.staticType == null && resolutionMap.staticTypeForExpression(node.prefix).isDynamic) { - return null; + return; } - return super.visitPrefixedIdentifier(node); + super.visitPrefixedIdentifier(node); } @override - Object visitSimpleIdentifier(SimpleIdentifier node) { + void visitSimpleIdentifier(SimpleIdentifier node) { // In cases where identifiers are being used for something other than an // expressions, then they can be ignored. AstNode parent = node.parent; if (parent is MethodInvocation && identical(node, parent.methodName)) { - return null; + return; } else if (parent is RedirectingConstructorInvocation && identical(node, parent.constructorName)) { - return null; + return; } else if (parent is SuperConstructorInvocation && identical(node, parent.constructorName)) { - return null; + return; } else if (parent is ConstructorName && identical(node, parent.name)) { - return null; + return; } else if (parent is ConstructorFieldInitializer && identical(node, parent.fieldName)) { - return null; + return; } else if (node.staticElement is PrefixElement) { // Prefixes don't have a type. - return null; + return; } - return super.visitSimpleIdentifier(node); + super.visitSimpleIdentifier(node); } @override - Object visitTypeAnnotation(TypeAnnotation node) { + void visitTypeAnnotation(TypeAnnotation node) { if (node.type == null) { _unresolvedTypes.add(node); } else { _resolvedTypeCount++; } - return super.visitTypeAnnotation(node); + super.visitTypeAnnotation(node); } @override - Object visitTypeName(TypeName node) { + void visitTypeName(TypeName node) { // Note: do not visit children from this node, the child SimpleIdentifier in // TypeName (i.e. "String") does not have a static type defined. // TODO(brianwilkerson) Not visiting the children means that we won't catch @@ -568,7 +567,6 @@ } else { _resolvedTypeCount++; } - return null; } String _getFileName(AstNode node) { @@ -856,77 +854,6 @@ } } - test_functionExpression_asInvocationArgument() async { - if (previewDart2) { - return; - } - String code = r''' -class MyMap<K, V> { - forEach(f(K key, V value)) {} -} -f(MyMap<int, String> m) { - m.forEach((k, v) { - k; - v; - }); -}'''; - Source source = addSource(code); - CompilationUnit unit = await _computeResolvedUnit(source); - // k - SimpleIdentifier kIdentifier = EngineTestCase.findNode( - unit, code, "k;", (node) => node is SimpleIdentifier); - expect(kIdentifier.staticType, typeProvider.dynamicType); - // v - SimpleIdentifier vIdentifier = EngineTestCase.findNode( - unit, code, "v;", (node) => node is SimpleIdentifier); - expect(vIdentifier.staticType, typeProvider.dynamicType); - } - - test_functionExpression_asInvocationArgument_functionExpressionInvocation() async { - if (previewDart2) { - return; - } - String code = r''' -main() { - (f(String value)) {} ((v) { - v; - }); -}'''; - Source source = addSource(code); - CompilationUnit unit = await _computeResolvedUnit(source); - // v - FormalParameter vParameter = EngineTestCase.findNode( - unit, code, "v)", (node) => node is FormalParameter); - expect(vParameter.identifier.staticType, typeProvider.dynamicType); - SimpleIdentifier vIdentifier = EngineTestCase.findNode( - unit, code, "v;", (node) => node is SimpleIdentifier); - expect(vIdentifier.staticType, typeProvider.dynamicType); - } - - test_functionExpression_asInvocationArgument_keepIfLessSpecific() async { - if (previewDart2) { - return; - } - String code = r''' -class MyList { - forEach(f(Object value)) {} -} -f(MyList list) { - list.forEach((int v) { - v; - }); -}'''; - Source source = addSource(code); - CompilationUnit unit = await _computeResolvedUnit(source); - // v - FormalParameter vParameter = EngineTestCase.findNode( - unit, code, "v)", (node) => node is SimpleFormalParameter); - expect(vParameter.identifier.staticType, typeProvider.intType); - SimpleIdentifier vIdentifier = EngineTestCase.findNode( - unit, code, "v;", (node) => node is SimpleIdentifier); - expect(vIdentifier.staticType, typeProvider.intType); - } - test_functionExpression_asInvocationArgument_notSubtypeOfStaticType() async { String code = r''' class A { @@ -946,50 +873,6 @@ same(0)); } - test_functionExpression_asInvocationArgument_replaceIfMoreSpecific() async { - if (previewDart2) { - return; - } - String code = r''' -class MyList<E> { - forEach(f(E value)) {} -} -f(MyList<String> list) { - list.forEach((Object v) { - v; - }); -}'''; - Source source = addSource(code); - CompilationUnit unit = await _computeResolvedUnit(source); - // v - FormalParameter vParameter = EngineTestCase.findNode( - unit, code, "v)", (node) => node is SimpleFormalParameter); - expect(vParameter.identifier.staticType, typeProvider.objectType); - } - - test_initializer() async { - if (previewDart2) { - return; - } - Source source = addSource(r''' -f() { - var v = 0; - return v; -}'''); - CompilationUnit unit = await _computeResolvedUnit(source); - FunctionDeclaration function = unit.declarations[0] as FunctionDeclaration; - BlockFunctionBody body = - function.functionExpression.body as BlockFunctionBody; - NodeList<Statement> statements = body.block.statements; - // Type of 'v' in declaration. - { - VariableDeclarationStatement statement = - statements[0] as VariableDeclarationStatement; - SimpleIdentifier variableName = statement.variables.variables[0].name; - expect(variableName.staticType, typeProvider.dynamicType); - } - } - test_initializer_hasStaticType() async { Source source = addSource(r''' f() { @@ -1168,23 +1051,6 @@ expect(getter.staticType, typeProvider.dynamicType); } - test_objectAccessInference_enabled_for_cascades() async { - if (previewDart2) { - return; - } - String name = 'hashCode'; - String code = ''' -main() { - dynamic obj; - obj..$name..$name; // marker -}'''; - CompilationUnit unit = await resolveSource(code); - PropertyAccess access = - findMarkedIdentifier(code, unit, "; // marker").parent; - expect(access.staticType, typeProvider.dynamicType); - expect(access.realTarget.staticType, typeProvider.dynamicType); - } - test_objectMethodInference_disabled_for_library_prefix() async { String name = 'toString'; addNamedSource('/helper.dart', ''' @@ -1223,38 +1089,6 @@ expect(methodInvoke.staticType, typeProvider.dynamicType); } - test_objectMethodInference_enabled_for_cascades() async { - if (previewDart2) { - return; - } - String name = 'toString'; - String code = ''' -main() { - dynamic obj; - obj..$name()..$name(); // marker -}'''; - CompilationUnit unit = await resolveSource(code); - SimpleIdentifier methodName = - findMarkedIdentifier(code, unit, "(); // marker"); - MethodInvocation methodInvoke = methodName.parent; - - expect(methodInvoke.staticType, typeProvider.dynamicType); - expect(methodInvoke.realTarget.staticType, typeProvider.dynamicType); - } - - test_propagatedReturnType_localFunction() async { - if (previewDart2) { - return; - } - String code = r''' -main() { - f() => 42; - var v = f(); -}'''; - CompilationUnit unit = await resolveSource(code); - assertAssignedType(code, unit, typeProvider.dynamicType); - } - /** * Return the resolved unit for the given [source]. * @@ -1293,6 +1127,7 @@ _classElement("Iterable", objectType, ["T"]).type; InterfaceType listType = _classElement("List", objectType, ["E"]).type; InterfaceType mapType = _classElement("Map", objectType, ["K", "V"]).type; + InterfaceType setType = _classElement("Set", objectType, ["E"]).type; InterfaceType stackTraceType = _classElement("StackTrace", objectType).type; InterfaceType streamType = _classElement("Stream", objectType, ["T"]).type; InterfaceType stringType = _classElement("String", objectType).type; @@ -1307,24 +1142,28 @@ iterableType.element, listType.element, mapType.element, + setType.element, objectType.element, stackTraceType.element, stringType.element, symbolType.element, typeType.element ]; + coreUnit.source = new TestSource('dart:core'); + coreUnit.librarySource = coreUnit.source; CompilationUnitElementImpl asyncUnit = new CompilationUnitElementImpl(); asyncUnit.types = <ClassElement>[ futureType.element, futureOrType.element, streamType.element ]; - AnalysisContext context = AnalysisEngine.instance.createAnalysisContext(); + asyncUnit.source = new TestSource('dart:async'); + asyncUnit.librarySource = asyncUnit.source; LibraryElementImpl coreLibrary = new LibraryElementImpl.forNode( - context, AstTestFactory.libraryIdentifier2(["dart.core"])); + null, null, AstTestFactory.libraryIdentifier2(["dart.core"])); coreLibrary.definingCompilationUnit = coreUnit; LibraryElementImpl asyncLibrary = new LibraryElementImpl.forNode( - context, AstTestFactory.libraryIdentifier2(["dart.async"])); + null, null, AstTestFactory.libraryIdentifier2(["dart.async"])); asyncLibrary.definingCompilationUnit = asyncUnit; // // Create a type provider and ensure that it can return the expected types. @@ -1425,7 +1264,7 @@ resourceProvider: resourceProvider); Source librarySource = new FileSource(getFile("/lib.dart")); LibraryElementImpl element = new LibraryElementImpl.forNode( - context, AstTestFactory.libraryIdentifier2(["lib"])); + context, null, AstTestFactory.libraryIdentifier2(["lib"])); element.definingCompilationUnit = new CompilationUnitElementImpl(); _typeProvider = new TestTypeProvider(); libraryScope = new LibraryScope(element); @@ -1462,7 +1301,7 @@ InternalAnalysisContext context = AnalysisContextFactory.contextWithCore( resourceProvider: resourceProvider); var source = getFile('/test.dart').createSource(); - var libraryElement = new LibraryElementImpl.forNode(context, null) + var libraryElement = new LibraryElementImpl.forNode(context, null, null) ..definingCompilationUnit = unitElement; var libraryScope = new LibraryScope(libraryElement); var visitor = new TypeResolverVisitor( @@ -2332,7 +2171,7 @@ InternalAnalysisContext context = AnalysisContextFactory.contextWithCore( resourceProvider: resourceProvider); var source = getFile('/test.dart').createSource(); - var libraryElement = new LibraryElementImpl.forNode(context, null) + var libraryElement = new LibraryElementImpl.forNode(context, null, null) ..definingCompilationUnit = unitElement; libraryScope = new LibraryScope(libraryElement); visitor = new TypeResolverVisitor(
diff --git a/pkg/analyzer/test/generated/resolver_test_case.dart b/pkg/analyzer/test/generated/resolver_test_case.dart index d7a954d..2c68db3 100644 --- a/pkg/analyzer/test/generated/resolver_test_case.dart +++ b/pkg/analyzer/test/generated/resolver_test_case.dart
@@ -1,9 +1,10 @@ -// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file +// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. import 'dart:async'; +import 'package:analyzer/dart/analysis/results.dart'; import 'package:analyzer/dart/ast/ast.dart'; import 'package:analyzer/dart/ast/standard_resolution_map.dart'; import 'package:analyzer/dart/ast/visitor.dart'; @@ -11,9 +12,11 @@ import 'package:analyzer/dart/element/type.dart'; import 'package:analyzer/error/error.dart'; import 'package:analyzer/file_system/file_system.dart'; -import 'package:analyzer/file_system/memory_file_system.dart'; +import 'package:analyzer/src/dart/analysis/byte_store.dart'; import 'package:analyzer/src/dart/analysis/driver.dart'; +import 'package:analyzer/src/dart/analysis/experiments.dart'; import 'package:analyzer/src/dart/analysis/file_state.dart'; +import 'package:analyzer/src/dart/analysis/performance_logger.dart'; import 'package:analyzer/src/dart/element/element.dart'; import 'package:analyzer/src/dart/element/type.dart'; import 'package:analyzer/src/error/codes.dart'; @@ -26,11 +29,10 @@ import 'package:analyzer/src/generated/testing/ast_test_factory.dart'; import 'package:analyzer/src/generated/testing/element_factory.dart'; import 'package:analyzer/src/source/package_map_resolver.dart'; -import 'package:analyzer/src/dart/analysis/byte_store.dart'; -import 'package:analyzer/src/dart/analysis/performance_logger.dart'; +import 'package:analyzer/src/test_utilities/mock_sdk.dart'; +import 'package:analyzer/src/test_utilities/resource_provider_mixin.dart'; import 'package:test/test.dart'; -import '../src/context/mock_sdk.dart'; import 'analysis_context_factory.dart'; import 'test_support.dart'; @@ -38,7 +40,7 @@ * An AST visitor used to verify that all of the nodes in an AST structure that * should have been resolved were resolved. */ -class ResolutionVerifier extends RecursiveAstVisitor<Object> { +class ResolutionVerifier extends RecursiveAstVisitor<void> { /** * A set containing nodes that are known to not be resolvable and should * therefore not cause the test to fail. @@ -88,7 +90,7 @@ } @override - Object visitAnnotation(Annotation node) { + void visitAnnotation(Annotation node) { node.visitChildren(this); ElementAnnotation elementAnnotation = node.elementAnnotation; if (elementAnnotation == null) { @@ -98,154 +100,153 @@ } else if (elementAnnotation is! ElementAnnotation) { _wrongTypedNodes.add(node); } - return null; } @override - Object visitBinaryExpression(BinaryExpression node) { + void visitBinaryExpression(BinaryExpression node) { node.visitChildren(this); if (!node.operator.isUserDefinableOperator) { - return null; + return; } DartType operandType = node.leftOperand.staticType; if (operandType == null || operandType.isDynamic) { - return null; + return; } - return _checkResolved( - node, node.staticElement, (node) => node is MethodElement); + _checkResolved(node, node.staticElement, (node) => node is MethodElement); } @override - Object visitCommentReference(CommentReference node) => null; + void visitCommentReference(CommentReference node) {} @override - Object visitCompilationUnit(CompilationUnit node) { + void visitCompilationUnit(CompilationUnit node) { node.visitChildren(this); - return _checkResolved( + _checkResolved( node, node.declaredElement, (node) => node is CompilationUnitElement); } @override - Object visitExportDirective(ExportDirective node) => - _checkResolved(node, node.element, (node) => node is ExportElement); + void visitExportDirective(ExportDirective node) { + _checkResolved(node, node.element, (node) => node is ExportElement); + } @override - Object visitFunctionDeclaration(FunctionDeclaration node) { + void visitFunctionDeclaration(FunctionDeclaration node) { node.visitChildren(this); if (node.declaredElement is LibraryElement) { _wrongTypedNodes.add(node); } - return null; } @override - Object visitFunctionExpressionInvocation(FunctionExpressionInvocation node) { + void visitFunctionExpressionInvocation(FunctionExpressionInvocation node) { node.visitChildren(this); // TODO(brianwilkerson) If we start resolving function expressions, then // conditionally check to see whether the node was resolved correctly. - return null; //checkResolved(node, node.getElement(), FunctionElement.class); } @override - Object visitImportDirective(ImportDirective node) { + void visitImportDirective(ImportDirective node) { // Not sure how to test the combinators given that it isn't an error if the // names are not defined. _checkResolved(node, node.element, (node) => node is ImportElement); SimpleIdentifier prefix = node.prefix; if (prefix == null) { - return null; + return; } - return _checkResolved( + _checkResolved( prefix, prefix.staticElement, (node) => node is PrefixElement); } @override - Object visitIndexExpression(IndexExpression node) { + void visitIndexExpression(IndexExpression node) { node.visitChildren(this); DartType targetType = node.realTarget.staticType; if (targetType == null || targetType.isDynamic) { - return null; + return; } - return _checkResolved( - node, node.staticElement, (node) => node is MethodElement); + _checkResolved(node, node.staticElement, (node) => node is MethodElement); } @override - Object visitLibraryDirective(LibraryDirective node) => - _checkResolved(node, node.element, (node) => node is LibraryElement); + void visitLibraryDirective(LibraryDirective node) { + _checkResolved(node, node.element, (node) => node is LibraryElement); + } @override - Object visitNamedExpression(NamedExpression node) => - node.expression.accept(this); + void visitNamedExpression(NamedExpression node) { + node.expression.accept(this); + } @override - Object visitPartDirective(PartDirective node) => _checkResolved( - node, node.element, (node) => node is CompilationUnitElement); + void visitPartDirective(PartDirective node) { + _checkResolved( + node, node.element, (node) => node is CompilationUnitElement); + } @override - Object visitPartOfDirective(PartOfDirective node) => - _checkResolved(node, node.element, (node) => node is LibraryElement); + void visitPartOfDirective(PartOfDirective node) { + _checkResolved(node, node.element, (node) => node is LibraryElement); + } @override - Object visitPostfixExpression(PostfixExpression node) { + void visitPostfixExpression(PostfixExpression node) { node.visitChildren(this); if (!node.operator.isUserDefinableOperator) { - return null; + return; } DartType operandType = node.operand.staticType; if (operandType == null || operandType.isDynamic) { - return null; + return; } - return _checkResolved( - node, node.staticElement, (node) => node is MethodElement); + _checkResolved(node, node.staticElement, (node) => node is MethodElement); } @override - Object visitPrefixedIdentifier(PrefixedIdentifier node) { + void visitPrefixedIdentifier(PrefixedIdentifier node) { SimpleIdentifier prefix = node.prefix; prefix.accept(this); DartType prefixType = prefix.staticType; if (prefixType == null || prefixType.isDynamic) { - return null; + return; } - return _checkResolved(node, node.staticElement, null); + _checkResolved(node, node.staticElement, null); } @override - Object visitPrefixExpression(PrefixExpression node) { + void visitPrefixExpression(PrefixExpression node) { node.visitChildren(this); if (!node.operator.isUserDefinableOperator) { - return null; + return; } DartType operandType = node.operand.staticType; if (operandType == null || operandType.isDynamic) { - return null; + return; } - return _checkResolved( - node, node.staticElement, (node) => node is MethodElement); + _checkResolved(node, node.staticElement, (node) => node is MethodElement); } @override - Object visitPropertyAccess(PropertyAccess node) { + void visitPropertyAccess(PropertyAccess node) { Expression target = node.realTarget; target.accept(this); DartType targetType = target.staticType; if (targetType == null || targetType.isDynamic) { - return null; + return; } - return node.propertyName.accept(this); + node.propertyName.accept(this); } @override - Object visitSimpleIdentifier(SimpleIdentifier node) { + void visitSimpleIdentifier(SimpleIdentifier node) { if (node.name == "void") { - return null; + return; } if (resolutionMap.staticTypeForExpression(node) != null && resolutionMap.staticTypeForExpression(node).isDynamic && node.staticElement == null) { - return null; + return; } AstNode parent = node.parent; if (parent is MethodInvocation) { @@ -254,14 +255,14 @@ Expression target = invocation.realTarget; DartType targetType = target == null ? null : target.staticType; if (targetType == null || targetType.isDynamic) { - return null; + return; } } } - return _checkResolved(node, node.staticElement, null); + _checkResolved(node, node.staticElement, null); } - Object _checkResolved( + void _checkResolved( AstNode node, Element element, Predicate<Element> predicate) { if (element == null) { if (_knownExceptions == null || !_knownExceptions.contains(node)) { @@ -272,7 +273,6 @@ _wrongTypedNodes.add(node); } } - return null; } String _getFileName(AstNode node) { @@ -310,12 +310,7 @@ } } -class ResolverTestCase extends EngineTestCase { - /** - * The resource provider used by the test case. - */ - MemoryResourceProvider resourceProvider = new MemoryResourceProvider(); - +class ResolverTestCase extends EngineTestCase with ResourceProviderMixin { /** * The analysis context used to parse the compilation units being resolved. */ @@ -350,9 +345,6 @@ bool get enableNewAnalysisDriver => false; - /// TODO(brianwilkerson) Remove this getter. - bool get previewDart2 => true; - /** * Return a type provider that can be used to test the results of resolution. * @@ -384,8 +376,8 @@ * set in the content provider. Return the source representing the added file. */ Source addNamedSource(String filePath, String contents) { - filePath = resourceProvider.convertPath(filePath); - File file = resourceProvider.newFile(filePath, contents); + filePath = convertPath(filePath); + File file = newFile(filePath, content: contents); Source source = file.createSource(); if (enableNewAnalysisDriver) { driver.addFile(filePath); @@ -529,7 +521,7 @@ Future<TestAnalysisResult> computeAnalysisResult(Source source) async { TestAnalysisResult analysisResult; if (enableNewAnalysisDriver) { - AnalysisResult result = await driver.getResult(source.fullName); + ResolvedUnitResult result = await driver.getResult(source.fullName); analysisResult = new TestAnalysisResult(source, result.unit, result.errors); } else { @@ -570,7 +562,7 @@ * give it an empty content. Return the source that was created. */ Source createNamedSource(String fileName) { - Source source = resourceProvider.getFile(fileName).createSource(); + Source source = getFile(fileName).createSource(); analysisContext2.setContents(source, ''); return source; } @@ -585,7 +577,7 @@ LibraryElementImpl createTestLibrary( AnalysisContext context, String libraryName, [List<String> typeNames]) { - String fileName = resourceProvider.convertPath("/test/$libraryName.dart"); + String fileName = convertPath("/test/$libraryName.dart"); Source definingCompilationUnitSource = createNamedSource(fileName); List<CompilationUnitElement> sourcedCompilationUnits; if (typeNames == null) { @@ -611,7 +603,9 @@ compilationUnit.librarySource = compilationUnit.source = definingCompilationUnitSource; LibraryElementImpl library = new LibraryElementImpl.forNode( - context, AstTestFactory.libraryIdentifier2([libraryName])); + context, + driver?.currentSession, + AstTestFactory.libraryIdentifier2([libraryName])); library.definingCompilationUnit = compilationUnit; library.parts = sourcedCompilationUnits; return library; @@ -662,6 +656,10 @@ fail('Only packages or options can be specified.'); } options ??= defaultAnalysisOptions; + (options as AnalysisOptionsImpl).enabledExperiments = [ + Experiments.constantUpdate2018Name, + Experiments.setLiteralName + ]; if (enableNewAnalysisDriver) { DartSdk sdk = new MockSdk(resourceProvider: resourceProvider) ..context.analysisOptions = options; @@ -674,10 +672,8 @@ var packageMap = <String, List<Folder>>{}; packages.forEach((args) { String name = args[0]; - String path = - resourceProvider.convertPath('/packages/$name/$name.dart'); String content = args[1]; - File file = resourceProvider.newFile(path, content); + File file = newFile('/packages/$name/$name.dart', content: content); packageMap[name] = <Folder>[file.parent]; }); resolvers.add(new PackageMapUriResolver(resourceProvider, packageMap)); @@ -832,6 +828,19 @@ CompilationUnit testUnit; /** + * Find the expression that starts at the offset of [search] and validate its + * that its static type matches the given [type]. + * + * If [type] is a string, validates that the expression's static type + * stringifies to that text. Otherwise, [type] is used directly a [Matcher] + * to match the type. + */ + void expectExpressionType(String search, type) { + Expression expression = findExpression(search); + _expectType(expression.staticType, type); + } + + /** * Looks up the identifier with [name] and validates that its type type * stringifies to [type] and that its generics match the given stringified * output. @@ -889,15 +898,19 @@ void expectInitializerType(String name, type) { SimpleIdentifier identifier = findIdentifier(name); VariableDeclaration declaration = - identifier.getAncestor((node) => node is VariableDeclaration); + identifier.thisOrAncestorOfType<VariableDeclaration>(); Expression initializer = declaration.initializer; _expectType(initializer.staticType, type); } + Expression findExpression(String search) { + return EngineTestCase.findNode( + testUnit, testCode, search, (node) => node is Expression); + } + SimpleIdentifier findIdentifier(String search) { - SimpleIdentifier identifier = EngineTestCase.findNode( + return EngineTestCase.findNode( testUnit, testCode, search, (node) => node is SimpleIdentifier); - return identifier; } Future<Null> resolveTestUnit(String code, {bool noErrors: true}) async {
diff --git a/pkg/analyzer/test/generated/sdk_test.dart b/pkg/analyzer/test/generated/sdk_test.dart index f311ea9..6dae63b 100644 --- a/pkg/analyzer/test/generated/sdk_test.dart +++ b/pkg/analyzer/test/generated/sdk_test.dart
@@ -4,10 +4,11 @@ import 'package:analyzer/src/generated/engine.dart'; import 'package:analyzer/src/generated/sdk.dart'; +import 'package:analyzer/src/test_utilities/mock_sdk.dart'; +import 'package:analyzer/src/test_utilities/resource_provider_mixin.dart'; import 'package:test/test.dart'; import 'package:test_reflective_loader/test_reflective_loader.dart'; -import '../src/context/mock_sdk.dart'; import 'test_support.dart'; main() { @@ -18,14 +19,14 @@ } @reflectiveTest -class DartSdkManagerTest extends EngineTestCase { +class DartSdkManagerTest extends EngineTestCase with ResourceProviderMixin { void test_anySdk() { DartSdkManager manager = new DartSdkManager('/a/b/c', false); expect(manager.anySdk, isNull); AnalysisOptions options = new AnalysisOptionsImpl(); SdkDescription description = new SdkDescription(<String>['/c/d'], options); - DartSdk sdk = new MockSdk(); + DartSdk sdk = new MockSdk(resourceProvider: resourceProvider); manager.getSdk(description, () => sdk); expect(manager.anySdk, same(sdk)); } @@ -34,11 +35,11 @@ DartSdkManager manager = new DartSdkManager('/a/b/c', false); AnalysisOptions options = new AnalysisOptionsImpl(); SdkDescription description1 = new SdkDescription(<String>['/c/d'], options); - DartSdk sdk1 = new MockSdk(); + DartSdk sdk1 = new MockSdk(resourceProvider: resourceProvider); DartSdk result1 = manager.getSdk(description1, () => sdk1); expect(result1, same(sdk1)); SdkDescription description2 = new SdkDescription(<String>['/e/f'], options); - DartSdk sdk2 = new MockSdk(); + DartSdk sdk2 = new MockSdk(resourceProvider: resourceProvider); DartSdk result2 = manager.getSdk(description2, () => sdk2); expect(result2, same(sdk2)); @@ -50,7 +51,7 @@ DartSdkManager manager = new DartSdkManager('/a/b/c', false); AnalysisOptions options = new AnalysisOptionsImpl(); SdkDescription description = new SdkDescription(<String>['/c/d'], options); - DartSdk sdk = new MockSdk(); + DartSdk sdk = new MockSdk(resourceProvider: resourceProvider); DartSdk result = manager.getSdk(description, () => sdk); expect(result, same(sdk)); manager.getSdk(description, _failIfAbsent);
diff --git a/pkg/analyzer/test/generated/simple_resolver_test.dart b/pkg/analyzer/test/generated/simple_resolver_test.dart index 3d64b48..55d92dd 100644 --- a/pkg/analyzer/test/generated/simple_resolver_test.dart +++ b/pkg/analyzer/test/generated/simple_resolver_test.dart
@@ -142,7 +142,7 @@ } // get parameter Expression rhs = assignment.rightHandSide; - expect(rhs.staticParameterElement, previewDart2 ? isNotNull : isNull); + expect(rhs.staticParameterElement, isNotNull); } test_argumentResolution_setter_propagated_propertyAccess() async { @@ -166,7 +166,7 @@ } // get parameter Expression rhs = assignment.rightHandSide; - expect(rhs.staticParameterElement, previewDart2 ? isNotNull : isNull); + expect(rhs.staticParameterElement, isNotNull); } test_argumentResolution_setter_static() async { @@ -376,42 +376,6 @@ verify([source]); } - test_commentReference_class() async { - Source source = addSource(r''' -f() {} -/** [A] [new A] [A.n] [new A.n] [m] [f] */ -class A { - A() {} - A.n() {} - m() {} -}'''); - await computeAnalysisResult(source); - assertNoErrors(source); - verify([source]); - } - - test_commentReference_parameter() async { - Source source = addSource(r''' -class A { - A() {} - A.n() {} - /** [e] [f] */ - m(e, f()) {} -}'''); - await computeAnalysisResult(source); - assertNoErrors(source); - verify([source]); - } - - test_commentReference_singleLine() async { - Source source = addSource(r''' -/// [A] -class A {}'''); - await computeAnalysisResult(source); - assertNoErrors(source); - verify([source]); - } - test_continueTarget_labeled() async { // Verify that the target of the label is correctly found and is recorded // as the unlabeled portion of the statement. @@ -1717,7 +1681,7 @@ } class _SimpleResolverTest_localVariable_types_invoked - extends RecursiveAstVisitor<Object> { + extends RecursiveAstVisitor<void> { final SimpleResolverTest test; List<bool> found; @@ -1729,25 +1693,20 @@ : super(); @override - Object visitSimpleIdentifier(SimpleIdentifier node) { + void visitSimpleIdentifier(SimpleIdentifier node) { if (node.name == "myVar" && node.parent is MethodInvocation) { try { found[0] = true; // check static type DartType staticType = node.staticType; - if (test.previewDart2) { - expect(staticType is FunctionType, isTrue); - FunctionType functionType = staticType; - expect( - functionType.parameters[0].type, same(test.typeProvider.intType)); - expect(functionType.returnType, same(test.typeProvider.stringType)); - } else { - expect(staticType, same(test.typeProvider.dynamicType)); - } + expect(staticType is FunctionType, isTrue); + FunctionType functionType = staticType; + expect( + functionType.parameters[0].type, same(test.typeProvider.intType)); + expect(functionType.returnType, same(test.typeProvider.stringType)); } on AnalysisException catch (e, stackTrace) { thrownException[0] = new CaughtException(e, stackTrace); } } - return null; } }
diff --git a/pkg/analyzer/test/generated/source_factory_test.dart b/pkg/analyzer/test/generated/source_factory_test.dart index 09a3c10..767de68 100644 --- a/pkg/analyzer/test/generated/source_factory_test.dart +++ b/pkg/analyzer/test/generated/source_factory_test.dart
@@ -13,6 +13,7 @@ import 'package:analyzer/src/generated/utilities_dart.dart' as utils; import 'package:analyzer/src/source/package_map_resolver.dart'; import 'package:analyzer/src/source/source_resource.dart'; +import 'package:analyzer/src/test_utilities/resource_provider_mixin.dart'; import 'package:package_config/packages.dart'; import 'package:package_config/packages_file.dart' as pkgfile show parse; import 'package:package_config/src/packages_impl.dart'; @@ -217,9 +218,7 @@ } @reflectiveTest -class SourceFactoryTest { - MemoryResourceProvider resourceProvider = new MemoryResourceProvider(); - +class SourceFactoryTest with ResourceProviderMixin { void test_creation() { expect(new SourceFactory([]), isNotNull); } @@ -252,12 +251,11 @@ void test_resolveUri_nonAbsolute_absolute() { SourceFactory factory = new SourceFactory([new AbsoluteUriResolver(resourceProvider)]); - String sourcePath = resourceProvider.convertPath('/does/not/exist.dart'); + String sourcePath = convertPath('/does/not/exist.dart'); String targetRawPath = '/does/not/matter.dart'; - String targetPath = resourceProvider.convertPath(targetRawPath); - String targetUri = - resourceProvider.pathContext.toUri(targetRawPath).toString(); - Source sourceSource = new FileSource(resourceProvider.getFile(sourcePath)); + String targetPath = convertPath(targetRawPath); + String targetUri = toUri(targetRawPath).toString(); + Source sourceSource = new FileSource(getFile(sourcePath)); Source result = factory.resolveUri(sourceSource, targetUri); expect(result.fullName, targetPath); } @@ -265,10 +263,9 @@ void test_resolveUri_nonAbsolute_relative() { SourceFactory factory = new SourceFactory([new AbsoluteUriResolver(resourceProvider)]); - String path = _p('/does/not/have.dart'); - Source containingSource = new FileSource(resourceProvider.getFile(path)); + Source containingSource = new FileSource(getFile('/does/not/have.dart')); Source result = factory.resolveUri(containingSource, 'exist.dart'); - expect(result.fullName, _p('/does/not/exist.dart')); + expect(result.fullName, convertPath('/does/not/exist.dart')); } void test_resolveUri_nonAbsolute_relative_package() { @@ -301,8 +298,8 @@ } void test_restoreUri() { - File file1 = resourceProvider.getFile(_p("/some/file1.dart")); - File file2 = resourceProvider.getFile(_p("/some/file2.dart")); + File file1 = getFile("/some/file1.dart"); + File file2 = getFile("/some/file2.dart"); Source source1 = new FileSource(file1); Source source2 = new FileSource(file2); Uri expected1 = Uri.parse("file:///my_file.dart"); @@ -311,11 +308,6 @@ expect(factory.restoreUri(source1), same(expected1)); expect(factory.restoreUri(source2), same(null)); } - - /** - * Return the [resourceProvider] specific path for the given Posix [path]. - */ - String _p(String path) => resourceProvider.convertPath(path); } class UriResolver_absolute extends UriResolver {
diff --git a/pkg/analyzer/test/generated/static_type_analyzer_test.dart b/pkg/analyzer/test/generated/static_type_analyzer_test.dart index 8995879..6657e81 100644 --- a/pkg/analyzer/test/generated/static_type_analyzer_test.dart +++ b/pkg/analyzer/test/generated/static_type_analyzer_test.dart
@@ -1,4 +1,4 @@ -// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file +// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. @@ -33,6 +33,7 @@ defineReflectiveSuite(() { defineReflectiveTests(StaticTypeAnalyzerTest); defineReflectiveTests(StaticTypeAnalyzer2Test); + defineReflectiveTests(StaticTypeAnalyzer3Test); }); } @@ -57,7 +58,7 @@ } '''; await resolveTestUnit(code); - expectInitializerType('foo', previewDart2 ? 'int' : 'dynamic'); + expectInitializerType('foo', 'int'); } test_FunctionExpressionInvocation_curried() async { @@ -117,11 +118,7 @@ } """; await resolveTestUnit(code); - if (previewDart2) { - expectIdentifierType("p()", '() → dynamic'); - } else { - expectIdentifierType("p()", DynamicTypeImpl.instance); - } + expectIdentifierType("p()", '() → dynamic'); } test_staticMethods_classTypeParameters() async { @@ -156,7 +153,7 @@ FunctionTypeImpl type = expectFunctionType('m);', '<S>(S) → void', elementTypeParams: '[S]', typeFormals: '[S]', - identifierType: previewDart2 ? '<S>(S) → void' : '(dynamic) → void'); + identifierType: '<S>(S) → void'); typeS = type.typeFormals[0].type; type = type.instantiate([DynamicTypeImpl.instance]); @@ -172,8 +169,7 @@ typeParams: '[S]', typeArgs: '[S]', typeFormals: '[U]', - identifierType: - previewDart2 ? '<U>(S, U) → void' : '(S, dynamic) → void'); + identifierType: '<U>(S, U) → void'); type = type.instantiate([DynamicTypeImpl.instance]); expect(type.toString(), '(S, dynamic) → void'); @@ -184,6 +180,48 @@ } } +/** + * End-to-end tests of the static type analyzer that use the new driver. + */ +@reflectiveTest +class StaticTypeAnalyzer3Test extends StaticTypeAnalyzer2TestShared { + bool get enableNewAnalysisDriver => true; + + test_emptyMapLiteral_inContext() async { + String code = r''' +main() { + useMap({}); +} +void useMap(Map<int, int> m) { +} +'''; + await resolveTestUnit(code); + expectExpressionType('{}', 'Map<int, int>'); + } + + test_emptyMapLiteral_notInContext() async { + String code = r''' +main() { + var v = {}; +} +'''; + await resolveTestUnit(code); + expectExpressionType('{}', 'Map<dynamic, dynamic>'); + } + + test_emptySetLiteral_inContext() async { + String code = r''' +main() { + useSet({}); +} +void useSet(Set<int> s) { +} +'''; + await resolveTestUnit(code); + expectExpressionType('{}', 'Set<int>'); + } +} + @reflectiveTest class StaticTypeAnalyzerTest extends EngineTestCase with ResourceProviderMixin { /** @@ -206,9 +244,6 @@ */ TypeProvider _typeProvider; - /// TODO(brianwilkerson) Remove this getter. - bool get previewDart2 => true; - /** * The type system used to analyze the test cases. */ @@ -661,8 +696,6 @@ void test_visitFunctionExpression_async_expression() { // () async => e, where e has type int InterfaceType intType = _typeProvider.intType; - InterfaceType futureIntType = - _typeProvider.futureType.instantiate(<DartType>[intType]); Expression expression = _resolvedVariable(intType, 'e'); ExpressionFunctionBody body = AstTestFactory.expressionFunctionBody(expression); @@ -670,17 +703,13 @@ FunctionExpression node = _resolvedFunctionExpression( AstTestFactory.formalParameterList([]), body); DartType resultType = _analyze(node); - if (previewDart2) { - _assertFunctionType( - _typeProvider.futureType - .instantiate(<DartType>[_typeProvider.dynamicType]), - null, - null, - null, - resultType); - } else { - _assertFunctionType(futureIntType, null, null, null, resultType); - } + _assertFunctionType( + _typeProvider.futureType + .instantiate(<DartType>[_typeProvider.dynamicType]), + null, + null, + null, + resultType); _listener.assertNoErrors(); } @@ -696,17 +725,13 @@ FunctionExpression node = _resolvedFunctionExpression( AstTestFactory.formalParameterList([]), body); DartType resultType = _analyze(node); - if (previewDart2) { - _assertFunctionType( - _typeProvider.futureType - .instantiate(<DartType>[_typeProvider.dynamicType]), - null, - null, - null, - resultType); - } else { - _assertFunctionType(futureIntType, null, null, null, resultType); - } + _assertFunctionType( + _typeProvider.futureType + .instantiate(<DartType>[_typeProvider.dynamicType]), + null, + null, + null, + resultType); _listener.assertNoErrors(); } @@ -724,17 +749,13 @@ FunctionExpression node = _resolvedFunctionExpression( AstTestFactory.formalParameterList([]), body); DartType resultType = _analyze(node); - if (previewDart2) { - _assertFunctionType( - _typeProvider.futureType - .instantiate(<DartType>[_typeProvider.dynamicType]), - null, - null, - null, - resultType); - } else { - _assertFunctionType(futureIntType, null, null, null, resultType); - } + _assertFunctionType( + _typeProvider.futureType + .instantiate(<DartType>[_typeProvider.dynamicType]), + null, + null, + null, + resultType); _listener.assertNoErrors(); } @@ -800,13 +821,8 @@ DartType resultType = _analyze(node); Map<String, DartType> expectedNamedTypes = new HashMap<String, DartType>(); expectedNamedTypes["p"] = dynamicType; - if (previewDart2) { - _assertFunctionType( - dynamicType, null, null, expectedNamedTypes, resultType); - } else { - _assertFunctionType( - _typeProvider.intType, null, null, expectedNamedTypes, resultType); - } + _assertFunctionType( + dynamicType, null, null, expectedNamedTypes, resultType); _listener.assertNoErrors(); } @@ -838,13 +854,8 @@ AstTestFactory.expressionFunctionBody(_resolvedInteger(0))); _analyze5(p); DartType resultType = _analyze(node); - if (previewDart2) { - _assertFunctionType( - dynamicType, <DartType>[dynamicType], null, null, resultType); - } else { - _assertFunctionType(_typeProvider.intType, <DartType>[dynamicType], null, - null, resultType); - } + _assertFunctionType( + dynamicType, <DartType>[dynamicType], null, null, resultType); _listener.assertNoErrors(); } @@ -883,13 +894,8 @@ DartType resultType = _analyze(node); Map<String, DartType> expectedNamedTypes = new HashMap<String, DartType>(); expectedNamedTypes["p2"] = dynamicType; - if (previewDart2) { - _assertFunctionType(dynamicType, <DartType>[dynamicType], null, - expectedNamedTypes, resultType); - } else { - _assertFunctionType(_typeProvider.intType, <DartType>[dynamicType], null, - expectedNamedTypes, resultType); - } + _assertFunctionType(dynamicType, <DartType>[dynamicType], null, + expectedNamedTypes, resultType); _listener.assertNoErrors(); } @@ -926,13 +932,8 @@ _analyze5(p1); _analyze5(p2); DartType resultType = _analyze(node); - if (previewDart2) { - _assertFunctionType(dynamicType, <DartType>[dynamicType], - <DartType>[dynamicType], null, resultType); - } else { - _assertFunctionType(_typeProvider.intType, <DartType>[dynamicType], - <DartType>[dynamicType], null, resultType); - } + _assertFunctionType(dynamicType, <DartType>[dynamicType], + <DartType>[dynamicType], null, resultType); _listener.assertNoErrors(); } @@ -967,13 +968,8 @@ AstTestFactory.expressionFunctionBody(_resolvedInteger(0))); _analyze5(p); DartType resultType = _analyze(node); - if (previewDart2) { - _assertFunctionType( - dynamicType, null, <DartType>[dynamicType], null, resultType); - } else { - _assertFunctionType(_typeProvider.intType, null, <DartType>[dynamicType], - null, resultType); - } + _assertFunctionType( + dynamicType, null, <DartType>[dynamicType], null, resultType); _listener.assertNoErrors(); } @@ -1139,16 +1135,9 @@ // [0] Expression node = AstTestFactory.listLiteral([_resolvedInteger(0)]); DartType resultType = _analyze(node); - if (previewDart2) { - _assertType2( - _typeProvider.listType.instantiate(<DartType>[_typeProvider.intType]), - resultType); - } else { - _assertType2( - _typeProvider.listType - .instantiate(<DartType>[_typeProvider.dynamicType]), - resultType); - } + _assertType2( + _typeProvider.listType.instantiate(<DartType>[_typeProvider.intType]), + resultType); _listener.assertNoErrors(); } @@ -1194,17 +1183,10 @@ Expression node = AstTestFactory.mapLiteral2( [AstTestFactory.mapLiteralEntry("k", _resolvedInteger(0))]); DartType resultType = _analyze(node); - if (previewDart2) { - _assertType2( - _typeProvider.mapType.instantiate( - <DartType>[_typeProvider.dynamicType, _typeProvider.intType]), - resultType); - } else { - _assertType2( - _typeProvider.mapType.instantiate( - <DartType>[_typeProvider.dynamicType, _typeProvider.dynamicType]), - resultType); - } + _assertType2( + _typeProvider.mapType.instantiate( + <DartType>[_typeProvider.dynamicType, _typeProvider.intType]), + resultType); _listener.assertNoErrors(); } @@ -1545,7 +1527,7 @@ definingCompilationUnit.librarySource = definingCompilationUnit.source = source; LibraryElementImpl definingLibrary = - new LibraryElementImpl.forNode(context, null); + new LibraryElementImpl.forNode(context, null, null); definingLibrary.definingCompilationUnit = definingCompilationUnit; _typeProvider = context.typeProvider; _visitor = new ResolverVisitor(
diff --git a/pkg/analyzer/test/generated/static_type_warning_code_test.dart b/pkg/analyzer/test/generated/static_type_warning_code_test.dart index e4f9e69..283d077 100644 --- a/pkg/analyzer/test/generated/static_type_warning_code_test.dart +++ b/pkg/analyzer/test/generated/static_type_warning_code_test.dart
@@ -2,12 +2,9 @@ // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. -import 'package:analyzer/error/error.dart'; import 'package:analyzer/src/error/codes.dart'; import 'package:analyzer/src/generated/engine.dart'; -import 'package:analyzer/src/generated/java_core.dart' show formatList; import 'package:analyzer/src/generated/source_io.dart'; -import 'package:test/test.dart'; import 'package:test_reflective_loader/test_reflective_loader.dart'; import 'resolver_test_case.dart'; @@ -30,21 +27,6 @@ }''', [StaticTypeWarningCode.UNDEFINED_ENUM_CONSTANT]); } - test_ambiguousImport_function() async { - Source source = addSource(r''' -import 'lib1.dart'; -import 'lib2.dart'; -g() { return f(); }'''); - addNamedSource("/lib1.dart", r''' -library lib1; -f() {}'''); - addNamedSource("/lib2.dart", r''' -library lib2; -f() {}'''); - await computeAnalysisResult(source); - assertErrors(source, [StaticWarningCode.AMBIGUOUS_IMPORT]); - } - test_assert_message_suppresses_type_promotion() async { // If a variable is assigned to inside the expression for an assert // message, type promotion should be suppressed, just as it would be if the @@ -218,11 +200,12 @@ }''', [StaticTypeWarningCode.EXPECTED_ONE_LIST_TYPE_ARGUMENTS]); } - test_expectedTwoMapTypeArguments_one() async { + @failingTest + test_expectedOneSetTypeArgument() async { await assertErrorsInCode(r''' main() { - <int> {}; -}''', [StaticTypeWarningCode.EXPECTED_TWO_MAP_TYPE_ARGUMENTS]); + <int, int>{2, 3}; +}''', [StaticTypeWarningCode.EXPECTED_ONE_SET_TYPE_ARGUMENTS]); } test_expectedTwoMapTypeArguments_three() async { @@ -457,16 +440,6 @@ ''', [StaticTypeWarningCode.ILLEGAL_SYNC_GENERATOR_RETURN_TYPE]); } - test_instanceAccessToStaticMember_method_invocation() async { - await assertErrorsInCode(r''' -class A { - static m() {} -} -main(A a) { - a.m(); -}''', [StaticTypeWarningCode.INSTANCE_ACCESS_TO_STATIC_MEMBER]); - } - test_instanceAccessToStaticMember_method_reference() async { await assertErrorsInCode(r''' class A { @@ -617,85 +590,6 @@ }''', [StaticTypeWarningCode.INVALID_ASSIGNMENT]); } - test_invocationOfNonFunction_class() async { - await assertErrorsInCode(r''' -class A { - void m() { - A(); - } -}''', previewDart2 ? [] : [StaticTypeWarningCode.INVOCATION_OF_NON_FUNCTION]); - } - - test_invocationOfNonFunction_dynamic() async { - await assertErrorsInCode(r''' -main() { - dynamic d; - d.hashCode(); -} -''', [StaticTypeWarningCode.INVOCATION_OF_NON_FUNCTION]); - } - - test_invocationOfNonFunction_localGenericFunction() async { - // Invoking `.call` on a `Function` type works similarly to invoking it on - // `dynamic`--the invocation is accepted at compile time, and all type - // checking is deferred until runtime. - await assertErrorsInCode(''' -f(Function f) { - return f(); -}''', []); - } - - test_invocationOfNonFunction_localObject() async { - await assertErrorsInCode(''' -f(Object o) { - return o(); -}''', [StaticTypeWarningCode.INVOCATION_OF_NON_FUNCTION]); - } - - test_invocationOfNonFunction_localVariable() async { - await assertErrorsInCode(r''' -f() { - int x; - return x(); -}''', [StaticTypeWarningCode.INVOCATION_OF_NON_FUNCTION]); - } - - test_invocationOfNonFunction_ordinaryInvocation() async { - await assertErrorsInCode(r''' -class A { - static int x; -} -class B { - m() { - A.x(); - } -}''', [StaticTypeWarningCode.INVOCATION_OF_NON_FUNCTION]); - // A call to verify(source) fails as A.x() cannot be resolved. - } - - test_invocationOfNonFunction_staticInvocation() async { - await assertErrorsInCode(r''' -class A { - static int get g => 0; - f() { - A.g(); - } -}''', [StaticTypeWarningCode.INVOCATION_OF_NON_FUNCTION]); - // A call to verify(source) fails as g() cannot be resolved. - } - - test_invocationOfNonFunction_superExpression() async { - await assertErrorsInCode(r''' -class A { - int get g => 0; -} -class B extends A { - m() { - var v = super.g(); - } -}''', [StaticTypeWarningCode.INVOCATION_OF_NON_FUNCTION]); - } - test_invocationOfNonFunctionExpression_literal() async { await assertErrorsInCode(r''' f() { @@ -1348,34 +1242,6 @@ }''', [StaticTypeWarningCode.UNDEFINED_GETTER]); } - test_undefinedFunction() async { - await assertErrorsInCode(r''' -void f() { - g(); -}''', [StaticTypeWarningCode.UNDEFINED_FUNCTION]); - } - - test_undefinedFunction_inCatch() async { - await assertErrorsInCode(r''' -void f() { - try { - } on Object { - g(); - } -}''', [StaticTypeWarningCode.UNDEFINED_FUNCTION]); - } - - test_undefinedFunction_inImportedLib() async { - Source source = addSource(r''' -import 'lib.dart' as f; -main() { return f.g(); }'''); - addNamedSource("/lib.dart", r''' -library lib; -h() {}'''); - await computeAnalysisResult(source); - assertErrors(source, [StaticTypeWarningCode.UNDEFINED_FUNCTION]); - } - test_undefinedGetter() async { await assertErrorsInUnverifiedCode(r''' class T {} @@ -1433,12 +1299,11 @@ test_undefinedGetter_typeLiteral_conditionalAccess() async { // When applied to a type literal, the conditional access operator '?.' // cannot be used to access instance getters of Type. - // TODO(brianwilkerson) We cannot verify in previewDart2 because hashCode - // isn't resolved. + // TODO(brianwilkerson) We cannot verify because hashCode isn't resolved. await assertErrorsInCode(''' class A {} f() => A?.hashCode; -''', [StaticTypeWarningCode.UNDEFINED_GETTER], verify: !previewDart2); +''', [StaticTypeWarningCode.UNDEFINED_GETTER], verify: false); } test_undefinedGetter_wrongNumberOfTypeArguments_tooLittle() async { @@ -1471,15 +1336,6 @@ }''', [StaticTypeWarningCode.NON_TYPE_AS_TYPE_ARGUMENT]); } - test_undefinedMethod() async { - await assertErrorsInCode(r''' -class A { - void m() { - n(); - } -}''', [StaticTypeWarningCode.UNDEFINED_METHOD]); - } - test_undefinedMethod_assignmentExpression() async { await assertErrorsInCode(r''' class A {} @@ -1491,17 +1347,6 @@ }''', [StaticTypeWarningCode.UNDEFINED_METHOD]); } - test_undefinedMethod_generic_function_call() async { - // Invoking `.call` on a `Function` type works similarly to invoking it on - // `dynamic`--the invocation is accepted at compile time, and all type - // checking is deferred until runtime. - await assertErrorsInCode(''' -f(Function f) { - f.call(); -} -''', []); - } - test_undefinedMethod_ignoreTypePropagation() async { await assertErrorsInCode(r''' class A {} @@ -1521,14 +1366,6 @@ [StaticTypeWarningCode.UNDEFINED_METHOD]); } - test_undefinedMethod_object_call() async { - await assertErrorsInCode(''' -f(Object o) { - o.call(); -} -''', [StaticTypeWarningCode.UNDEFINED_METHOD]); - } - test_undefinedMethod_ofNull() async { // TODO(scheglov) Track https://github.com/dart-lang/sdk/issues/28430 to // decide whether a warning should be reported here. @@ -1540,69 +1377,15 @@ ''', [StaticTypeWarningCode.UNDEFINED_METHOD]); } - test_undefinedMethod_private() async { - addNamedSource("/lib.dart", r''' -library lib; -class A { - _foo() {} -}'''); - await assertErrorsInCode(r''' -import 'lib.dart'; -class B extends A { - test() { - _foo(); - } -}''', [StaticTypeWarningCode.UNDEFINED_METHOD]); - } - - test_undefinedMethod_proxy_annotation_fakeProxy() async { - await assertErrorsInCode(r''' -library L; -class Fake { - const Fake(); -} -const proxy = const Fake(); -@proxy class PrefixProxy {} -main() { - new PrefixProxy().foo(); -}''', [StaticTypeWarningCode.UNDEFINED_METHOD]); - } - - test_undefinedMethod_typeLiteral_cascadeTarget() async { - await assertErrorsInCode(''' -class T { - static void foo() {} -} -main() { - T..foo(); -} -''', [StaticTypeWarningCode.UNDEFINED_METHOD]); - } - - test_undefinedMethod_typeLiteral_conditionalAccess() async { - // When applied to a type literal, the conditional access operator '?.' - // cannot be used to access instance methods of Type. - await assertErrorsInCode(''' -class A {} -f() => A?.toString(); -''', [StaticTypeWarningCode.UNDEFINED_METHOD]); - } - test_undefinedMethodWithConstructor() async { - // TODO(brianwilkerson) We cannot verify in previewDart2 because 'C' could - // not be resolved. - await assertErrorsInCode( - r''' + // TODO(brianwilkerson) We cannot verify because 'C' could not be resolved. + await assertErrorsInCode(r''' class C { C.m(); } f() { C c = C.m(); -}''', - previewDart2 - ? [] - : [StaticTypeWarningCode.UNDEFINED_METHOD_WITH_CONSTRUCTOR], - verify: !previewDart2); +}''', [], verify: false); } test_undefinedOperator_indexBoth() async { @@ -1610,7 +1393,10 @@ class A {} f(A a) { a[0]++; -}''', [StaticTypeWarningCode.UNDEFINED_OPERATOR]); +}''', [ + StaticTypeWarningCode.UNDEFINED_OPERATOR, + StaticTypeWarningCode.UNDEFINED_OPERATOR, + ]); } test_undefinedOperator_indexGetter() async { @@ -1701,18 +1487,6 @@ ''', [StaticTypeWarningCode.UNQUALIFIED_REFERENCE_TO_NON_LOCAL_STATIC_MEMBER]); } - test_unqualifiedReferenceToNonLocalStaticMember_method() async { - await assertErrorsInCode(r''' -class A { - static void a() {} -} -class B extends A { - void b() { - a(); - } -}''', [StaticTypeWarningCode.UNQUALIFIED_REFERENCE_TO_NON_LOCAL_STATIC_MEMBER]); - } - test_unqualifiedReferenceToNonLocalStaticMember_setter() async { await assertErrorsInCode(r''' class A { @@ -1883,26 +1657,6 @@ resetWith(options: options); } - test_genericMethodWrongNumberOfTypeArguments() async { - Source source = addSource(''' -f() {} -main() { - f<int>(); -} -'''); - TestAnalysisResult analysisResult = await computeAnalysisResult(source); - assertErrors( - source, [StaticTypeWarningCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS_METHOD]); - for (AnalysisError error in analysisResult.errors) { - if (error.errorCode == - StaticTypeWarningCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS) { - expect(error.message, - formatList(error.errorCode.message, ['() → dynamic', 0, 1])); - } - } - verify([source]); - } - test_legalAsyncGeneratorReturnType_function_supertypeOfStream() async { await assertErrorsInCode(''' import 'dart:async';
diff --git a/pkg/analyzer/test/generated/static_warning_code_driver_test.dart b/pkg/analyzer/test/generated/static_warning_code_driver_test.dart index adf005d..699954f 100644 --- a/pkg/analyzer/test/generated/static_warning_code_driver_test.dart +++ b/pkg/analyzer/test/generated/static_warning_code_driver_test.dart
@@ -16,4 +16,8 @@ class StaticWarningCodeTest_Driver extends StaticWarningCodeTest { @override bool get enableNewAnalysisDriver => true; + + test_setElementTypeNotAssignable() async { + return super.test_setElementTypeNotAssignable(); + } }
diff --git a/pkg/analyzer/test/generated/static_warning_code_test.dart b/pkg/analyzer/test/generated/static_warning_code_test.dart index 4b7068e..07f6d2f 100644 --- a/pkg/analyzer/test/generated/static_warning_code_test.dart +++ b/pkg/analyzer/test/generated/static_warning_code_test.dart
@@ -274,24 +274,6 @@ assertErrors(source, [StaticWarningCode.AMBIGUOUS_IMPORT]); } - test_ambiguousImport_withPrefix() async { - Source source = addSource(r''' -library test; -import 'lib1.dart' as p; -import 'lib2.dart' as p; -main() { - p.f(); -}'''); - addNamedSource("/lib1.dart", r''' -library lib1; -f() {}'''); - addNamedSource("/lib2.dart", r''' -library lib2; -f() {}'''); - await computeAnalysisResult(source); - assertErrors(source, [StaticWarningCode.AMBIGUOUS_IMPORT]); - } - test_argumentTypeNotAssignable_ambiguousClassName() async { // See dartbug.com/19624 Source source = addNamedSource("/lib1.dart", r''' @@ -315,10 +297,6 @@ expect(StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE, error.errorCode); String message = error.message; expect(message.indexOf("_A") != -1, isTrue); - if (!previewDart2) { - expect(message.indexOf("lib1.dart") != -1, isTrue); - expect(message.indexOf("lib2.dart") != -1, isTrue); - } } test_argumentTypeNotAssignable_annotation_namedConstructor() async { @@ -501,11 +479,7 @@ acceptFunNumOptBool(funNumBool); }'''); await computeAnalysisResult(source); - if (previewDart2) { - assertErrors(source, [StrongModeCode.INVALID_CAST_FUNCTION]); - } else { - assertErrors(source, [StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE]); - } + assertErrors(source, [StrongModeCode.INVALID_CAST_FUNCTION]); verify([source]); } @@ -1111,15 +1085,10 @@ A(String this.x) {} }'''); await computeAnalysisResult(source); - if (previewDart2) { - assertErrors(source, [ - StaticWarningCode.FIELD_INITIALIZING_FORMAL_NOT_ASSIGNABLE, - StrongModeCode.INVALID_PARAMETER_DECLARATION - ]); - } else { - assertErrors( - source, [StaticWarningCode.FIELD_INITIALIZING_FORMAL_NOT_ASSIGNABLE]); - } + assertErrors(source, [ + StaticWarningCode.FIELD_INITIALIZING_FORMAL_NOT_ASSIGNABLE, + StrongModeCode.INVALID_PARAMETER_DECLARATION + ]); verify([source]); } @@ -1356,11 +1325,7 @@ } '''); await computeAnalysisResult(source); - if (previewDart2) { - assertNoErrors(source); - } else { - assertErrors(source, [StaticTypeWarningCode.INVALID_ASSIGNMENT]); - } + assertNoErrors(source); } test_generalizedVoid_interpolateVoidValueError() async { @@ -1374,51 +1339,6 @@ assertErrors(source, [StaticWarningCode.USE_OF_VOID_RESULT]); } - test_generalizedVoid_invocationOfVoidFieldError() async { - Source source = addSource(r''' -class Container<T>{ - T value; -} -void main(Container<void> voidContainer) { - voidContainer.value(); -} -'''); - await computeAnalysisResult(source); - assertErrors(source, [StaticWarningCode.USE_OF_VOID_RESULT]); - } - - test_generalizedVoid_invocationOfVoidLocalError() async { - Source source = addSource(r''' -void main() { - void x; - x(); -} -'''); - await computeAnalysisResult(source); - assertErrors(source, [StaticWarningCode.USE_OF_VOID_RESULT]); - } - - test_generalizedVoid_invocationOfVoidResultError() async { - Source source = addSource(r''' -void main() { - main()(); -} -'''); - await computeAnalysisResult(source); - assertErrors(source, [StaticWarningCode.USE_OF_VOID_RESULT]); - } - - test_generalizedVoid_invocationOfVoidToplevelError() async { - Source source = addSource(r''' -void x; -void main() { - x(); -} -'''); - await computeAnalysisResult(source); - assertErrors(source, [StaticWarningCode.USE_OF_VOID_RESULT]); - } - test_generalizedVoid_negateVoidValueError() async { Source source = addSource(r''' void main() { @@ -1533,28 +1453,6 @@ assertErrors(source, [StaticWarningCode.USE_OF_VOID_RESULT]); } - test_generalizedVoid_useOfVoidCallMethodError() async { - Source source = addSource(r''' -void main() { - void x; - x.toString(); -} -'''); - await computeAnalysisResult(source); - assertErrors(source, [StaticWarningCode.USE_OF_VOID_RESULT]); - } - - test_generalizedVoid_useOfVoidCallMethodWithNullError() async { - Source source = addSource(r''' -void main() { - void x; - x?.toString(); -} -'''); - await computeAnalysisResult(source); - assertErrors(source, [StaticWarningCode.USE_OF_VOID_RESULT]); - } - test_generalizedVoid_useOfVoidCallSetterError() async { Source source = addSource(r''' void main() { @@ -1566,17 +1464,6 @@ assertErrors(source, [StaticWarningCode.USE_OF_VOID_RESULT]); } - test_generalizedVoid_useOfVoidCascadeError() async { - Source source = addSource(r''' -void main() { - void x; - x..toString(); -} -'''); - await computeAnalysisResult(source); - assertErrors(source, [StaticWarningCode.USE_OF_VOID_RESULT]); - } - test_generalizedVoid_useOfVoidCastsOk() async { Source source = addSource(r''' void use(dynamic x) { } @@ -2257,13 +2144,7 @@ } '''); await computeAnalysisResult(source); - if (previewDart2) { - assertNoErrors(source); - } else { - assertErrors(source, [ - StaticWarningCode.INVALID_OVERRIDE_DIFFERENT_DEFAULT_VALUES_POSITIONAL - ]); - } + assertNoErrors(source); verify([source]); } @@ -2280,12 +2161,7 @@ } '''); await computeAnalysisResult(source); - if (previewDart2) { - assertNoErrors(source); - } else { - assertErrors(source, - [StaticWarningCode.INVALID_OVERRIDE_DIFFERENT_DEFAULT_VALUES_NAMED]); - } + assertNoErrors(source); verify([source]); } @@ -2368,12 +2244,7 @@ m({int p : 1}) {} }'''); await computeAnalysisResult(source); - if (previewDart2) { - assertNoErrors(source); - } else { - assertErrors(source, - [StaticWarningCode.INVALID_OVERRIDE_DIFFERENT_DEFAULT_VALUES_NAMED]); - } + assertNoErrors(source); verify([source]); } @@ -2386,13 +2257,7 @@ m([int p = 1]) {} }'''); await computeAnalysisResult(source); - if (previewDart2) { - assertNoErrors(source); - } else { - assertErrors(source, [ - StaticWarningCode.INVALID_OVERRIDE_DIFFERENT_DEFAULT_VALUES_POSITIONAL - ]); - } + assertNoErrors(source); verify([source]); } @@ -2405,11 +2270,7 @@ m({a}) {} }'''); await computeAnalysisResult(source); - if (previewDart2) { - assertErrors(source, [CompileTimeErrorCode.INVALID_OVERRIDE]); - } else { - assertErrors(source, [StaticWarningCode.INVALID_OVERRIDE_NAMED]); - } + assertErrors(source, [CompileTimeErrorCode.INVALID_OVERRIDE]); verify([source]); } @@ -2422,11 +2283,7 @@ m({a, c}) {} }'''); await computeAnalysisResult(source); - if (previewDart2) { - assertErrors(source, [CompileTimeErrorCode.INVALID_OVERRIDE]); - } else { - assertErrors(source, [StaticWarningCode.INVALID_OVERRIDE_NAMED]); - } + assertErrors(source, [CompileTimeErrorCode.INVALID_OVERRIDE]); verify([source]); } @@ -2439,11 +2296,7 @@ m([a]) {} }'''); await computeAnalysisResult(source); - if (previewDart2) { - assertErrors(source, [CompileTimeErrorCode.INVALID_OVERRIDE]); - } else { - assertErrors(source, [StaticWarningCode.INVALID_OVERRIDE_POSITIONAL]); - } + assertErrors(source, [CompileTimeErrorCode.INVALID_OVERRIDE]); verify([source]); } @@ -2456,11 +2309,7 @@ m(a, b, [c]) {} }'''); await computeAnalysisResult(source); - if (previewDart2) { - assertErrors(source, [CompileTimeErrorCode.INVALID_OVERRIDE]); - } else { - assertErrors(source, [StaticWarningCode.INVALID_OVERRIDE_POSITIONAL]); - } + assertErrors(source, [CompileTimeErrorCode.INVALID_OVERRIDE]); verify([source]); } @@ -2473,11 +2322,7 @@ m(a, [c, d]) {} }'''); await computeAnalysisResult(source); - if (previewDart2) { - assertErrors(source, [CompileTimeErrorCode.INVALID_OVERRIDE]); - } else { - assertErrors(source, [StaticWarningCode.INVALID_OVERRIDE_POSITIONAL]); - } + assertErrors(source, [CompileTimeErrorCode.INVALID_OVERRIDE]); verify([source]); } @@ -2490,11 +2335,7 @@ m(a, b) {} }'''); await computeAnalysisResult(source); - if (previewDart2) { - assertErrors(source, [CompileTimeErrorCode.INVALID_OVERRIDE]); - } else { - assertErrors(source, [StaticWarningCode.INVALID_OVERRIDE_REQUIRED]); - } + assertErrors(source, [CompileTimeErrorCode.INVALID_OVERRIDE]); verify([source]); } @@ -2507,12 +2348,7 @@ void set s(String v) {} }'''); await computeAnalysisResult(source); - if (previewDart2) { - assertErrors(source, [CompileTimeErrorCode.INVALID_OVERRIDE]); - } else { - assertErrors(source, - [StaticWarningCode.INVALID_SETTER_OVERRIDE_NORMAL_PARAM_TYPE]); - } + assertErrors(source, [CompileTimeErrorCode.INVALID_OVERRIDE]); verify([source]); } @@ -2529,15 +2365,10 @@ set setter14(String _) => null; }'''); await computeAnalysisResult(source); - if (previewDart2) { - assertErrors(source, [ - CompileTimeErrorCode.INVALID_OVERRIDE, - CompileTimeErrorCode.INVALID_OVERRIDE, - ]); - } else { - assertErrors(source, - [StaticWarningCode.INVALID_SETTER_OVERRIDE_NORMAL_PARAM_TYPE]); - } + assertErrors(source, [ + CompileTimeErrorCode.INVALID_OVERRIDE, + CompileTimeErrorCode.INVALID_OVERRIDE, + ]); verify([source]); } @@ -2555,15 +2386,10 @@ set setter14(String _) => null; }'''); await computeAnalysisResult(source); - if (previewDart2) { - assertErrors(source, [ - CompileTimeErrorCode.INVALID_OVERRIDE, - CompileTimeErrorCode.INVALID_OVERRIDE - ]); - } else { - assertErrors(source, - [StaticWarningCode.INVALID_SETTER_OVERRIDE_NORMAL_PARAM_TYPE]); - } + assertErrors(source, [ + CompileTimeErrorCode.INVALID_OVERRIDE, + CompileTimeErrorCode.INVALID_OVERRIDE + ]); verify([source]); } @@ -2579,15 +2405,10 @@ set s(double d) {} }'''); await computeAnalysisResult(source); - if (previewDart2) { - assertErrors(source, [ - CompileTimeErrorCode.INVALID_OVERRIDE, - CompileTimeErrorCode.INVALID_OVERRIDE - ]); - } else { - assertErrors(source, - [StaticWarningCode.INVALID_SETTER_OVERRIDE_NORMAL_PARAM_TYPE]); - } + assertErrors(source, [ + CompileTimeErrorCode.INVALID_OVERRIDE, + CompileTimeErrorCode.INVALID_OVERRIDE + ]); verify([source]); } @@ -2653,14 +2474,7 @@ } }'''); await computeAnalysisResult(source); - if (previewDart2) { - assertErrors(source, [StaticWarningCode.RETURN_WITHOUT_VALUE]); - } else { - assertErrors(source, [ - StaticWarningCode.MIXED_RETURN_TYPES, - StaticWarningCode.MIXED_RETURN_TYPES - ]); - } + assertErrors(source, [StaticWarningCode.RETURN_WITHOUT_VALUE]); verify([source]); } @@ -3451,11 +3265,15 @@ Null f() {return;} '''); await computeAnalysisResult(source); - if (previewDart2) { - assertNoErrors(source); - } else { - assertErrors(source, [StaticWarningCode.RETURN_WITHOUT_VALUE]); - } + assertNoErrors(source); + } + + @failingTest + test_setElementTypeNotAssignable() async { + Source source = addSource("var v = <String>{42};"); + await computeAnalysisResult(source); + assertErrors(source, [StaticWarningCode.SET_ELEMENT_TYPE_NOT_ASSIGNABLE]); + verify([source]); } test_staticAccessToInstanceMember_method_invocation() async { @@ -3813,11 +3631,7 @@ } }'''); await computeAnalysisResult(source); - if (previewDart2) { - assertNoErrors(source); - } else { - assertErrors(source, [StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE]); - } + assertNoErrors(source); } test_typeTestNonType() async { @@ -3974,29 +3788,6 @@ assertErrors(source, [StaticTypeWarningCode.UNDEFINED_GETTER]); } - test_undefinedStaticMethodOrGetter_method() async { - Source source = addSource(r''' -class C {} -f(var p) { - f(C.m()); -}'''); - await computeAnalysisResult(source); - assertErrors(source, [StaticTypeWarningCode.UNDEFINED_METHOD]); - } - - test_undefinedStaticMethodOrGetter_method_inSuperclass() async { - Source source = addSource(r''' -class S { - static m() {} -} -class C extends S {} -f(var p) { - f(C.m()); -}'''); - await computeAnalysisResult(source); - assertErrors(source, [StaticTypeWarningCode.UNDEFINED_METHOD]); - } - test_undefinedStaticMethodOrGetter_setter_inSuperclass() async { Source source = addSource(r''' class S {
diff --git a/pkg/analyzer/test/generated/strong_mode_test.dart b/pkg/analyzer/test/generated/strong_mode_test.dart index 70a60b6..6b9af7e 100644 --- a/pkg/analyzer/test/generated/strong_mode_test.dart +++ b/pkg/analyzer/test/generated/strong_mode_test.dart
@@ -2909,7 +2909,7 @@ } /// Test cases for [StrongModeStaticTypeAnalyzer2Test] -abstract class StrongModeStaticTypeAnalyzer2TestCases +mixin StrongModeStaticTypeAnalyzer2TestCases implements StaticTypeAnalyzer2TestShared { void expectStaticInvokeType(String search, String type) { var invocation = findIdentifier(search).parent as MethodInvocation; @@ -2927,17 +2927,6 @@ expectInitializerType('foo', 'int'); } - test_dynamicObjectMethod_toString() async { - String code = r''' -main() { - dynamic a = null; - var foo = a.toString(); -} -'''; - await resolveTestUnit(code); - expectInitializerType('foo', 'String'); - } - test_futureOr_promotion1() async { // Test that promotion from FutureOr<T> to T works for concrete types String code = r''' @@ -3612,22 +3601,6 @@ verify([source]); } - test_genericMethod_partiallyAppliedErrorWithBound() async { - await resolveTestUnit(r''' -void f<X extends List, Y>() => null; - -void test() { - f<int>(); -} -''', noErrors: false); - assertErrors(testSource, [ - // Make sure to catch both the missing parameter: - StaticTypeWarningCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS_METHOD, - // And the incorrect parameter: - StaticTypeWarningCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS - ]); - } - test_genericMethod_propagatedType_promotion() async { // Regression test for: // https://github.com/dart-lang/sdk/issues/25340
diff --git a/pkg/analyzer/test/generated/test_all.dart b/pkg/analyzer/test/generated/test_all.dart index 3b976b4..ac07574 100644 --- a/pkg/analyzer/test/generated/test_all.dart +++ b/pkg/analyzer/test/generated/test_all.dart
@@ -5,7 +5,6 @@ import 'package:test_reflective_loader/test_reflective_loader.dart'; import 'all_the_rest_test.dart' as all_the_rest; -import 'bazel_test.dart' as bazel_test; import 'checked_mode_compile_time_error_code_driver_test.dart' as checked_mode_compile_time_error_code_driver_test; import 'checked_mode_compile_time_error_code_test.dart' @@ -19,7 +18,6 @@ import 'engine_test.dart' as engine_test; import 'error_suppression_driver_test.dart' as error_suppression_driver_test; import 'error_suppression_test.dart' as error_suppression_test; -import 'gn_test.dart' as gn_test; import 'hint_code_driver_test.dart' as hint_code_driver_test; import 'hint_code_test.dart' as hint_code_test; import 'inheritance_manager_test.dart' as inheritance_manager_test; @@ -31,8 +29,6 @@ import 'non_error_resolver_test.dart' as non_error_resolver_test; import 'non_hint_code_driver_test.dart' as non_hint_code_driver_test; import 'non_hint_code_test.dart' as non_hint_code_test; -import 'package_build_test.dart' as package_build_test; -import 'package_test.dart' as package_test; import 'parser_fasta_test.dart' as parser_fasta_test; import 'parser_test.dart' as parser_test; import 'resolver_driver_test.dart' as resolver_driver_test; @@ -59,7 +55,6 @@ main() { defineReflectiveSuite(() { all_the_rest.main(); - bazel_test.main(); checked_mode_compile_time_error_code_driver_test.main(); checked_mode_compile_time_error_code_test.main(); compile_time_error_code_driver_test.main(); @@ -70,7 +65,6 @@ engine_test.main(); error_suppression_driver_test.main(); error_suppression_test.main(); - gn_test.main(); hint_code_driver_test.main(); hint_code_test.main(); inheritance_manager_test.main(); @@ -82,8 +76,6 @@ non_error_resolver_test.main(); non_hint_code_driver_test.main(); non_hint_code_test.main(); - package_build_test.main(); - package_test.main(); parser_fasta_test.main(); parser_test.main(); resolver_driver_test.main();
diff --git a/pkg/analyzer/test/generated/test_support.dart b/pkg/analyzer/test/generated/test_support.dart index 8a6e9d4..e44dd22 100644 --- a/pkg/analyzer/test/generated/test_support.dart +++ b/pkg/analyzer/test/generated/test_support.dart
@@ -1,4 +1,4 @@ -// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file +// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. @@ -133,7 +133,7 @@ throw new ArgumentError("Not found '$prefix'."); } AstNode node = new NodeLocator(offset).searchWithin(root); - return node.getAncestor(predicate); + return node.thisOrAncestorMatching(predicate); } /**
diff --git a/pkg/analyzer/test/generated/type_system_test.dart b/pkg/analyzer/test/generated/type_system_test.dart index 67110dd..b682c79 100644 --- a/pkg/analyzer/test/generated/type_system_test.dart +++ b/pkg/analyzer/test/generated/type_system_test.dart
@@ -1,25 +1,26 @@ -// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file +// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. // Tests related to the [TypeSystem] class. -import 'package:analyzer/analyzer.dart' - show ErrorReporter, ParameterKind, StrongModeCode; import 'package:analyzer/dart/ast/standard_ast_factory.dart' show astFactory; import 'package:analyzer/dart/ast/token.dart' show Keyword; import 'package:analyzer/dart/element/element.dart'; import 'package:analyzer/dart/element/type.dart'; +import 'package:analyzer/error/listener.dart'; import 'package:analyzer/file_system/memory_file_system.dart'; import 'package:analyzer/src/dart/ast/token.dart' show KeywordToken; import 'package:analyzer/src/dart/element/element.dart'; import 'package:analyzer/src/dart/element/type.dart'; +import 'package:analyzer/src/error/codes.dart'; import 'package:analyzer/src/generated/engine.dart'; import 'package:analyzer/src/generated/resolver.dart'; import 'package:analyzer/src/generated/source.dart' show NonExistingSource, UriKind; import 'package:analyzer/src/generated/testing/element_factory.dart'; import 'package:analyzer/src/generated/testing/test_type_provider.dart'; +import 'package:analyzer/src/generated/utilities_dart.dart'; import 'package:path/path.dart' show toUri; import 'package:test/test.dart'; import 'package:test_reflective_loader/test_reflective_loader.dart';
diff --git a/pkg/analyzer/test/parse_compilation_unit_test.dart b/pkg/analyzer/test/parse_compilation_unit_test.dart index a916d00..74a0179 100644 --- a/pkg/analyzer/test/parse_compilation_unit_test.dart +++ b/pkg/analyzer/test/parse_compilation_unit_test.dart
@@ -2,6 +2,7 @@ // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. +// ignore: deprecated_member_use import 'package:analyzer/analyzer.dart'; import 'package:test/test.dart';
diff --git a/pkg/analyzer/test/source/sdk_ext_test.dart b/pkg/analyzer/test/source/sdk_ext_test.dart index b09c36b..4f542d1 100644 --- a/pkg/analyzer/test/source/sdk_ext_test.dart +++ b/pkg/analyzer/test/source/sdk_ext_test.dart
@@ -3,8 +3,8 @@ // BSD-style license that can be found in the LICENSE file. import 'package:analyzer/file_system/file_system.dart'; -import 'package:analyzer/file_system/memory_file_system.dart'; import 'package:analyzer/src/source/sdk_ext.dart'; +import 'package:analyzer/src/test_utilities/resource_provider_mixin.dart'; import 'package:test/test.dart'; import 'package:test_reflective_loader/test_reflective_loader.dart'; @@ -15,9 +15,7 @@ } @reflectiveTest -class SdkExtUriResolverTest { - MemoryResourceProvider resourceProvider; - +class SdkExtUriResolverTest with ResourceProviderMixin { void setUp() { String joinAndEscape(List<String> components) { return resourceProvider.pathContext @@ -25,10 +23,9 @@ .replaceAll(r'\', r'\\'); } - resourceProvider = new MemoryResourceProvider(); - resourceProvider.newFolder(resourceProvider.convertPath('/empty')); - resourceProvider.newFolder(resourceProvider.convertPath('/tmp')); - resourceProvider.newFile(resourceProvider.convertPath('/tmp/_sdkext'), ''' + newFolder('/empty'); + newFolder('/tmp'); + newFile('/tmp/_sdkext', content: ''' { "dart:fox": "slippy.dart", "dart:bear": "grizzly.dart", @@ -41,47 +38,37 @@ test_create_badJSON() { var resolver = new SdkExtUriResolver(null); resolver.addSdkExt(r'''{{{,{{}}},}}''', null); - expect(resolver.length, equals(0)); + expect(resolver.length, 0); } test_create_noSdkExtPackageMap() { var resolver = new SdkExtUriResolver({ - 'fox': <Folder>[ - resourceProvider.getFolder(resourceProvider.convertPath('/empty')) - ] + 'fox': <Folder>[getFolder('/empty')] }); - expect(resolver.length, equals(0)); + expect(resolver.length, 0); } test_create_nullPackageMap() { var resolver = new SdkExtUriResolver(null); - expect(resolver.length, equals(0)); + expect(resolver.length, 0); } test_create_sdkExtPackageMap() { var resolver = new SdkExtUriResolver({ - 'fox': <Folder>[ - resourceProvider.newFolder(resourceProvider.convertPath('/tmp')) - ] + 'fox': <Folder>[newFolder('/tmp')] }); // We have four mappings. - expect(resolver.length, equals(4)); + expect(resolver.length, 4); // Check that they map to the correct paths. - expect(resolver['dart:fox'], - equals(resourceProvider.convertPath('/tmp/slippy.dart'))); - expect(resolver['dart:bear'], - equals(resourceProvider.convertPath('/tmp/grizzly.dart'))); - expect(resolver['dart:relative'], - equals(resourceProvider.convertPath('/relative.dart'))); - expect(resolver['dart:deep'], - equals(resourceProvider.convertPath('/tmp/deep/directory/file.dart'))); + expect(resolver['dart:fox'], convertPath('/tmp/slippy.dart')); + expect(resolver['dart:bear'], convertPath('/tmp/grizzly.dart')); + expect(resolver['dart:relative'], convertPath('/relative.dart')); + expect(resolver['dart:deep'], convertPath('/tmp/deep/directory/file.dart')); } test_restoreAbsolute() { var resolver = new SdkExtUriResolver({ - 'fox': <Folder>[ - resourceProvider.newFolder(resourceProvider.convertPath('/tmp')) - ] + 'fox': <Folder>[newFolder('/tmp')] }); var source = resolver.resolveAbsolute(Uri.parse('dart:fox')); expect(source, isNotNull); @@ -89,8 +76,8 @@ var restoreUri = resolver.restoreAbsolute(source); expect(restoreUri, isNotNull); // Verify that it is 'dart:fox'. - expect(restoreUri.toString(), equals('dart:fox')); - expect(restoreUri.scheme, equals('dart')); - expect(restoreUri.path, equals('fox')); + expect(restoreUri.toString(), 'dart:fox'); + expect(restoreUri.scheme, 'dart'); + expect(restoreUri.path, 'fox'); } }
diff --git a/pkg/analyzer/test/src/abstract_single_unit.dart b/pkg/analyzer/test/src/abstract_single_unit.dart index f8fbb79..164b2f5 100644 --- a/pkg/analyzer/test/src/abstract_single_unit.dart +++ b/pkg/analyzer/test/src/abstract_single_unit.dart
@@ -51,7 +51,7 @@ AstNode findNodeAtOffset(int offset, [Predicate<AstNode> predicate]) { AstNode result = new NodeLocator(offset).searchWithin(testUnit); if (result != null && predicate != null) { - result = result.getAncestor(predicate); + result = result.thisOrAncestorMatching(predicate); } return result; }
diff --git a/pkg/analyzer/test/src/command_line/arguments_test.dart b/pkg/analyzer/test/src/command_line/arguments_test.dart index c612c12..3662f70 100644 --- a/pkg/analyzer/test/src/command_line/arguments_test.dart +++ b/pkg/analyzer/test/src/command_line/arguments_test.dart
@@ -2,12 +2,12 @@ // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. -import 'package:analyzer/file_system/memory_file_system.dart'; import 'package:analyzer/src/command_line/arguments.dart'; import 'package:analyzer/src/context/builder.dart'; import 'package:analyzer/src/dart/sdk/sdk.dart'; import 'package:analyzer/src/generated/engine.dart'; import 'package:analyzer/src/generated/sdk.dart'; +import 'package:analyzer/src/test_utilities/resource_provider_mixin.dart'; import 'package:args/args.dart'; import 'package:test/test.dart'; import 'package:test_reflective_loader/test_reflective_loader.dart'; @@ -19,27 +19,25 @@ } @reflectiveTest -class ArgumentsTest { +class ArgumentsTest with ResourceProviderMixin { void test_createContextBuilderOptions_all() { String dartSdkSummaryPath = 'a'; String defaultAnalysisOptionsFilePath = 'b'; String defaultPackageFilePath = 'c'; String defaultPackagesDirectoryPath = 'd'; - MemoryResourceProvider provider = new MemoryResourceProvider(); ArgParser parser = new ArgParser(); defineAnalysisArguments(parser); List<String> args = [ '--dart-sdk-summary=$dartSdkSummaryPath', '-Dfoo=1', '-Dbar=2', - '--no-declaration-casts', '--no-implicit-casts', '--no-implicit-dynamic', '--options=$defaultAnalysisOptionsFilePath', '--packages=$defaultPackageFilePath', '--package-root=$defaultPackagesDirectoryPath', ]; - ArgResults result = parse(provider, parser, args); + ArgResults result = parse(resourceProvider, parser, args); ContextBuilderOptions options = createContextBuilderOptions(result); expect(options, isNotNull); expect(options.dartSdkSummaryPath, dartSdkSummaryPath); @@ -54,17 +52,15 @@ AnalysisOptionsImpl defaultOptions = options.defaultOptions; expect(defaultOptions, isNotNull); expect(defaultOptions.strongMode, true); - expect(defaultOptions.declarationCasts, false); expect(defaultOptions.implicitCasts, false); expect(defaultOptions.implicitDynamic, false); } void test_createContextBuilderOptions_none() { - MemoryResourceProvider provider = new MemoryResourceProvider(); ArgParser parser = new ArgParser(); defineAnalysisArguments(parser); List<String> args = []; - ArgResults result = parse(provider, parser, args); + ArgResults result = parse(resourceProvider, parser, args); ContextBuilderOptions options = createContextBuilderOptions(result); expect(options, isNotNull); expect(options.dartSdkSummaryPath, isNull); @@ -74,79 +70,61 @@ expect(options.defaultPackagesDirectoryPath, isNull); AnalysisOptionsImpl defaultOptions = options.defaultOptions; expect(defaultOptions, isNotNull); - expect(defaultOptions.strongMode, defaultOptions.previewDart2); - expect(defaultOptions.declarationCasts, true); + expect(defaultOptions.strongMode, true); expect(defaultOptions.implicitCasts, true); expect(defaultOptions.implicitDynamic, true); } void test_createDartSdkManager_noPath_noSummaries() { - MemoryResourceProvider provider = new MemoryResourceProvider(); ArgParser parser = new ArgParser(); defineAnalysisArguments(parser); List<String> args = []; - ArgResults result = parse(provider, parser, args); - DartSdkManager manager = createDartSdkManager(provider, false, result); + ArgResults result = parse(resourceProvider, parser, args); + DartSdkManager manager = + createDartSdkManager(resourceProvider, false, result); expect(manager, isNotNull); expect(manager.defaultSdkDirectory, - FolderBasedDartSdk.defaultSdkDirectory(provider)); + FolderBasedDartSdk.defaultSdkDirectory(resourceProvider)); expect(manager.canUseSummaries, false); } void test_createDartSdkManager_noPath_summaries() { - MemoryResourceProvider provider = new MemoryResourceProvider(); ArgParser parser = new ArgParser(); defineAnalysisArguments(parser); List<String> args = []; - ArgResults result = parse(provider, parser, args); - DartSdkManager manager = createDartSdkManager(provider, true, result); + ArgResults result = parse(resourceProvider, parser, args); + DartSdkManager manager = + createDartSdkManager(resourceProvider, true, result); expect(manager, isNotNull); expect(manager.defaultSdkDirectory, - FolderBasedDartSdk.defaultSdkDirectory(provider)); + FolderBasedDartSdk.defaultSdkDirectory(resourceProvider)); expect(manager.canUseSummaries, true); } void test_createDartSdkManager_path_noSummaries() { - MemoryResourceProvider provider = new MemoryResourceProvider(); ArgParser parser = new ArgParser(); defineAnalysisArguments(parser); List<String> args = ['--dart-sdk=x']; - ArgResults result = parse(provider, parser, args); - DartSdkManager manager = createDartSdkManager(provider, false, result); + ArgResults result = parse(resourceProvider, parser, args); + DartSdkManager manager = + createDartSdkManager(resourceProvider, false, result); expect(manager, isNotNull); expect(manager.defaultSdkDirectory, 'x'); expect(manager.canUseSummaries, false); } void test_createDartSdkManager_path_summaries() { - MemoryResourceProvider provider = new MemoryResourceProvider(); ArgParser parser = new ArgParser(); defineAnalysisArguments(parser); List<String> args = ['--dart-sdk=y']; - ArgResults result = parse(provider, parser, args); - DartSdkManager manager = createDartSdkManager(provider, true, result); + ArgResults result = parse(resourceProvider, parser, args); + DartSdkManager manager = + createDartSdkManager(resourceProvider, true, result); expect(manager, isNotNull); expect(manager.defaultSdkDirectory, 'y'); expect(manager.canUseSummaries, true); } - void test_declarationCast_noImplicitCast() { - MemoryResourceProvider provider = new MemoryResourceProvider(); - ArgParser parser = new ArgParser(); - defineAnalysisArguments(parser); - List<String> args = [ - '--declaration-casts', - '--no-implicit-casts', - ]; - ArgResults result = parse(provider, parser, args); - ContextBuilderOptions options = createContextBuilderOptions(result); - expect(options, isNotNull); - AnalysisOptionsImpl defaultOptions = options.defaultOptions; - expect(defaultOptions, isNotNull); - expect(defaultOptions.declarationCasts, true); - expect(defaultOptions.implicitCasts, false); - } - void test_defineAnalysisArguments() { ArgParser parser = new ArgParser(); defineAnalysisArguments(parser); @@ -179,62 +157,40 @@ expect(result, orderedEquals(['--a', '--c=0', '-e=2', '-f', 'bar'])); } - void test_noAssignmentCast() { - MemoryResourceProvider provider = new MemoryResourceProvider(); + void test_implicitCast() { ArgParser parser = new ArgParser(); defineAnalysisArguments(parser); List<String> args = [ - '--no-declaration-casts', - ]; - ArgResults result = parse(provider, parser, args); - ContextBuilderOptions options = createContextBuilderOptions(result); - expect(options, isNotNull); - AnalysisOptionsImpl defaultOptions = options.defaultOptions; - expect(defaultOptions, isNotNull); - expect(defaultOptions.declarationCasts, false); - expect(defaultOptions.implicitCasts, true); - } - - void test_noAssignmentCast_implicitCast() { - MemoryResourceProvider provider = new MemoryResourceProvider(); - ArgParser parser = new ArgParser(); - defineAnalysisArguments(parser); - List<String> args = [ - '--no-declaration-casts', '--implicit-casts', ]; - ArgResults result = parse(provider, parser, args); + ArgResults result = parse(resourceProvider, parser, args); ContextBuilderOptions options = createContextBuilderOptions(result); expect(options, isNotNull); AnalysisOptionsImpl defaultOptions = options.defaultOptions; expect(defaultOptions, isNotNull); - expect(defaultOptions.declarationCasts, false); expect(defaultOptions.implicitCasts, true); } void test_noImplicitCast() { - MemoryResourceProvider provider = new MemoryResourceProvider(); ArgParser parser = new ArgParser(); defineAnalysisArguments(parser); List<String> args = [ '--no-implicit-casts', ]; - ArgResults result = parse(provider, parser, args); + ArgResults result = parse(resourceProvider, parser, args); ContextBuilderOptions options = createContextBuilderOptions(result); expect(options, isNotNull); AnalysisOptionsImpl defaultOptions = options.defaultOptions; expect(defaultOptions, isNotNull); - expect(defaultOptions.declarationCasts, false); expect(defaultOptions.implicitCasts, false); } void test_parse_noReplacement_noIgnored() { - MemoryResourceProvider provider = new MemoryResourceProvider(); ArgParser parser = new ArgParser(); parser.addFlag('xx'); parser.addOption('yy'); List<String> args = ['--xx', '--yy=abc', 'foo', 'bar']; - ArgResults result = parse(provider, parser, args); + ArgResults result = parse(resourceProvider, parser, args); expect(result, isNotNull); expect(result['xx'], true); expect(result['yy'], 'abc'); @@ -242,17 +198,15 @@ } void test_preprocessArgs_noReplacement() { - MemoryResourceProvider provider = new MemoryResourceProvider(); List<String> original = ['--xx' '--yy' 'baz']; - List<String> result = preprocessArgs(provider, original); + List<String> result = preprocessArgs(resourceProvider, original); expect(result, orderedEquals(original)); expect(identical(original, result), isFalse); } void test_preprocessArgs_replacement_exists() { - MemoryResourceProvider provider = new MemoryResourceProvider(); - String filePath = provider.convertPath('/args.txt'); - provider.newFile(filePath, ''' + String filePath = convertPath('/args.txt'); + newFile(filePath, content: ''' -a --xx @@ -260,16 +214,15 @@ bar '''); List<String> result = - preprocessArgs(provider, ['--preserved', '@$filePath']); + preprocessArgs(resourceProvider, ['--preserved', '@$filePath']); expect(result, orderedEquals(['--preserved', '-a', '--xx', 'foo', 'bar'])); } void test_preprocessArgs_replacement_nonexistent() { - MemoryResourceProvider provider = new MemoryResourceProvider(); - String filePath = provider.convertPath('/args.txt'); + String filePath = convertPath('/args.txt'); List<String> args = ['ignored', '@$filePath']; try { - preprocessArgs(provider, args); + preprocessArgs(resourceProvider, args); fail('Expect exception'); } on Exception catch (e) { expect(e.toString(), contains('Failed to read file')); @@ -278,10 +231,9 @@ } void test_preprocessArgs_replacement_notLast() { - MemoryResourceProvider provider = new MemoryResourceProvider(); - String filePath = provider.convertPath('/args.txt'); + String filePath = convertPath('/args.txt'); List<String> args = ['a', '@$filePath', 'b']; - List<String> result = preprocessArgs(provider, args); + List<String> result = preprocessArgs(resourceProvider, args); expect(result, orderedEquals(args)); } }
diff --git a/pkg/analyzer/test/src/context/abstract_context.dart b/pkg/analyzer/test/src/context/abstract_context.dart index eb77d7e..131646e 100644 --- a/pkg/analyzer/test/src/context/abstract_context.dart +++ b/pkg/analyzer/test/src/context/abstract_context.dart
@@ -6,7 +6,6 @@ import 'package:analyzer/dart/element/element.dart'; import 'package:analyzer/dart/element/visitor.dart'; import 'package:analyzer/file_system/file_system.dart'; -import 'package:analyzer/file_system/memory_file_system.dart'; import 'package:analyzer/src/context/cache.dart'; import 'package:analyzer/src/context/context.dart'; import 'package:analyzer/src/file_system/file_system.dart'; @@ -15,12 +14,12 @@ import 'package:analyzer/src/generated/source.dart'; import 'package:analyzer/src/task/api/model.dart'; import 'package:analyzer/src/task/driver.dart'; +import 'package:analyzer/src/test_utilities/mock_sdk.dart'; +import 'package:analyzer/src/test_utilities/resource_provider_mixin.dart'; import 'package:plugin/manager.dart'; import 'package:plugin/plugin.dart'; import 'package:test/test.dart'; -import 'mock_sdk.dart'; - /** * Finds an [Element] with the given [name]. */ @@ -43,12 +42,7 @@ */ typedef void _ElementVisitorFunction(Element element); -class AbstractContextTest { - static final MockSdk SHARED_MOCK_SDK = new MockSdk(); - static final MockSdk SHARED_STRONG_MOCK_SDK = new MockSdk(); - - MemoryResourceProvider resourceProvider = new MemoryResourceProvider(); - +class AbstractContextTest with ResourceProviderMixin { DartSdk sdk; SourceFactory sourceFactory; AnalysisContextImpl context; @@ -125,8 +119,7 @@ DartSdk createDartSdk() => new MockSdk(resourceProvider: resourceProvider); Source newSource(String path, [String content = '']) { - File file = - resourceProvider.newFile(resourceProvider.convertPath(path), content); + File file = newFile(path, content: content); return file.createSource(); }
diff --git a/pkg/analyzer/test/src/context/builder_test.dart b/pkg/analyzer/test/src/context/builder_test.dart index 45d21f0..3594512 100644 --- a/pkg/analyzer/test/src/context/builder_test.dart +++ b/pkg/analyzer/test/src/context/builder_test.dart
@@ -1,15 +1,13 @@ -// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file +// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. import 'package:analyzer/file_system/file_system.dart'; -import 'package:analyzer/file_system/memory_file_system.dart'; import 'package:analyzer/src/command_line/arguments.dart'; import 'package:analyzer/src/context/builder.dart'; import 'package:analyzer/src/context/context_root.dart'; import 'package:analyzer/src/context/source.dart'; import 'package:analyzer/src/file_system/file_system.dart'; -import 'package:analyzer/src/generated/bazel.dart'; import 'package:analyzer/src/generated/engine.dart'; import 'package:analyzer/src/generated/sdk.dart'; import 'package:analyzer/src/generated/source.dart'; @@ -17,6 +15,9 @@ import 'package:analyzer/src/lint/registry.dart'; import 'package:analyzer/src/services/lint.dart'; import 'package:analyzer/src/source/package_map_resolver.dart'; +import 'package:analyzer/src/test_utilities/mock_sdk.dart'; +import 'package:analyzer/src/test_utilities/resource_provider_mixin.dart'; +import 'package:analyzer/src/workspace/bazel.dart'; import 'package:args/args.dart'; import 'package:package_config/packages.dart'; import 'package:package_config/src/packages_impl.dart'; @@ -26,7 +27,6 @@ import '../../embedder_tests.dart'; import '../../generated/test_support.dart'; -import 'mock_sdk.dart'; main() { defineReflectiveSuite(() { @@ -36,17 +36,7 @@ } @reflectiveTest -class ContextBuilderTest extends EngineTestCase { - /** - * The resource provider to be used by tests. - */ - MemoryResourceProvider resourceProvider; - - /** - * The path context used to manipulate file paths. - */ - path.Context pathContext; - +class ContextBuilderTest extends EngineTestCase with ResourceProviderMixin { /** * The SDK manager used by the tests; */ @@ -79,15 +69,15 @@ _MockLintRule _mockPublicMemberApiDocs; Uri convertedDirectoryUri(String directoryPath) { - return new Uri.directory(resourceProvider.convertPath(directoryPath), - windows: pathContext.style == path.windows.style); + return new Uri.directory(convertPath(directoryPath), + windows: resourceProvider.pathContext.style == path.windows.style); } void createDefaultSdk(Folder sdkDir) { - defaultSdkPath = pathContext.join(sdkDir.path, 'default', 'sdk'); - String librariesFilePath = pathContext.join(defaultSdkPath, 'lib', - '_internal', 'sdk_library_metadata', 'lib', 'libraries.dart'); - resourceProvider.newFile(librariesFilePath, r''' + defaultSdkPath = join(sdkDir.path, 'default', 'sdk'); + String librariesFilePath = join(defaultSdkPath, 'lib', '_internal', + 'sdk_library_metadata', 'lib', 'libraries.dart'); + newFile(librariesFilePath, content: r''' const Map<String, LibraryInfo> libraries = const { "async": const LibraryInfo("async/async.dart"), "core": const LibraryInfo("core/core.dart"), @@ -98,20 +88,17 @@ options: builderOptions); } - void createFile(String path, String content) { - resourceProvider.newFile(path, content); - } - @override void setUp() { - resourceProvider = new MemoryResourceProvider(); - pathContext = resourceProvider.pathContext; new MockSdk(resourceProvider: resourceProvider); - sdkManager = - new DartSdkManager(resourceProvider.convertPath('/sdk'), false); + sdkManager = new DartSdkManager(convertPath('/sdk'), false); contentCache = new ContentCache(); - builder = new ContextBuilder(resourceProvider, sdkManager, contentCache, - options: builderOptions); + builder = new ContextBuilder( + resourceProvider, + sdkManager, + contentCache, + options: builderOptions, + ); } @failingTest @@ -131,11 +118,9 @@ expected.lint = true; expected.lintRules = Registry.ruleRegistry.defaultRules; - String path = resourceProvider.convertPath('/some/directory/path'); - String filePath = - pathContext.join(path, AnalysisEngine.ANALYSIS_OPTIONS_YAML_FILE); - resourceProvider.newFile(filePath, ''' -'''); + String path = convertPath('/some/directory/path'); + String filePath = join(path, AnalysisEngine.ANALYSIS_OPTIONS_YAML_FILE); + newFile(filePath); AnalysisOptions options = builder.getAnalysisOptions(path); _expectEqualOptions(options, expected); @@ -155,10 +140,9 @@ Registry.ruleRegistry['mock_lint_rule'], ]; - String path = resourceProvider.convertPath('/some/directory/path'); - String filePath = - pathContext.join(path, AnalysisEngine.ANALYSIS_OPTIONS_YAML_FILE); - resourceProvider.newFile(filePath, ''' + String path = convertPath('/some/directory/path'); + String filePath = join(path, AnalysisEngine.ANALYSIS_OPTIONS_YAML_FILE); + newFile(filePath, content: ''' linter: rules: - mock_lint_rule @@ -181,10 +165,9 @@ Registry.ruleRegistry['mock_lint_rule'], ]; - String path = resourceProvider.convertPath('/some/directory/path'); - String filePath = - pathContext.join(path, AnalysisEngine.ANALYSIS_OPTIONS_YAML_FILE); - resourceProvider.newFile(filePath, ''' + String path = convertPath('/some/directory/path'); + String filePath = join(path, AnalysisEngine.ANALYSIS_OPTIONS_YAML_FILE); + newFile(filePath, content: ''' linter: rules: - mock_lint_rule @@ -207,10 +190,9 @@ Registry.ruleRegistry['mock_lint_rule'], ]; - String path = resourceProvider.convertPath('/some/directory/path'); - String filePath = - pathContext.join(path, AnalysisEngine.ANALYSIS_OPTIONS_YAML_FILE); - resourceProvider.newFile(filePath, ''' + String path = convertPath('/some/directory/path'); + String filePath = join(path, AnalysisEngine.ANALYSIS_OPTIONS_YAML_FILE); + newFile(filePath, content: ''' linter: rules: - mock_lint_rule @@ -231,10 +213,9 @@ expected.lint = false; expected.lintRules = <LintRule>[]; - String path = resourceProvider.convertPath('/some/directory/path'); - String filePath = - pathContext.join(path, AnalysisEngine.ANALYSIS_OPTIONS_YAML_FILE); - resourceProvider.newFile(filePath, ''' + String path = convertPath('/some/directory/path'); + String filePath = join(path, AnalysisEngine.ANALYSIS_OPTIONS_YAML_FILE); + newFile(filePath, content: ''' '''); AnalysisOptions options = builder.getAnalysisOptions(path); @@ -251,15 +232,15 @@ // options: createContextBuilderOptions(argResults)); // // AnalysisOptionsImpl expected = new AnalysisOptionsImpl(); -// expected.previewDart2 = true; +// expected.option = true; // // String path = resourceProvider.convertPath('/some/directory/path'); // String filePath = -// pathContext.join(path, AnalysisEngine.ANALYSIS_OPTIONS_YAML_FILE); +// join(path, AnalysisEngine.ANALYSIS_OPTIONS_YAML_FILE); // resourceProvider.newFile(filePath, ''' //analyzer: // language: -// enablePreviewDart2: true +// option: true //'''); // // AnalysisOptions options = builder.getAnalysisOptions(path); @@ -276,11 +257,11 @@ void test_convertPackagesToMap_packages() { String fooName = 'foo'; - String fooPath = resourceProvider.convertPath('/pkg/foo'); - Uri fooUri = pathContext.toUri(fooPath); + String fooPath = convertPath('/pkg/foo'); + Uri fooUri = resourceProvider.pathContext.toUri(fooPath); String barName = 'bar'; - String barPath = resourceProvider.convertPath('/pkg/bar'); - Uri barUri = pathContext.toUri(barPath); + String barPath = convertPath('/pkg/bar'); + Uri barUri = resourceProvider.pathContext.toUri(barPath); MapPackages packages = new MapPackages({fooName: fooUri, barName: barUri}); Map<String, List<Folder>> result = builder.convertPackagesToMap(packages); @@ -311,16 +292,16 @@ void test_createPackageMap_fromPackageDirectory_explicit() { // Use a package directory that is outside the project directory. - String rootPath = resourceProvider.convertPath('/root'); - String projectPath = pathContext.join(rootPath, 'project'); - String packageDirPath = pathContext.join(rootPath, 'packages'); + String rootPath = convertPath('/root'); + String projectPath = join(rootPath, 'project'); + String packageDirPath = join(rootPath, 'packages'); String fooName = 'foo'; - String fooPath = pathContext.join(packageDirPath, fooName); + String fooPath = join(packageDirPath, fooName); String barName = 'bar'; - String barPath = pathContext.join(packageDirPath, barName); - resourceProvider.newFolder(projectPath); - resourceProvider.newFolder(fooPath); - resourceProvider.newFolder(barPath); + String barPath = join(packageDirPath, barName); + newFolder(projectPath); + newFolder(fooPath); + newFolder(barPath); builderOptions.defaultPackagesDirectoryPath = packageDirPath; @@ -334,14 +315,14 @@ void test_createPackageMap_fromPackageDirectory_inRoot() { // Use a package directory that is inside the project directory. - String projectPath = resourceProvider.convertPath('/root/project'); - String packageDirPath = pathContext.join(projectPath, 'packages'); + String projectPath = convertPath('/root/project'); + String packageDirPath = join(projectPath, 'packages'); String fooName = 'foo'; - String fooPath = pathContext.join(packageDirPath, fooName); + String fooPath = join(packageDirPath, fooName); String barName = 'bar'; - String barPath = pathContext.join(packageDirPath, barName); - resourceProvider.newFolder(fooPath); - resourceProvider.newFolder(barPath); + String barPath = join(packageDirPath, barName); + newFolder(fooPath); + newFolder(barPath); Packages packages = builder.createPackageMap(projectPath); expect(packages, isNotNull); @@ -353,13 +334,13 @@ void test_createPackageMap_fromPackageFile_explicit() { // Use a package file that is outside the project directory's hierarchy. - String rootPath = resourceProvider.convertPath('/root'); - String projectPath = pathContext.join(rootPath, 'project'); - String packageFilePath = pathContext.join(rootPath, 'child', '.packages'); - resourceProvider.newFolder(projectPath); + String rootPath = convertPath('/root'); + String projectPath = join(rootPath, 'project'); + String packageFilePath = join(rootPath, 'child', '.packages'); + newFolder(projectPath); Uri fooUri = convertedDirectoryUri('/pkg/foo'); Uri barUri = convertedDirectoryUri('/pkg/bar'); - createFile(packageFilePath, ''' + newFile(packageFilePath, content: ''' foo:$fooUri bar:$barUri '''); @@ -375,13 +356,13 @@ void test_createPackageMap_fromPackageFile_inParentOfRoot() { // Use a package file that is inside the parent of the project directory. - String rootPath = resourceProvider.convertPath('/root'); - String projectPath = pathContext.join(rootPath, 'project'); - String packageFilePath = pathContext.join(rootPath, '.packages'); - resourceProvider.newFolder(projectPath); + String rootPath = convertPath('/root'); + String projectPath = join(rootPath, 'project'); + String packageFilePath = join(rootPath, '.packages'); + newFolder(projectPath); Uri fooUri = convertedDirectoryUri('/pkg/foo'); Uri barUri = convertedDirectoryUri('/pkg/bar'); - createFile(packageFilePath, ''' + newFile(packageFilePath, content: ''' foo:$fooUri bar:$barUri '''); @@ -396,13 +377,13 @@ void test_createPackageMap_fromPackageFile_inRoot() { // Use a package file that is inside the project directory. - String rootPath = resourceProvider.convertPath('/root'); - String projectPath = pathContext.join(rootPath, 'project'); - String packageFilePath = pathContext.join(projectPath, '.packages'); - resourceProvider.newFolder(projectPath); + String rootPath = convertPath('/root'); + String projectPath = join(rootPath, 'project'); + String packageFilePath = join(projectPath, '.packages'); + newFolder(projectPath); Uri fooUri = convertedDirectoryUri('/pkg/foo'); Uri barUri = convertedDirectoryUri('/pkg/bar'); - createFile(packageFilePath, ''' + newFile(packageFilePath, content: ''' foo:$fooUri bar:$barUri '''); @@ -416,26 +397,24 @@ } void test_createPackageMap_none() { - String rootPath = resourceProvider.convertPath('/root'); - resourceProvider.newFolder(rootPath); + String rootPath = convertPath('/root'); + newFolder(rootPath); Packages packages = builder.createPackageMap(rootPath); expect(packages, same(Packages.noPackages)); } void test_createPackageMap_rootDoesNotExist() { - String rootPath = resourceProvider.convertPath('/root'); + String rootPath = convertPath('/root'); Packages packages = builder.createPackageMap(rootPath); expect(packages, same(Packages.noPackages)); } void test_createSourceFactory_bazelWorkspace_fileProvider() { - String _p(String path) => resourceProvider.convertPath(path); - - String projectPath = _p('/workspace/my/module'); - resourceProvider.newFile(_p('/workspace/WORKSPACE'), ''); - resourceProvider.newFolder(_p('/workspace/bazel-bin')); - resourceProvider.newFolder(_p('/workspace/bazel-genfiles')); - resourceProvider.newFolder(projectPath); + String projectPath = convertPath('/workspace/my/module'); + newFile('/workspace/WORKSPACE'); + newFolder('/workspace/bazel-bin'); + newFolder('/workspace/bazel-genfiles'); + newFolder(projectPath); AnalysisOptionsImpl options = new AnalysisOptionsImpl(); SourceFactoryImpl factory = @@ -447,14 +426,12 @@ } void test_createSourceFactory_bazelWorkspace_withPackagesFile() { - String _p(String path) => resourceProvider.convertPath(path); - - String projectPath = _p('/workspace/my/module'); - resourceProvider.newFile(_p('/workspace/WORKSPACE'), ''); - resourceProvider.newFolder(_p('/workspace/bazel-bin')); - resourceProvider.newFolder(_p('/workspace/bazel-genfiles')); - resourceProvider.newFolder(projectPath); - resourceProvider.newFile(_p(path.join(projectPath, '.packages')), ''); + String projectPath = convertPath('/workspace/my/module'); + newFile('/workspace/WORKSPACE'); + newFolder('/workspace/bazel-bin'); + newFolder('/workspace/bazel-genfiles'); + newFolder(projectPath); + newFile(join(projectPath, '.packages')); AnalysisOptionsImpl options = new AnalysisOptionsImpl(); SourceFactoryImpl factory = @@ -466,28 +443,28 @@ } void test_createSourceFactory_noProvider_packages_embedder_extensions() { - String rootPath = resourceProvider.convertPath('/root'); - Folder rootFolder = resourceProvider.getFolder(rootPath); + String rootPath = convertPath('/root'); + Folder rootFolder = getFolder(rootPath); createDefaultSdk(rootFolder); - String projectPath = pathContext.join(rootPath, 'project'); - String packageFilePath = pathContext.join(projectPath, '.packages'); - String packageA = pathContext.join(rootPath, 'pkgs', 'a'); - String embedderPath = pathContext.join(packageA, '_embedder.yaml'); - String packageB = pathContext.join(rootPath, 'pkgs', 'b'); - String extensionPath = pathContext.join(packageB, '_sdkext'); - createFile(packageFilePath, ''' -a:${pathContext.toUri(packageA)} -b:${pathContext.toUri(packageB)} + String projectPath = join(rootPath, 'project'); + String packageFilePath = join(projectPath, '.packages'); + String packageA = join(rootPath, 'pkgs', 'a'); + String embedderPath = join(packageA, '_embedder.yaml'); + String packageB = join(rootPath, 'pkgs', 'b'); + String extensionPath = join(packageB, '_sdkext'); + newFile(packageFilePath, content: ''' +a:${resourceProvider.pathContext.toUri(packageA)} +b:${resourceProvider.pathContext.toUri(packageB)} '''); - String asyncPath = pathContext.join(packageA, 'sdk', 'async.dart'); - String corePath = pathContext.join(packageA, 'sdk', 'core.dart'); - createFile(embedderPath, ''' + String asyncPath = join(packageA, 'sdk', 'async.dart'); + String corePath = join(packageA, 'sdk', 'core.dart'); + newFile(embedderPath, content: ''' embedded_libs: "dart:async": ${_relativeUri(asyncPath, from: packageA)} "dart:core": ${_relativeUri(corePath, from: packageA)} '''); - String fooPath = pathContext.join(packageB, 'ext', 'foo.dart'); - createFile(extensionPath, '''{ + String fooPath = join(packageB, 'ext', 'foo.dart'); + newFile(extensionPath, content: '''{ "dart:foo": "${_relativeUri(fooPath, from: packageB)}" }'''); AnalysisOptionsImpl options = new AnalysisOptionsImpl(); @@ -504,25 +481,25 @@ Source packageSource = factory.forUri('package:b/b.dart'); expect(packageSource, isNotNull); - expect(packageSource.fullName, pathContext.join(packageB, 'b.dart')); + expect(packageSource.fullName, join(packageB, 'b.dart')); } void test_createSourceFactory_noProvider_packages_embedder_noExtensions() { - String rootPath = resourceProvider.convertPath('/root'); - Folder rootFolder = resourceProvider.getFolder(rootPath); + String rootPath = convertPath('/root'); + Folder rootFolder = getFolder(rootPath); createDefaultSdk(rootFolder); - String projectPath = pathContext.join(rootPath, 'project'); - String packageFilePath = pathContext.join(projectPath, '.packages'); - String packageA = pathContext.join(rootPath, 'pkgs', 'a'); - String embedderPath = pathContext.join(packageA, '_embedder.yaml'); - String packageB = pathContext.join(rootPath, 'pkgs', 'b'); - createFile(packageFilePath, ''' -a:${pathContext.toUri(packageA)} -b:${pathContext.toUri(packageB)} + String projectPath = join(rootPath, 'project'); + String packageFilePath = join(projectPath, '.packages'); + String packageA = join(rootPath, 'pkgs', 'a'); + String embedderPath = join(packageA, '_embedder.yaml'); + String packageB = join(rootPath, 'pkgs', 'b'); + newFile(packageFilePath, content: ''' +a:${resourceProvider.pathContext.toUri(packageA)} +b:${resourceProvider.pathContext.toUri(packageB)} '''); - String asyncPath = pathContext.join(packageA, 'sdk', 'async.dart'); - String corePath = pathContext.join(packageA, 'sdk', 'core.dart'); - createFile(embedderPath, ''' + String asyncPath = join(packageA, 'sdk', 'async.dart'); + String corePath = join(packageA, 'sdk', 'core.dart'); + newFile(embedderPath, content: ''' embedded_libs: "dart:async": ${_relativeUri(asyncPath, from: packageA)} "dart:core": ${_relativeUri(corePath, from: packageA)} @@ -537,7 +514,7 @@ Source packageSource = factory.forUri('package:b/b.dart'); expect(packageSource, isNotNull); - expect(packageSource.fullName, pathContext.join(packageB, 'b.dart')); + expect(packageSource.fullName, join(packageB, 'b.dart')); } @failingTest @@ -546,16 +523,16 @@ } void test_createSourceFactory_noProvider_packages_noEmbedder_noExtensions() { - String rootPath = resourceProvider.convertPath('/root'); - Folder rootFolder = resourceProvider.getFolder(rootPath); + String rootPath = convertPath('/root'); + Folder rootFolder = getFolder(rootPath); createDefaultSdk(rootFolder); - String projectPath = pathContext.join(rootPath, 'project'); - String packageFilePath = pathContext.join(projectPath, '.packages'); - String packageA = pathContext.join(rootPath, 'pkgs', 'a'); - String packageB = pathContext.join(rootPath, 'pkgs', 'b'); - createFile(packageFilePath, ''' -a:${pathContext.toUri(packageA)} -b:${pathContext.toUri(packageB)} + String projectPath = join(rootPath, 'project'); + String packageFilePath = join(projectPath, '.packages'); + String packageA = join(rootPath, 'pkgs', 'a'); + String packageB = join(rootPath, 'pkgs', 'b'); + newFile(packageFilePath, content: ''' +a:${resourceProvider.pathContext.toUri(packageA)} +b:${resourceProvider.pathContext.toUri(packageB)} '''); AnalysisOptionsImpl options = new AnalysisOptionsImpl(); @@ -563,12 +540,12 @@ Source dartSource = factory.forUri('dart:core'); expect(dartSource, isNotNull); - expect(dartSource.fullName, - pathContext.join(defaultSdkPath, 'lib', 'core', 'core.dart')); + expect( + dartSource.fullName, join(defaultSdkPath, 'lib', 'core', 'core.dart')); Source packageSource = factory.forUri('package:a/a.dart'); expect(packageSource, isNotNull); - expect(packageSource.fullName, pathContext.join(packageA, 'a.dart')); + expect(packageSource.fullName, join(packageA, 'a.dart')); } void test_declareVariables_emptyMap() { @@ -633,10 +610,8 @@ DartSdk sdk = builder.findSdk(null, new AnalysisOptionsImpl()); expect(sdk, isNotNull); Source htmlSource = sdk.mapDartUri('dart:html'); - expect( - htmlSource.fullName, - resourceProvider - .convertPath('/sdk/lib/html/dart2js/html_dart2js.dart')); + expect(htmlSource.fullName, + convertPath('/sdk/lib/html/dart2js/html_dart2js.dart')); expect(htmlSource.exists(), isTrue); } @@ -647,25 +622,19 @@ AnalysisOptionsImpl expected = new AnalysisOptionsImpl(); expected.lint = true; expected.lintRules = <Linter>[_mockLintRule]; - createFile(resourceProvider.convertPath('/root/WORKSPACE'), ''); - createFile( - resourceProvider - .convertPath('/root/dart/analysis_options/lib/default.yaml'), - ''' + newFile('/root/WORKSPACE'); + newFile('/root/dart/analysis_options/lib/default.yaml', content: ''' linter: rules: - mock_lint_rule '''); - createFile( - resourceProvider - .convertPath('/root/dart/analysis_options/lib/flutter.yaml'), - ''' + newFile('/root/dart/analysis_options/lib/flutter.yaml', content: ''' linter: rules: - mock_lint_rule2 '''); - AnalysisOptions options = builder - .getAnalysisOptions(resourceProvider.convertPath('/root/some/path')); + AnalysisOptions options = + builder.getAnalysisOptions(convertPath('/root/some/path')); _expectEqualOptions(options, expected); } @@ -676,18 +645,15 @@ AnalysisOptionsImpl expected = new AnalysisOptionsImpl(); expected.lint = true; expected.lintRules = <Linter>[_mockLintRule]; - String packagesFilePath = - resourceProvider.convertPath('/some/directory/path/.packages'); - createFile(packagesFilePath, 'flutter:/pkg/flutter/lib/'); - String optionsFilePath = resourceProvider - .convertPath('/pkg/flutter/lib/analysis_options_user.yaml'); - createFile(optionsFilePath, ''' + String packagesFilePath = convertPath('/some/directory/path/.packages'); + newFile(packagesFilePath, content: 'flutter:/pkg/flutter/lib/'); + newFile('/pkg/flutter/lib/analysis_options_user.yaml', content: ''' linter: rules: - mock_lint_rule '''); - String projPath = resourceProvider.convertPath('/some/directory/path'); - AnalysisOptions options = builder.getAnalysisOptions(projPath); + String projectPath = convertPath('/some/directory/path'); + AnalysisOptions options = builder.getAnalysisOptions(projectPath); _expectEqualOptions(options, expected); } @@ -697,10 +663,9 @@ builderOptions.defaultOptions = defaultOptions; AnalysisOptionsImpl expected = new AnalysisOptionsImpl(); expected.enableLazyAssignmentOperators = true; - String path = resourceProvider.convertPath('/some/directory/path'); - String filePath = - pathContext.join(path, AnalysisEngine.ANALYSIS_OPTIONS_YAML_FILE); - resourceProvider.newFile(filePath, ''' + String path = convertPath('/some/directory/path'); + String filePath = join(path, AnalysisEngine.ANALYSIS_OPTIONS_YAML_FILE); + newFile(filePath, content: ''' linter: rules: - empty_constructor_bodies @@ -716,10 +681,9 @@ builderOptions.defaultOptions = defaultOptions; AnalysisOptionsImpl expected = new AnalysisOptionsImpl(); expected.implicitDynamic = false; - String path = resourceProvider.convertPath('/some/directory/path'); - String filePath = - pathContext.join(path, AnalysisEngine.ANALYSIS_OPTIONS_YAML_FILE); - resourceProvider.newFile(filePath, ''' + String path = convertPath('/some/directory/path'); + String filePath = join(path, AnalysisEngine.ANALYSIS_OPTIONS_YAML_FILE); + newFile(filePath, content: ''' analyzer: strong-mode: implicit-dynamic: false @@ -730,13 +694,12 @@ } void test_getAnalysisOptions_gnWorkspace() { - String _p(String path) => resourceProvider.convertPath(path); + String _p(String path) => convertPath(path); String projectPath = _p('/workspace/some/path'); - resourceProvider.newFolder(_p('/workspace/.jiri_root')); - resourceProvider.newFile( - _p('/workspace/out/debug/gen/dart.sources/foo_pkg'), - _p('/workspace/foo_pkg/lib')); - resourceProvider.newFolder(projectPath); + newFolder('/workspace/.jiri_root'); + newFile('/workspace/out/debug/gen/dart.sources/foo_pkg', + content: _p('/workspace/foo_pkg/lib')); + newFolder(projectPath); ArgParser argParser = new ArgParser(); defineAnalysisArguments(argParser); ArgResults argResults = argParser.parse([]); @@ -759,25 +722,23 @@ _mockLintRule2, _mockLintRule3 ]; - resourceProvider.newFile( - resourceProvider.convertPath('/mypkgs/somepkg/lib/here.yaml'), ''' + newFile('/mypkgs/somepkg/lib/here.yaml', content: ''' linter: rules: - mock_lint_rule3 '''); - String path = resourceProvider.convertPath('/some/directory/path'); - resourceProvider.newFile(pathContext.join(path, '.packages'), ''' + String path = convertPath('/some/directory/path'); + newFile(join(path, '.packages'), content: ''' somepkg:../../../mypkgs/somepkg/lib '''); - resourceProvider.newFile(pathContext.join(path, 'bar.yaml'), ''' + newFile(join(path, 'bar.yaml'), content: ''' include: package:somepkg/here.yaml linter: rules: - mock_lint_rule2 '''); - String filePath = - pathContext.join(path, AnalysisEngine.ANALYSIS_OPTIONS_YAML_FILE); - resourceProvider.newFile(filePath, ''' + String filePath = join(path, AnalysisEngine.ANALYSIS_OPTIONS_YAML_FILE); + newFile(filePath, content: ''' include: bar.yaml linter: rules: @@ -789,20 +750,18 @@ } void test_getAnalysisOptions_invalid() { - String path = resourceProvider.convertPath('/some/directory/path'); - String filePath = - pathContext.join(path, AnalysisEngine.ANALYSIS_OPTIONS_YAML_FILE); - resourceProvider.newFile(filePath, ';'); + String path = convertPath('/some/directory/path'); + String filePath = join(path, AnalysisEngine.ANALYSIS_OPTIONS_YAML_FILE); + newFile(filePath, content: ';'); AnalysisOptions options = builder.getAnalysisOptions(path); expect(options, isNotNull); } void test_getAnalysisOptions_noDefault_noOverrides() { - String path = resourceProvider.convertPath('/some/directory/path'); - String filePath = - pathContext.join(path, AnalysisEngine.ANALYSIS_OPTIONS_YAML_FILE); - resourceProvider.newFile(filePath, ''' + String path = convertPath('/some/directory/path'); + String filePath = join(path, AnalysisEngine.ANALYSIS_OPTIONS_YAML_FILE); + newFile(filePath, content: ''' linter: rules: - empty_constructor_bodies @@ -815,10 +774,9 @@ void test_getAnalysisOptions_noDefault_overrides() { AnalysisOptionsImpl expected = new AnalysisOptionsImpl(); expected.implicitDynamic = false; - String path = resourceProvider.convertPath('/some/directory/path'); - String filePath = - pathContext.join(path, AnalysisEngine.ANALYSIS_OPTIONS_YAML_FILE); - resourceProvider.newFile(filePath, ''' + String path = convertPath('/some/directory/path'); + String filePath = join(path, AnalysisEngine.ANALYSIS_OPTIONS_YAML_FILE); + newFile(filePath, content: ''' analyzer: strong-mode: implicit-dynamic: false @@ -829,24 +787,41 @@ } void test_getAnalysisOptions_optionsPath() { - String path = resourceProvider.convertPath('/some/directory/path'); - String filePath = - pathContext.join(path, AnalysisEngine.ANALYSIS_OPTIONS_YAML_FILE); - resourceProvider.newFile(filePath, ''' + String path = convertPath('/some/directory/path'); + String filePath = join(path, AnalysisEngine.ANALYSIS_OPTIONS_YAML_FILE); + newFile(filePath, content: ''' linter: rules: - empty_constructor_bodies '''); - ContextRoot root = new ContextRoot(path, [], pathContext: pathContext); + ContextRoot root = + new ContextRoot(path, [], pathContext: resourceProvider.pathContext); builder.getAnalysisOptions(path, contextRoot: root); expect(root.optionsFilePath, equals(filePath)); } + void test_getAnalysisOptions_sdkVersionConstraint() { + var projectPath = convertPath('/test'); + newFile(join(projectPath, AnalysisEngine.PUBSPEC_YAML_FILE), content: ''' +environment: + sdk: ^2.1.0 +'''); + + var options = builder.getAnalysisOptions(projectPath); + expect(options.sdkVersionConstraint.toString(), '^2.1.0'); + } + + void test_getAnalysisOptions_sdkVersionConstraint_any_noOptionsFile() { + var projectPath = convertPath('/test'); + var options = builder.getAnalysisOptions(projectPath); + expect(options.sdkVersionConstraint, isNull); + } + void test_getOptionsFile_explicit() { - String path = resourceProvider.convertPath('/some/directory/path'); - String filePath = resourceProvider.convertPath('/options/analysis.yaml'); - resourceProvider.newFile(filePath, ''); + String path = convertPath('/some/directory/path'); + String filePath = convertPath('/options/analysis.yaml'); + newFile(filePath); builderOptions.defaultAnalysisOptionsFilePath = filePath; File result = builder.getOptionsFile(path); @@ -855,11 +830,11 @@ } void test_getOptionsFile_inParentOfRoot_new() { - String parentPath = resourceProvider.convertPath('/some/directory'); - String path = pathContext.join(parentPath, 'path'); + String parentPath = convertPath('/some/directory'); + String path = join(parentPath, 'path'); String filePath = - pathContext.join(parentPath, AnalysisEngine.ANALYSIS_OPTIONS_YAML_FILE); - resourceProvider.newFile(filePath, ''); + join(parentPath, AnalysisEngine.ANALYSIS_OPTIONS_YAML_FILE); + newFile(filePath); File result = builder.getOptionsFile(path); expect(result, isNotNull); @@ -867,11 +842,10 @@ } void test_getOptionsFile_inParentOfRoot_old() { - String parentPath = resourceProvider.convertPath('/some/directory'); - String path = pathContext.join(parentPath, 'path'); - String filePath = - pathContext.join(parentPath, AnalysisEngine.ANALYSIS_OPTIONS_FILE); - resourceProvider.newFile(filePath, ''); + String parentPath = convertPath('/some/directory'); + String path = join(parentPath, 'path'); + String filePath = join(parentPath, AnalysisEngine.ANALYSIS_OPTIONS_FILE); + newFile(filePath); File result = builder.getOptionsFile(path); expect(result, isNotNull); @@ -879,10 +853,9 @@ } void test_getOptionsFile_inRoot_new() { - String path = resourceProvider.convertPath('/some/directory/path'); - String filePath = - pathContext.join(path, AnalysisEngine.ANALYSIS_OPTIONS_YAML_FILE); - resourceProvider.newFile(filePath, ''); + String path = convertPath('/some/directory/path'); + String filePath = join(path, AnalysisEngine.ANALYSIS_OPTIONS_YAML_FILE); + newFile(filePath); File result = builder.getOptionsFile(path); expect(result, isNotNull); @@ -890,10 +863,9 @@ } void test_getOptionsFile_inRoot_old() { - String path = resourceProvider.convertPath('/some/directory/path'); - String filePath = - pathContext.join(path, AnalysisEngine.ANALYSIS_OPTIONS_FILE); - resourceProvider.newFile(filePath, ''); + String path = convertPath('/some/directory/path'); + String filePath = join(path, AnalysisEngine.ANALYSIS_OPTIONS_FILE); + newFile(filePath); File result = builder.getOptionsFile(path); expect(result, isNotNull); @@ -931,7 +903,6 @@ expect(actual.preserveComments, expected.preserveComments); expect(actual.strongMode, expected.strongMode); expect(actual.strongModeHints, expected.strongModeHints); - expect(actual.declarationCasts, expected.declarationCasts); expect(actual.implicitCasts, expected.implicitCasts); expect(actual.implicitDynamic, expected.implicitDynamic); expect(actual.trackCacheDependencies, expected.trackCacheDependencies); @@ -939,6 +910,7 @@ } Uri _relativeUri(String path, {String from}) { + var pathContext = resourceProvider.pathContext; String relativePath = pathContext.relative(path, from: from); return pathContext.toUri(relativePath); }
diff --git a/pkg/analyzer/test/src/context/cache_test.dart b/pkg/analyzer/test/src/context/cache_test.dart index fbd0736..2b42c7d9 100644 --- a/pkg/analyzer/test/src/context/cache_test.dart +++ b/pkg/analyzer/test/src/context/cache_test.dart
@@ -4,7 +4,6 @@ import 'package:analyzer/exception/exception.dart'; import 'package:analyzer/file_system/file_system.dart'; -import 'package:analyzer/file_system/memory_file_system.dart'; import 'package:analyzer/file_system/physical_file_system.dart'; import 'package:analyzer/src/context/cache.dart'; import 'package:analyzer/src/dart/sdk/sdk.dart'; @@ -14,6 +13,7 @@ import 'package:analyzer/src/source/package_map_resolver.dart'; import 'package:analyzer/src/task/api/model.dart'; import 'package:analyzer/src/task/model.dart'; +import 'package:analyzer/src/test_utilities/resource_provider_mixin.dart'; import 'package:test/test.dart'; import 'package:test_reflective_loader/test_reflective_loader.dart'; @@ -1162,13 +1162,12 @@ } @reflectiveTest -class PackageCachePartitionTest extends CachePartitionTest { - MemoryResourceProvider resourceProvider; +class PackageCachePartitionTest extends CachePartitionTest + with ResourceProviderMixin { Folder rootFolder; CachePartition createPartition() { - resourceProvider = new MemoryResourceProvider(); - rootFolder = resourceProvider.newFolder('/package/root'); + rootFolder = newFolder('/package/root'); return new PackageCachePartition(null, rootFolder); }
diff --git a/pkg/analyzer/test/src/context/context_test.dart b/pkg/analyzer/test/src/context/context_test.dart index b33ce36..9ebd97f 100644 --- a/pkg/analyzer/test/src/context/context_test.dart +++ b/pkg/analyzer/test/src/context/context_test.dart
@@ -2686,7 +2686,7 @@ void test_validateCacheConsistency_deletedFile() { String pathA = '/a.dart'; String pathB = '/b.dart'; - var fileA = newFile(pathA, content: ""); + var fileA = newFile(pathA); var fileB = newFile(pathB, content: "import 'a.dart';"); Source sourceA = fileA.createSource(); Source sourceB = fileB.createSource();
diff --git a/pkg/analyzer/test/src/context/mock_sdk.dart b/pkg/analyzer/test/src/context/mock_sdk.dart deleted file mode 100644 index ba87ba5..0000000 --- a/pkg/analyzer/test/src/context/mock_sdk.dart +++ /dev/null
@@ -1,686 +0,0 @@ -// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file -// for details. All rights reserved. Use of this source code is governed by a -// BSD-style license that can be found in the LICENSE file. - -import 'package:analyzer/file_system/file_system.dart' as resource; -import 'package:analyzer/file_system/memory_file_system.dart' as resource; -import 'package:analyzer/src/context/cache.dart'; -import 'package:analyzer/src/context/context.dart'; -import 'package:analyzer/src/generated/engine.dart' show AnalysisEngine; -import 'package:analyzer/src/generated/sdk.dart'; -import 'package:analyzer/src/generated/source.dart'; -import 'package:analyzer/src/summary/idl.dart' show PackageBundle; -import 'package:analyzer/src/summary/summary_file_builder.dart'; - -const String librariesContent = r''' -const Map<String, LibraryInfo> libraries = const { - "async": const LibraryInfo("async/async.dart"), - "collection": const LibraryInfo("collection/collection.dart"), - "convert": const LibraryInfo("convert/convert.dart"), - "core": const LibraryInfo("core/core.dart"), - "html": const LibraryInfo( - "html/dartium/html_dartium.dart", - dart2jsPath: "html/dart2js/html_dart2js.dart"), - "math": const LibraryInfo("math/math.dart"), - "_foreign_helper": const LibraryInfo("_internal/js_runtime/lib/foreign_helper.dart"), -}; -'''; - -const String sdkRoot = '/sdk'; - -const _MockSdkLibrary _LIB_ASYNC = - const _MockSdkLibrary('dart:async', '$sdkRoot/lib/async/async.dart', ''' -library dart.async; - -import 'dart:math'; - -part 'stream.dart'; - -class Future<T> { - factory Future(computation()) => null; - factory Future.delayed(Duration duration, [T computation()]) => null; - factory Future.microtask(FutureOr<T> computation()) => null; - factory Future.value([FutureOr<T> result]) => null; - - static Future<List<T>> wait<T>( - Iterable<Future<T>> futures) => null; - Future<R> then<R>(FutureOr<R> onValue(T value)) => null; - - Future<T> whenComplete(action()); -} - -class FutureOr<T> {} - -abstract class Completer<T> { - factory Completer() => null; - factory Completer.sync() => null; - Future<T> get future; - void complete([value]); - void completeError(Object error, [StackTrace stackTrace]); - bool get isCompleted; -} - -abstract class Timer { - static void run(void callback()) {} -} - -class _StreamIterator<T> implements StreamIterator<T> {} -class _AsyncStarStreamController {} -Function _asyncThenWrapperHelper(continuation) {} -Function _asyncErrorWrapperHelper(continuation) {} -Future _awaitHelper( - object, Function thenCallback, Function errorCallback, var awaiter) {} -''', const <String, String>{ - '$sdkRoot/lib/async/stream.dart': r''' -part of dart.async; -abstract class Stream<T> { - Future<T> get first; - StreamSubscription<T> listen(void onData(T event), - { Function onError, - void onDone(), - bool cancelOnError}); - Stream(); - factory Stream.fromIterable(Iterable<T> data) => null; -} - -abstract class StreamIterator<T> {} - -abstract class StreamSubscription<T> { - Future cancel(); - void onData(void handleData(T data)); - void onError(Function handleError); - void onDone(void handleDone()); - void pause([Future resumeSignal]); - void resume(); - bool get isPaused; - Future<E> asFuture<E>([E futureValue]); -} - -abstract class StreamTransformer<S, T> {} -''' -}); - -const _MockSdkLibrary _LIB_ASYNC2 = - const _MockSdkLibrary('dart:async2', '$sdkRoot/lib/async2/async2.dart', ''' -library dart.async2; - -class Future {} -'''); - -const _MockSdkLibrary _LIB_COLLECTION = const _MockSdkLibrary( - 'dart:collection', '$sdkRoot/lib/collection/collection.dart', ''' -library dart.collection; - -abstract class HashMap<K, V> implements Map<K, V> {} -'''); - -const _MockSdkLibrary _LIB_CONVERT = const _MockSdkLibrary( - 'dart:convert', '$sdkRoot/lib/convert/convert.dart', ''' -library dart.convert; - -import 'dart:async'; - -abstract class Converter<S, T> implements StreamTransformer {} -class JsonDecoder extends Converter<String, Object> {} -'''); - -const _MockSdkLibrary _LIB_CORE = - const _MockSdkLibrary('dart:core', '$sdkRoot/lib/core/core.dart', ''' -library dart.core; - -import 'dart:async'; -import 'dart:_internal'; - -export 'dart:async' show Future, Stream; - -class Object { - const Object(); - bool operator ==(other) => identical(this, other); - String toString() => 'a string'; - int get hashCode => 0; - Type get runtimeType => null; - dynamic noSuchMethod(Invocation invocation) => null; -} - -class Function {} -class StackTrace {} - -class Symbol { - const factory Symbol(String name) = _SymbolImpl; -} - -class _SymbolImpl { - const _SymbolImpl(String name); -} - -class Type {} - -abstract class Comparable<T> { - int compareTo(T other); -} - -abstract class Pattern {} -abstract class String implements Comparable<String>, Pattern { - external factory String.fromCharCodes(Iterable<int> charCodes, - [int start = 0, int end]); - String operator +(String other) => null; - bool operator ==(Object other); - bool get isEmpty => false; - bool get isNotEmpty => false; - int get length => 0; - int codeUnitAt(int index); - String substring(int len) => null; - String toLowerCase(); - String toUpperCase(); - List<int> get codeUnits; -} -abstract class RegExp implements Pattern { - external factory RegExp(String source); -} - -class bool extends Object { - external const factory bool.fromEnvironment(String name, - {bool defaultValue: false}); -} - -abstract class Invocation {} - -abstract class num implements Comparable<num> { - bool operator ==(Object other); - bool operator <(num other); - bool operator <=(num other); - bool operator >(num other); - bool operator >=(num other); - num operator +(num other); - num operator -(num other); - num operator *(num other); - double operator /(num other); - int operator ^(int other); - int operator |(int other); - int operator <<(int other); - int operator >>(int other); - int operator ~/(num other); - num operator %(num other); - int operator ~(); - num operator -(); - int toInt(); - double toDouble(); - num abs(); - int round(); -} -abstract class int extends num { - external const factory int.fromEnvironment(String name, {int defaultValue}); - - bool get isNegative; - bool get isEven => false; - - int operator &(int other); - int operator |(int other); - int operator ^(int other); - int operator ~(); - int operator <<(int shiftAmount); - int operator >>(int shiftAmount); - - int operator -(); - - external static int parse(String source, - { int radix, - int onError(String source) }); - - String toString(); -} - -abstract class double extends num { - static const double NAN = 0.0 / 0.0; - static const double INFINITY = 1.0 / 0.0; - static const double NEGATIVE_INFINITY = -INFINITY; - static const double MIN_POSITIVE = 5e-324; - static const double MAX_FINITE = 1.7976931348623157e+308; - - double remainder(num other); - double operator +(num other); - double operator -(num other); - double operator *(num other); - double operator %(num other); - double operator /(num other); - int operator ~/(num other); - double operator -(); - double abs(); - double get sign; - int round(); - int floor(); - int ceil(); - int truncate(); - double roundToDouble(); - double floorToDouble(); - double ceilToDouble(); - double truncateToDouble(); - external static double parse(String source, - [double onError(String source)]); -} - -class DateTime extends Object {} - -class Null extends Object { - factory Null._uninstantiable() => null; -} - -class Deprecated extends Object { - final String expires; - const Deprecated(this.expires); -} -const Object deprecated = const Deprecated("next release"); - -class Iterator<E> { - bool moveNext(); - E get current; -} - -abstract class Iterable<E> { - Iterator<E> get iterator; - bool get isEmpty; - E get first; - int get length; - - Iterable<R> map<R>(R f(E e)); - - R fold<R>(R initialValue, - R combine(R previousValue, E element)) => null; - - Iterable<T> expand<T>(Iterable<T> f(E element)); - - Iterable<E> where(bool test(E element)); - - void forEach(void f(E element)); - - List<E> toList(); -} - -class List<E> implements Iterable<E> { - List([int length]); - factory List.from(Iterable elements, {bool growable: true}) => null; - void add(E value) {} - void addAll(Iterable<E> iterable) {} - E operator [](int index) => null; - void operator []=(int index, E value) {} - Iterator<E> get iterator => null; - void clear() {} - - bool get isEmpty => false; - E get first => null; - E get last => null; - -} - -class Map<K, V> extends Object { - Iterable<K> get keys => null; - int get length; - Iterable<V> get values; - V operator [](K key) => null; - void operator []=(K key, V value) {} - Map<RK, RV> cast<RK, RV>(); - bool containsKey(Object key); -} - -class Duration implements Comparable<Duration> {} - -class Exception { - factory Exception([var message]) => null; -} - -external bool identical(Object a, Object b); - -void print(Object object) {} - -class _Proxy { const _Proxy(); } -const Object proxy = const _Proxy(); - -class _Override { const _Override(); } -const Object override = const _Override(); - -class _CompileTimeError { - final String _errorMsg; - _CompileTimeError(this._errorMsg); -} - -class AbstractClassInstantiationError { - AbstractClassInstantiationError(String className); -} - -class FallThroughError { - FallThroughError(); - FallThroughError._create(String url, int line); -} - -abstract class _SyncIterable implements Iterable {} -class _InvocationMirror { - _InvocationMirror._withoutType( - String _functionName, List<Type> _typeArguments, - List _positionalArguments, Map<Symbol, dynamic>_namedArguments, - bool _isSuperInvocation); -} -'''); - -const _MockSdkLibrary _LIB_FOREIGN_HELPER = const _MockSdkLibrary( - 'dart:_foreign_helper', - '$sdkRoot/lib/_foreign_helper/_foreign_helper.dart', ''' -library dart._foreign_helper; - -JS(String typeDescription, String codeTemplate, - [arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11]) -{} -'''); - -const _MockSdkLibrary _LIB_HTML_DART2JS = const _MockSdkLibrary( - 'dart:html', '$sdkRoot/lib/html/dart2js/html_dart2js.dart', ''' -library dart.html; -class HtmlElement {} -'''); - -const _MockSdkLibrary _LIB_HTML_DARTIUM = const _MockSdkLibrary( - 'dart:html', '$sdkRoot/lib/html/dartium/html_dartium.dart', ''' -library dart.dom.html; - -final HtmlDocument document; - -abstract class Element {} - -abstract class HtmlDocument { - Element query(String relativeSelectors) => null; -} - -abstract class HtmlElement extends Element {} - -abstract class AnchorElement extends HtmlElement {} -abstract class BodyElement extends HtmlElement {} -abstract class ButtonElement extends HtmlElement {} -abstract class DivElement extends HtmlElement {} -abstract class InputElement extends HtmlElement {} -abstract class SelectElement extends HtmlElement {} - - -abstract class CanvasElement extends HtmlElement { - Object getContext(String contextId, [Map attributes]); - CanvasRenderingContext2D get context2D; -} - -abstract class CanvasRenderingContext2D {} - -Element query(String relativeSelectors) => null; -'''); - -const _MockSdkLibrary _LIB_INTERCEPTORS = const _MockSdkLibrary( - 'dart:_interceptors', - '$sdkRoot/lib/_internal/js_runtime/lib/interceptors.dart', ''' -library dart._interceptors; -'''); - -const _MockSdkLibrary _LIB_INTERNAL = const _MockSdkLibrary( - 'dart:_internal', '$sdkRoot/lib/_internal/internal.dart', ''' -library dart._internal; -class Symbol {} -class ExternalName { - final String name; - const ExternalName(this.name); -} -'''); - -const _MockSdkLibrary _LIB_MATH = - const _MockSdkLibrary('dart:math', '$sdkRoot/lib/math/math.dart', ''' -library dart.math; - -const double E = 2.718281828459045; -const double PI = 3.1415926535897932; -const double LN10 = 2.302585092994046; - -T min<T extends num>(T a, T b) => null; -T max<T extends num>(T a, T b) => null; - -external double cos(num radians); -external double sin(num radians); -external double sqrt(num radians); -class Random { - bool nextBool() => true; - double nextDouble() => 2.0; - int nextInt() => 1; -} -'''); - -const List<SdkLibrary> _LIBRARIES = const [ - _LIB_CORE, - _LIB_ASYNC, - _LIB_ASYNC2, - _LIB_COLLECTION, - _LIB_CONVERT, - _LIB_FOREIGN_HELPER, - _LIB_MATH, - _LIB_HTML_DART2JS, - _LIB_HTML_DARTIUM, - _LIB_INTERCEPTORS, - _LIB_INTERNAL, -]; - -class MockSdk implements DartSdk { - static const Map<String, String> _URI_MAP = const { - "dart:core": "$sdkRoot/lib/core/core.dart", - "dart:html": "$sdkRoot/lib/html/dartium/html_dartium.dart", - "dart:async": "$sdkRoot/lib/async/async.dart", - "dart:async2": "$sdkRoot/lib/async2/async2.dart", - "dart:async/stream.dart": "$sdkRoot/lib/async/stream.dart", - "dart:collection": "$sdkRoot/lib/collection/collection.dart", - "dart:convert": "$sdkRoot/lib/convert/convert.dart", - "dart:_foreign_helper": "$sdkRoot/lib/_foreign_helper/_foreign_helper.dart", - "dart:_interceptors": - "$sdkRoot/lib/_internal/js_runtime/lib/interceptors.dart", - "dart:_internal": "$sdkRoot/lib/_internal/internal.dart", - "dart:math": "$sdkRoot/lib/math/math.dart" - }; - - final resource.MemoryResourceProvider provider; - - final Map<String, String> uriMap = {}; - - /** - * The [AnalysisContextImpl] which is used for all of the sources. - */ - AnalysisContextImpl _analysisContext; - - @override - final List<SdkLibrary> sdkLibraries = []; - - /** - * The cached linked bundle of the SDK. - */ - PackageBundle _bundle; - - MockSdk( - {bool generateSummaryFiles: false, - resource.MemoryResourceProvider resourceProvider}) - : provider = resourceProvider ?? new resource.MemoryResourceProvider() { - _URI_MAP.forEach((uri, path) { - uriMap[uri] = provider.convertPath(path); - }); - - for (_MockSdkLibrary library in _LIBRARIES) { - var convertedLibrary = library._toProvider(provider); - sdkLibraries.add(convertedLibrary); - } - - for (_MockSdkLibrary library in sdkLibraries) { - provider.newFile(library.path, library.content); - library.parts.forEach((String path, String content) { - provider.newFile(path, content); - }); - } - provider.newFile( - provider.convertPath( - '$sdkRoot/lib/_internal/sdk_library_metadata/lib/libraries.dart'), - librariesContent); - if (generateSummaryFiles) { - List<int> bytes = _computeLinkedBundleBytes(); - provider.newFileWithBytes( - provider.convertPath('/lib/_internal/strong.sum'), bytes); - } - } - - @override - AnalysisContextImpl get context { - if (_analysisContext == null) { - _analysisContext = new _SdkAnalysisContext(this); - SourceFactory factory = new SourceFactory([new DartUriResolver(this)]); - _analysisContext.sourceFactory = factory; - } - return _analysisContext; - } - - @override - String get sdkVersion => throw new UnimplementedError(); - - @override - List<String> get uris => - sdkLibraries.map((SdkLibrary library) => library.shortName).toList(); - - @override - Source fromFileUri(Uri uri) { - String filePath = provider.pathContext.fromUri(uri); - if (!filePath.startsWith(provider.convertPath('$sdkRoot/lib/'))) { - return null; - } - for (SdkLibrary library in sdkLibraries) { - String libraryPath = library.path; - if (filePath == libraryPath) { - try { - resource.File file = provider.getResource(filePath); - Uri dartUri = Uri.parse(library.shortName); - return file.createSource(dartUri); - } catch (exception) { - return null; - } - } - String libraryRootPath = provider.pathContext.dirname(libraryPath) + - provider.pathContext.separator; - if (filePath.startsWith(libraryRootPath)) { - String pathInLibrary = filePath.substring(libraryRootPath.length); - String uriStr = '${library.shortName}/$pathInLibrary'; - try { - resource.File file = provider.getResource(filePath); - Uri dartUri = Uri.parse(uriStr); - return file.createSource(dartUri); - } catch (exception) { - return null; - } - } - } - return null; - } - - @override - PackageBundle getLinkedBundle() { - if (_bundle == null) { - resource.File summaryFile = - provider.getFile(provider.convertPath('/lib/_internal/strong.sum')); - List<int> bytes; - if (summaryFile.exists) { - bytes = summaryFile.readAsBytesSync(); - } else { - bytes = _computeLinkedBundleBytes(); - } - _bundle = new PackageBundle.fromBuffer(bytes); - } - return _bundle; - } - - @override - SdkLibrary getSdkLibrary(String dartUri) { - for (SdkLibrary library in _LIBRARIES) { - if (library.shortName == dartUri) { - return library; - } - } - return null; - } - - @override - Source mapDartUri(String dartUri) { - String path = uriMap[dartUri]; - if (path != null) { - resource.File file = provider.getResource(path); - Uri uri = new Uri(scheme: 'dart', path: dartUri.substring(5)); - return file.createSource(uri); - } - // If we reach here then we tried to use a dartUri that's not in the - // table above. - return null; - } - - /** - * Compute the bytes of the linked bundle associated with this SDK. - */ - List<int> _computeLinkedBundleBytes() { - List<Source> librarySources = sdkLibraries - .map((SdkLibrary library) => mapDartUri(library.shortName)) - .toList(); - return new SummaryBuilder(librarySources, context).build(); - } -} - -class _MockSdkLibrary implements SdkLibrary { - final String shortName; - final String path; - final String content; - final Map<String, String> parts; - - const _MockSdkLibrary(this.shortName, this.path, this.content, - [this.parts = const <String, String>{}]); - - @override - String get category => throw new UnimplementedError(); - - @override - bool get isDart2JsLibrary => throw new UnimplementedError(); - - @override - bool get isDocumented => throw new UnimplementedError(); - - @override - bool get isImplementation => throw new UnimplementedError(); - - @override - bool get isInternal => shortName.startsWith('dart:_'); - - @override - bool get isShared => throw new UnimplementedError(); - - @override - bool get isVmLibrary => throw new UnimplementedError(); - - _MockSdkLibrary _toProvider(resource.MemoryResourceProvider provider) { - return new _MockSdkLibrary( - shortName, - provider.convertPath(path), - content, - parts.map((path, content) { - var convertedPath = provider.convertPath(path); - return new MapEntry(convertedPath, content); - }), - ); - } -} - -/** - * An [AnalysisContextImpl] that only contains sources for a Dart SDK. - */ -class _SdkAnalysisContext extends AnalysisContextImpl { - final DartSdk sdk; - - _SdkAnalysisContext(this.sdk); - - @override - AnalysisCache createCacheFromSourceFactory(SourceFactory factory) { - if (factory == null) { - return super.createCacheFromSourceFactory(factory); - } - return new AnalysisCache( - <CachePartition>[AnalysisEngine.instance.partitionManager.forSdk(sdk)]); - } -}
diff --git a/pkg/analyzer/test/src/context/source_test.dart b/pkg/analyzer/test/src/context/source_test.dart index 18cc9b8..45a5ffc 100644 --- a/pkg/analyzer/test/src/context/source_test.dart +++ b/pkg/analyzer/test/src/context/source_test.dart
@@ -20,8 +20,8 @@ @reflectiveTest class SourceFactoryImplTest extends AbstractContextTest { void test_restoreUri() { - String libPath = resourceProvider.convertPath('/pkgs/somepkg/lib'); - Uri libUri = resourceProvider.getFolder(libPath).toUri(); + String libPath = convertPath('/pkgs/somepkg/lib'); + Uri libUri = getFolder(libPath).toUri(); Map<String, Uri> packageUriMap = <String, Uri>{'foo': libUri}; SourceFactoryImpl sourceFactory = new SourceFactoryImpl( <UriResolver>[new ResourceUriResolver(resourceProvider)],
diff --git a/pkg/analyzer/test/src/dart/analysis/analysis_context_collection_test.dart b/pkg/analyzer/test/src/dart/analysis/analysis_context_collection_test.dart index 0afd0b0..b2870e7 100644 --- a/pkg/analyzer/test/src/dart/analysis/analysis_context_collection_test.dart +++ b/pkg/analyzer/test/src/dart/analysis/analysis_context_collection_test.dart
@@ -1,15 +1,14 @@ -// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. import 'package:analyzer/src/dart/analysis/analysis_context_collection.dart'; +import 'package:analyzer/src/test_utilities/mock_sdk.dart'; import 'package:analyzer/src/test_utilities/resource_provider_mixin.dart'; import 'package:meta/meta.dart'; import 'package:test/test.dart'; import 'package:test_reflective_loader/test_reflective_loader.dart'; -import '../../context/mock_sdk.dart'; - main() { defineReflectiveSuite(() { defineReflectiveTests(AnalysisContextCollectionTest); @@ -17,7 +16,7 @@ } @reflectiveTest -class AnalysisContextCollectionTest extends Object with ResourceProviderMixin { +class AnalysisContextCollectionTest with ResourceProviderMixin { void setUp() { new MockSdk(resourceProvider: resourceProvider); }
diff --git a/pkg/analyzer/test/src/dart/analysis/base.dart b/pkg/analyzer/test/src/dart/analysis/base.dart index e9f6eaa..8f6daf9 100644 --- a/pkg/analyzer/test/src/dart/analysis/base.dart +++ b/pkg/analyzer/test/src/dart/analysis/base.dart
@@ -2,12 +2,14 @@ // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. +import 'package:analyzer/dart/analysis/results.dart'; import 'package:analyzer/dart/element/element.dart'; import 'package:analyzer/dart/element/visitor.dart'; import 'package:analyzer/file_system/file_system.dart'; -import 'package:analyzer/file_system/memory_file_system.dart'; +import 'package:analyzer/src/dart/analysis/byte_store.dart'; import 'package:analyzer/src/dart/analysis/driver.dart'; import 'package:analyzer/src/dart/analysis/file_state.dart'; +import 'package:analyzer/src/dart/analysis/performance_logger.dart'; import 'package:analyzer/src/dart/analysis/status.dart'; import 'package:analyzer/src/file_system/file_system.dart'; import 'package:analyzer/src/generated/engine.dart' show AnalysisOptionsImpl; @@ -16,12 +18,10 @@ import 'package:analyzer/src/generated/source.dart'; import 'package:analyzer/src/source/package_map_resolver.dart'; import 'package:analyzer/src/summary/package_bundle_reader.dart'; -import 'package:analyzer/src/dart/analysis/byte_store.dart'; -import 'package:analyzer/src/dart/analysis/performance_logger.dart'; +import 'package:analyzer/src/test_utilities/mock_sdk.dart'; +import 'package:analyzer/src/test_utilities/resource_provider_mixin.dart'; import 'package:test/test.dart'; -import '../../context/mock_sdk.dart'; - /** * Finds an [Element] with the given [name]. */ @@ -46,8 +46,7 @@ */ typedef void _ElementVisitorFunction(Element element); -class BaseAnalysisDriverTest { - final MemoryResourceProvider provider = new MemoryResourceProvider(); +class BaseAnalysisDriverTest with ResourceProviderMixin { DartSdk sdk; final ByteStore byteStore = new MemoryByteStore(); final FileContentOverlay contentOverlay = new FileContentOverlay(); @@ -60,7 +59,7 @@ AnalysisDriverScheduler scheduler; AnalysisDriver driver; final List<AnalysisStatus> allStatuses = <AnalysisStatus>[]; - final List<AnalysisResult> allResults = <AnalysisResult>[]; + final List<ResolvedUnitResult> allResults = <ResolvedUnitResult>[]; final List<ExceptionResult> allExceptions = <ExceptionResult>[]; String testProject; @@ -71,7 +70,7 @@ void addTestFile(String content, {bool priority: false}) { testCode = content; - provider.newFile(testFile, content); + newFile(testFile, content: content); driver.addFile(testFile); if (priority) { driver.priorityFiles = [testFile]; @@ -82,25 +81,26 @@ {Map<String, List<Folder>> packageMap, SummaryDataStore externalSummaries}) { packageMap ??= <String, List<Folder>>{ - 'test': [provider.getFolder(testProject)], - 'aaa': [provider.getFolder(_p('/aaa/lib'))], - 'bbb': [provider.getFolder(_p('/bbb/lib'))], + 'test': [getFolder(testProject)], + 'aaa': [getFolder('/aaa/lib')], + 'bbb': [getFolder('/bbb/lib')], }; return new AnalysisDriver( scheduler, logger, - provider, + resourceProvider, byteStore, contentOverlay, null, new SourceFactory([ new DartUriResolver(sdk), generatedUriResolver, - new PackageMapUriResolver(provider, packageMap), - new ResourceUriResolver(provider) - ], null, provider), + new PackageMapUriResolver(resourceProvider, packageMap), + new ResourceUriResolver(resourceProvider) + ], null, resourceProvider), createAnalysisOptions(), disableChangesAndCacheAllResults: disableChangesAndCacheAllResults, + enableIndex: true, externalSummaries: externalSummaries); } @@ -137,9 +137,9 @@ } void setUp() { - sdk = new MockSdk(resourceProvider: provider); - testProject = _p('/test/lib'); - testFile = _p('/test/lib/test.dart'); + sdk = new MockSdk(resourceProvider: resourceProvider); + testProject = convertPath('/test/lib'); + testFile = convertPath('/test/lib/test.dart'); logger = new PerformanceLog(logBuffer); scheduler = new AnalysisDriverScheduler(logger); driver = createAnalysisDriver(); @@ -150,8 +150,6 @@ } void tearDown() {} - - String _p(String path) => provider.convertPath(path); } /**
diff --git a/pkg/analyzer/test/src/dart/analysis/context_builder_test.dart b/pkg/analyzer/test/src/dart/analysis/context_builder_test.dart index 86c3094..c98351b 100644 --- a/pkg/analyzer/test/src/dart/analysis/context_builder_test.dart +++ b/pkg/analyzer/test/src/dart/analysis/context_builder_test.dart
@@ -7,16 +7,14 @@ import 'package:analyzer/dart/analysis/analysis_context.dart'; import 'package:analyzer/dart/analysis/context_root.dart'; import 'package:analyzer/dart/analysis/declared_variables.dart'; -import 'package:analyzer/file_system/file_system.dart'; import 'package:analyzer/src/dart/analysis/context_builder.dart'; import 'package:analyzer/src/dart/analysis/context_root.dart'; import 'package:analyzer/src/dart/analysis/driver_based_analysis_context.dart'; +import 'package:analyzer/src/test_utilities/mock_sdk.dart'; import 'package:analyzer/src/test_utilities/resource_provider_mixin.dart'; import 'package:test/test.dart'; import 'package:test_reflective_loader/test_reflective_loader.dart'; -import '../../context/mock_sdk.dart'; - main() { defineReflectiveSuite(() { defineReflectiveTests(ContextBuilderImplTest); @@ -24,7 +22,7 @@ } @reflectiveTest -class ContextBuilderImplTest extends Object with ResourceProviderMixin { +class ContextBuilderImplTest with ResourceProviderMixin { ContextBuilderImpl contextBuilder; ContextRoot contextRoot; @@ -38,11 +36,9 @@ } void setUp() { - resourceProvider.newFolder(resourceProvider.pathContext.dirname( - resourceProvider.pathContext.dirname(io.Platform.resolvedExecutable))); + newFile(io.Platform.resolvedExecutable); // create folders + var folder = newFolder('/home/test'); contextBuilder = new ContextBuilderImpl(resourceProvider: resourceProvider); - String path = resourceProvider.convertPath('/temp/root'); - Folder folder = resourceProvider.newFolder(path); contextRoot = new ContextRootImpl(resourceProvider, folder); }
diff --git a/pkg/analyzer/test/src/dart/analysis/context_locator_test.dart b/pkg/analyzer/test/src/dart/analysis/context_locator_test.dart index 388be9b..03db7aa 100644 --- a/pkg/analyzer/test/src/dart/analysis/context_locator_test.dart +++ b/pkg/analyzer/test/src/dart/analysis/context_locator_test.dart
@@ -1,4 +1,4 @@ -// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. @@ -16,7 +16,7 @@ } @reflectiveTest -class ContextLocatorImplTest extends Object with ResourceProviderMixin { +class ContextLocatorImplTest with ResourceProviderMixin { ContextLocatorImpl contextLocator; ContextRoot findRoot(List<ContextRoot> roots, Resource rootFolder) {
diff --git a/pkg/analyzer/test/src/dart/analysis/context_root_test.dart b/pkg/analyzer/test/src/dart/analysis/context_root_test.dart index 9b6324d..6edc6d2 100644 --- a/pkg/analyzer/test/src/dart/analysis/context_root_test.dart +++ b/pkg/analyzer/test/src/dart/analysis/context_root_test.dart
@@ -3,8 +3,8 @@ // BSD-style license that can be found in the LICENSE file. import 'package:analyzer/file_system/file_system.dart'; -import 'package:analyzer/file_system/memory_file_system.dart'; import 'package:analyzer/src/dart/analysis/context_root.dart'; +import 'package:analyzer/src/test_utilities/resource_provider_mixin.dart'; import 'package:test/test.dart'; import 'package:test_reflective_loader/test_reflective_loader.dart'; @@ -15,50 +15,48 @@ } @reflectiveTest -class ContextRootTest { - MemoryResourceProvider provider = new MemoryResourceProvider(); +class ContextRootTest with ResourceProviderMixin { String rootPath; Folder rootFolder; ContextRootImpl contextRoot; void setUp() { - rootPath = provider.convertPath('/test/root'); - rootFolder = provider.newFolder(rootPath); - contextRoot = new ContextRootImpl(provider, rootFolder); + rootPath = convertPath('/test/root'); + rootFolder = newFolder(rootPath); + contextRoot = new ContextRootImpl(resourceProvider, rootFolder); contextRoot.included.add(rootFolder); } test_analyzedFiles() { - String optionsPath = - provider.convertPath('/test/root/analysis_options.yaml'); - String readmePath = provider.convertPath('/test/root/README.md'); - String aPath = provider.convertPath('/test/root/lib/a.dart'); - String bPath = provider.convertPath('/test/root/lib/src/b.dart'); - String excludePath = provider.convertPath('/test/root/exclude'); - String cPath = provider.convertPath('/test/root/exclude/c.dart'); + String optionsPath = convertPath('/test/root/analysis_options.yaml'); + String readmePath = convertPath('/test/root/README.md'); + String aPath = convertPath('/test/root/lib/a.dart'); + String bPath = convertPath('/test/root/lib/src/b.dart'); + String excludePath = convertPath('/test/root/exclude'); + String cPath = convertPath('/test/root/exclude/c.dart'); - provider.newFile(optionsPath, ''); - provider.newFile(readmePath, ''); - provider.newFile(aPath, ''); - provider.newFile(bPath, ''); - provider.newFile(cPath, ''); - contextRoot.excluded.add(provider.newFolder(excludePath)); + newFile(optionsPath); + newFile(readmePath); + newFile(aPath); + newFile(bPath); + newFile(cPath); + contextRoot.excluded.add(newFolder(excludePath)); expect(contextRoot.analyzedFiles(), unorderedEquals([optionsPath, readmePath, aPath, bPath])); } test_isAnalyzed_explicitlyExcluded() { - String excludePath = provider.convertPath('/test/root/exclude'); - String filePath = provider.convertPath('/test/root/exclude/root.dart'); - contextRoot.excluded.add(provider.newFolder(excludePath)); + String excludePath = convertPath('/test/root/exclude'); + String filePath = convertPath('/test/root/exclude/root.dart'); + contextRoot.excluded.add(newFolder(excludePath)); expect(contextRoot.isAnalyzed(filePath), isFalse); } test_isAnalyzed_explicitlyExcluded_same() { - String aPath = provider.convertPath('/test/root/lib/a.dart'); - String bPath = provider.convertPath('/test/root/lib/b.dart'); - File aFile = provider.getFile(aPath); + String aPath = convertPath('/test/root/lib/a.dart'); + String bPath = convertPath('/test/root/lib/b.dart'); + File aFile = getFile(aPath); contextRoot.excluded.add(aFile); @@ -67,26 +65,26 @@ } test_isAnalyzed_implicitlyExcluded_dot_analysisOptions() { - String filePath = provider.convertPath('/test/root/lib/.analysis_options'); + String filePath = convertPath('/test/root/lib/.analysis_options'); expect(contextRoot.isAnalyzed(filePath), isFalse); } test_isAnalyzed_implicitlyExcluded_dot_packages() { - String filePath = provider.convertPath('/test/root/lib/.packages'); + String filePath = convertPath('/test/root/lib/.packages'); expect(contextRoot.isAnalyzed(filePath), isFalse); } test_isAnalyzed_included() { - String filePath = provider.convertPath('/test/root/lib/root.dart'); + String filePath = convertPath('/test/root/lib/root.dart'); expect(contextRoot.isAnalyzed(filePath), isTrue); } test_isAnalyzed_included_same() { - String aPath = provider.convertPath('/test/root/lib/a.dart'); - String bPath = provider.convertPath('/test/root/lib/b.dart'); - File aFile = provider.getFile(aPath); + String aPath = convertPath('/test/root/lib/a.dart'); + String bPath = convertPath('/test/root/lib/b.dart'); + File aFile = getFile(aPath); - contextRoot = new ContextRootImpl(provider, rootFolder); + contextRoot = new ContextRootImpl(resourceProvider, rootFolder); contextRoot.included.add(aFile); expect(contextRoot.isAnalyzed(aPath), isTrue); @@ -94,8 +92,8 @@ } test_isAnalyzed_packagesDirectory_analyzed() { - String folderPath = provider.convertPath('/test/root/lib/packages'); - provider.newFolder(folderPath); + String folderPath = convertPath('/test/root/lib/packages'); + newFolder(folderPath); expect(contextRoot.isAnalyzed(folderPath), isTrue); } }
diff --git a/pkg/analyzer/test/src/dart/analysis/dependency/base.dart b/pkg/analyzer/test/src/dart/analysis/dependency/base.dart new file mode 100644 index 0000000..8df8a047 --- /dev/null +++ b/pkg/analyzer/test/src/dart/analysis/dependency/base.dart
@@ -0,0 +1,184 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:analyzer/dart/ast/ast.dart'; +import 'package:analyzer/src/dart/analysis/dependency/library_builder.dart'; +import 'package:analyzer/src/dart/analysis/dependency/node.dart'; +import 'package:meta/meta.dart'; +import 'package:test/test.dart'; + +import '../../resolution/driver_resolution.dart'; + +class BaseDependencyTest extends DriverResolutionTest { +// DependencyTracker tracker; + String a; + String b; + String c; + Uri aUri; + Uri bUri; + Uri cUri; + + bool hasDartCore = false; + + void assertNodes( + List<DependencyNode> actualNodes, + List<ExpectedNode> expectedNodes, + ) { + expect(actualNodes, hasLength(expectedNodes.length)); + for (var expectedNode in expectedNodes) { + var topNode = _getNode( + actualNodes, + uri: expectedNode.uri, + name: expectedNode.name, + kind: expectedNode.kind, + ); + + if (expectedNode.classMembers != null) { + assertNodes(topNode.classMembers, expectedNode.classMembers); + } else { + expect(topNode.classMembers, isNull); + } + + if (expectedNode.classTypeParameters != null) { + assertNodes( + topNode.classTypeParameters, + expectedNode.classTypeParameters, + ); + } else { + expect(topNode.classTypeParameters, isNull); + } + } + } + + Future<Library> buildTestLibrary(String path, String content) async { +// if (!hasDartCore) { +// hasDartCore = true; +// await _addLibraryByUri('dart:core'); +// await _addLibraryByUri('dart:async'); +// await _addLibraryByUri('dart:math'); +// await _addLibraryByUri('dart:_internal'); +// } + + newFile(path, content: content); + driver.changeFile(path); + + var units = await _resolveLibrary(path); + var uri = units.first.declaredElement.source.uri; + + return buildLibrary(uri, units, _ReferenceCollector()); + +// tracker.addLibrary(uri, units); +// +// var library = tracker.libraries[uri]; +// expect(library, isNotNull); +// +// return library; + } + + DependencyNode getNode(Library library, + {@required Uri uri, + @required String name, + DependencyNodeKind kind, + String memberOf, + String typeParameterOf}) { + var nodes = library.declaredNodes; + if (memberOf != null) { + var class_ = _getNode(nodes, uri: aUri, name: memberOf); + expect(class_.kind, + anyOf(DependencyNodeKind.CLASS, DependencyNodeKind.MIXIN)); + nodes = class_.classMembers; + } else if (typeParameterOf != null) { + var class_ = _getNode(nodes, uri: aUri, name: typeParameterOf); + expect(class_.kind, + anyOf(DependencyNodeKind.CLASS, DependencyNodeKind.MIXIN)); + nodes = class_.classTypeParameters; + } + return _getNode(nodes, uri: aUri, name: name, kind: kind); + } + + @override + void setUp() { + super.setUp(); +// var logger = PerformanceLog(null); +// tracker = DependencyTracker(logger); + a = convertPath('/test/lib/a.dart'); + b = convertPath('/test/lib/b.dart'); + c = convertPath('/test/lib/c.dart'); + aUri = Uri.parse('package:test/a.dart'); + bUri = Uri.parse('package:test/b.dart'); + cUri = Uri.parse('package:test/c.dart'); + } + +// Future _addLibraryByUri(String uri) async { +// var path = driver.sourceFactory.forUri(uri).fullName; +// var unitResult = await driver.getUnitElement(path); +// +// var signature = ApiSignature(); +// signature.addString(unitResult.signature); +// var signatureBytes = signature.toByteList(); +// +// tracker.addLibraryElement(unitResult.element.library, signatureBytes); +// } + + DependencyNode _getNode(List<DependencyNode> nodes, + {@required Uri uri, @required String name, DependencyNodeKind kind}) { + var nameObj = DependencyName(uri, name); + for (var node in nodes) { + if (node.name == nameObj) { + if (kind != null && node.kind != kind) { + fail('Expected $kind "$name", found ${node.kind}'); + } + return node; + } + } + fail('Expected to find $uri::$name in:\n ${nodes.join('\n ')}'); + } + + Future<List<CompilationUnit>> _resolveLibrary(String libraryPath) async { + var resolvedLibrary = await driver.getResolvedLibrary(libraryPath); + return resolvedLibrary.units.map((ru) => ru.unit).toList(); + } +} + +class ExpectedNode { + final Uri uri; + final String name; + final DependencyNodeKind kind; + final List<ExpectedNode> classMembers; + final List<ExpectedNode> classTypeParameters; + + ExpectedNode( + this.uri, + this.name, + this.kind, { + this.classMembers, + this.classTypeParameters, + }); +} + +/// TODO(scheglov) remove it once we get actual implementation +class _ReferenceCollector implements ReferenceCollector { + @override + Uri get libraryUri => null; + + @override + void addImportPrefix(String name) {} + + @override + void appendExpression(Expression node) {} + + @override + void appendFormalParameters(FormalParameterList formalParameterList) {} + + @override + void appendFunctionBody(FunctionBody node) {} + + @override + void appendTypeAnnotation(TypeAnnotation node) {} + + @override + DependencyNodeDependencies finish(List<int> tokenSignature) { + return DependencyNodeDependencies(tokenSignature, [], [], [], []); + } +}
diff --git a/pkg/analyzer/test/src/dart/analysis/dependency/declared_nodes_test.dart b/pkg/analyzer/test/src/dart/analysis/dependency/declared_nodes_test.dart new file mode 100644 index 0000000..fec1f34 --- /dev/null +++ b/pkg/analyzer/test/src/dart/analysis/dependency/declared_nodes_test.dart
@@ -0,0 +1,1709 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:analyzer/src/dart/analysis/dependency/library_builder.dart' + hide buildLibrary; +import 'package:analyzer/src/dart/analysis/dependency/node.dart'; +import 'package:test/test.dart'; +import 'package:test_reflective_loader/test_reflective_loader.dart'; + +import 'base.dart'; + +main() { + defineReflectiveSuite(() { + defineReflectiveTests(DeclaredNodesTest); + }); +} + +@reflectiveTest +class DeclaredNodesTest extends BaseDependencyTest { + test_class_constructor() async { + var library = await buildTestLibrary(a, r''' +class C { + C(); + C.named(); +} +'''); + assertNodes(library.declaredNodes, [ + ExpectedNode( + aUri, + 'C', + DependencyNodeKind.CLASS, + classMembers: [ + ExpectedNode(aUri, '', DependencyNodeKind.CONSTRUCTOR), + ExpectedNode(aUri, 'named', DependencyNodeKind.CONSTRUCTOR), + ], + ), + ]); + } + + test_class_constructor_api_tokens_notSame_annotation() async { + await _assertApiTokenSignatureNotSame( + 'foo', + DependencyNodeKind.CONSTRUCTOR, + 'class X { X.foo(); }', + 'class X { @deprecated X.foo(); }', + memberOf: 'X', + ); + } + + test_class_constructor_api_tokens_notSame_parameter_add() async { + await _assertApiTokenSignatureNotSame( + 'foo', + DependencyNodeKind.CONSTRUCTOR, + 'class X { X.foo(); }', + 'class X { X.foo(int a); }', + memberOf: 'X', + ); + } + + test_class_constructor_api_tokens_notSame_parameter_name_edit_named() async { + await _assertApiTokenSignatureNotSame( + 'foo', + DependencyNodeKind.CONSTRUCTOR, + 'class X { X.foo({int a}); }', + 'class X { X.foo({int b}); }', + memberOf: 'X', + ); + } + + test_class_constructor_api_tokens_notSame_parameter_type() async { + await _assertApiTokenSignatureNotSame( + 'foo', + DependencyNodeKind.CONSTRUCTOR, + 'class X { X.foo(int a); }', + 'class X { X.foo(double a); }', + memberOf: 'X', + ); + } + + test_class_constructor_api_tokens_same_body() async { + await _assertApiTokenSignatureSame( + 'foo', + DependencyNodeKind.CONSTRUCTOR, + 'class X { X.foo() { print(1); } }', + 'class X { X.foo() { print(2); } }', + memberOf: 'X', + ); + } + + test_class_constructor_api_tokens_same_body_add() async { + await _assertApiTokenSignatureSame( + 'foo', + DependencyNodeKind.CONSTRUCTOR, + 'class X { X.foo(); }', + 'class X { X.foo() {} }', + memberOf: 'X', + ); + } + + test_class_constructor_api_tokens_same_parameter_name_edit_required() async { + await _assertApiTokenSignatureSame( + 'foo', + DependencyNodeKind.CONSTRUCTOR, + 'class X { X.foo(int a); }', + 'class X { X.foo(int b); }', + memberOf: 'X', + ); + } + + test_class_constructor_default() async { + var library = await buildTestLibrary(a, r''' +class C {} +'''); + assertNodes(library.declaredNodes, [ + ExpectedNode( + aUri, + 'C', + DependencyNodeKind.CLASS, + classMembers: [ + ExpectedNode(aUri, '', DependencyNodeKind.CONSTRUCTOR), + ], + ), + ]); + } + + test_class_field() async { + var library = await buildTestLibrary(a, r''' +class C { + int a = 1; + int b = 2, c = 3; +} +'''); + assertNodes(library.declaredNodes, [ + ExpectedNode( + aUri, + 'C', + DependencyNodeKind.CLASS, + classMembers: [ + ExpectedNode(aUri, '', DependencyNodeKind.CONSTRUCTOR), + ExpectedNode(aUri, 'a', DependencyNodeKind.GETTER), + ExpectedNode(aUri, 'b', DependencyNodeKind.GETTER), + ExpectedNode(aUri, 'c', DependencyNodeKind.GETTER), + ExpectedNode(aUri, 'a=', DependencyNodeKind.SETTER), + ExpectedNode(aUri, 'b=', DependencyNodeKind.SETTER), + ExpectedNode(aUri, 'c=', DependencyNodeKind.SETTER), + ], + ), + ]); + } + + test_class_field_api_tokens_notSame_annotation() async { + await _assertApiTokenSignatureNotSame( + 'foo', + DependencyNodeKind.GETTER, + 'class X { int foo = 0; }', + 'class X { @deprecated int foo = 0; }', + memberOf: 'X', + ); + } + + test_class_field_api_tokens_notSame_const() async { + await _assertApiTokenSignatureNotSame( + 'foo', + DependencyNodeKind.GETTER, + 'class X { int foo = 0; }', + 'class X { const int foo = 0; }', + memberOf: 'X', + ); + } + + test_class_field_api_tokens_same_final() async { + await _assertApiTokenSignatureSame( + 'foo', + DependencyNodeKind.GETTER, + 'class X { int foo = 0; }', + 'class X { final int foo = 0; }', + memberOf: 'X', + ); + } + + test_class_field_api_tokens_typed_notSame_type() async { + await _assertApiTokenSignatureNotSame( + 'foo', + DependencyNodeKind.GETTER, + 'class X { int foo = 0; }', + 'class X { num foo = 1; }', + memberOf: 'X', + ); + } + + test_class_field_api_tokens_typed_same_initializer() async { + await _assertApiTokenSignatureSame( + 'foo', + DependencyNodeKind.GETTER, + 'class X { int foo = 0; }', + 'class X { int foo = 1; }', + memberOf: 'X', + ); + } + + test_class_field_api_tokens_untyped_notSame_initializer() async { + await _assertApiTokenSignatureNotSame( + 'foo', + DependencyNodeKind.GETTER, + 'class X { var foo = 0; }', + 'class X { var foo = 1.0; }', + memberOf: 'X', + ); + } + + test_class_field_const() async { + var library = await buildTestLibrary(a, r''' +class X { + const foo = 1; + const bar = 2; +} +'''); + assertNodes(library.declaredNodes, [ + ExpectedNode( + aUri, + 'X', + DependencyNodeKind.CLASS, + classMembers: [ + ExpectedNode(aUri, '', DependencyNodeKind.CONSTRUCTOR), + ExpectedNode(aUri, 'foo', DependencyNodeKind.GETTER), + ExpectedNode(aUri, 'bar', DependencyNodeKind.GETTER), + ], + ), + ]); + } + + test_class_field_const_api_tokens_typed_notSame_initializer() async { + await _assertApiTokenSignatureNotSame( + 'foo', + DependencyNodeKind.GETTER, + 'class X { const int foo = 0; }', + 'class X { const int foo = 1; }', + memberOf: 'X', + ); + } + + test_class_field_final() async { + var library = await buildTestLibrary(a, r''' +class X { + final foo = 1; + final bar = 2; +} +'''); + assertNodes(library.declaredNodes, [ + ExpectedNode( + aUri, + 'X', + DependencyNodeKind.CLASS, + classMembers: [ + ExpectedNode(aUri, '', DependencyNodeKind.CONSTRUCTOR), + ExpectedNode(aUri, 'foo', DependencyNodeKind.GETTER), + ExpectedNode(aUri, 'bar', DependencyNodeKind.GETTER), + ], + ), + ]); + } + + test_class_field_final_api_tokens_typed_notSame_initializer_constClass() async { + await _assertApiTokenSignatureNotSame( + 'foo', + DependencyNodeKind.GETTER, + 'class X { final int foo = 0; const X(); }', + 'class X { final int foo = 1; const X(); }', + memberOf: 'X', + ); + } + + test_class_field_final_api_tokens_typed_same_initializer() async { + await _assertApiTokenSignatureSame( + 'foo', + DependencyNodeKind.GETTER, + 'class X { final int foo = 0; }', + 'class X { final int foo = 1; }', + memberOf: 'X', + ); + } + + test_class_field_final_api_tokens_untyped_notSame_initializer() async { + await _assertApiTokenSignatureNotSame( + 'foo', + DependencyNodeKind.GETTER, + 'class X { final foo = 0; }', + 'class X { final foo = 1.0; }', + memberOf: 'X', + ); + } + + test_class_getter() async { + var library = await buildTestLibrary(a, r''' +class C { + int get foo => 0; + int get bar => 0; +} +'''); + assertNodes(library.declaredNodes, [ + ExpectedNode( + aUri, + 'C', + DependencyNodeKind.CLASS, + classMembers: [ + ExpectedNode(aUri, '', DependencyNodeKind.CONSTRUCTOR), + ExpectedNode(aUri, 'foo', DependencyNodeKind.GETTER), + ExpectedNode(aUri, 'bar', DependencyNodeKind.GETTER), + ], + ), + ]); + } + + test_class_getter_api_tokens_notSame_returnType() async { + await _assertApiTokenSignatureNotSame( + 'foo', + DependencyNodeKind.GETTER, + 'class X { int get foo => null; }', + 'class X { double get foo => null; }', + memberOf: 'X', + ); + } + + test_class_method() async { + var library = await buildTestLibrary(a, r''' +class C { + void foo() {} + void bar() {} +} +'''); + assertNodes(library.declaredNodes, [ + ExpectedNode( + aUri, + 'C', + DependencyNodeKind.CLASS, + classMembers: [ + ExpectedNode(aUri, '', DependencyNodeKind.CONSTRUCTOR), + ExpectedNode(aUri, 'foo', DependencyNodeKind.METHOD), + ExpectedNode(aUri, 'bar', DependencyNodeKind.METHOD), + ], + ), + ]); + } + + test_class_method_api_tokens_notSame_annotation() async { + await _assertApiTokenSignatureNotSame( + 'foo', + DependencyNodeKind.METHOD, + 'class X { void foo() {} }', + 'class X { @deprecated void foo() {} }', + memberOf: 'X', + ); + } + + test_class_method_api_tokens_notSame_parameter_add() async { + await _assertApiTokenSignatureNotSame( + 'foo', + DependencyNodeKind.METHOD, + 'class X { void foo() {} }', + 'class X { void foo(int a) {} }', + memberOf: 'X', + ); + } + + test_class_method_api_tokens_notSame_parameter_name_edit_named() async { + await _assertApiTokenSignatureNotSame( + 'foo', + DependencyNodeKind.METHOD, + 'class X { void foo({int a}) {} }', + 'class X { void foo({int b}) {} }', + memberOf: 'X', + ); + } + + test_class_method_api_tokens_notSame_parameter_type() async { + await _assertApiTokenSignatureNotSame( + 'foo', + DependencyNodeKind.METHOD, + 'class X { void foo(int a) {} }', + 'class X { void foo(double a) {} }', + memberOf: 'X', + ); + } + + test_class_method_api_tokens_notSame_returnType() async { + await _assertApiTokenSignatureNotSame( + 'foo', + DependencyNodeKind.METHOD, + 'class X { int foo() {} }', + 'class X { double foo() {} }', + memberOf: 'X', + ); + } + + test_class_method_api_tokens_notSame_typeParameter_add() async { + await _assertApiTokenSignatureNotSame( + 'foo', + DependencyNodeKind.METHOD, + 'class X { void foo() {} }', + 'class X { void foo<T>() {} }', + memberOf: 'X', + ); + } + + test_class_method_api_tokens_notSame_typeParameter_bound_add() async { + await _assertApiTokenSignatureNotSame( + 'foo', + DependencyNodeKind.METHOD, + 'class X { void foo<T>() {} }', + 'class X { void foo<T extends num>() {} }', + memberOf: 'X', + ); + } + + test_class_method_api_tokens_same_async_add() async { + await _assertApiTokenSignatureSame( + 'foo', + DependencyNodeKind.METHOD, + 'class X { foo() {} }', + 'class X { foo() async {} }', + memberOf: 'X', + ); + } + + test_class_method_api_tokens_same_body() async { + await _assertApiTokenSignatureSame( + 'foo', + DependencyNodeKind.METHOD, + 'class X { void foo() { print(1); } }', + 'class X { void foo() { print(2); } }', + memberOf: 'X', + ); + } + + test_class_method_api_tokens_same_parameter_name_edit_required() async { + await _assertApiTokenSignatureSame( + 'foo', + DependencyNodeKind.METHOD, + 'class X { void foo(int a) {} }', + 'class X { void foo(int b) {} }', + memberOf: 'X', + ); + } + + test_class_setter() async { + var library = await buildTestLibrary(a, r''' +class C { + set foo(_) {} + set bar(_) {} +} +'''); + assertNodes(library.declaredNodes, [ + ExpectedNode( + aUri, + 'C', + DependencyNodeKind.CLASS, + classMembers: [ + ExpectedNode(aUri, '', DependencyNodeKind.CONSTRUCTOR), + ExpectedNode(aUri, 'foo', DependencyNodeKind.SETTER), + ExpectedNode(aUri, 'bar', DependencyNodeKind.SETTER), + ], + ), + ]); + } + + test_class_setter_api_tokens_notSame_returnType() async { + await _assertApiTokenSignatureNotSame( + 'foo', + DependencyNodeKind.SETTER, + 'class X { set foo(int a) {} }', + 'class X { set foo(double a) {} }', + memberOf: 'X', + ); + } + + test_class_setter_api_tokens_same_parameter_name() async { + await _assertApiTokenSignatureSame( + 'foo', + DependencyNodeKind.SETTER, + 'class X { set foo(int a) {} }', + 'class X { set foo(int b) {} }', + memberOf: 'X', + ); + } + + test_class_typeParameter() async { + var library = await buildTestLibrary(a, r''' +class A<T> {} +class B<T, U> {} +'''); + assertNodes(library.declaredNodes, [ + ExpectedNode( + aUri, + 'A', + DependencyNodeKind.CLASS, + classMembers: [ + ExpectedNode(aUri, '', DependencyNodeKind.CONSTRUCTOR), + ], + classTypeParameters: [ + ExpectedNode(aUri, 'T', DependencyNodeKind.TYPE_PARAMETER), + ], + ), + ExpectedNode( + aUri, + 'B', + DependencyNodeKind.CLASS, + classMembers: [ + ExpectedNode(aUri, '', DependencyNodeKind.CONSTRUCTOR), + ], + classTypeParameters: [ + ExpectedNode(aUri, 'T', DependencyNodeKind.TYPE_PARAMETER), + ExpectedNode(aUri, 'U', DependencyNodeKind.TYPE_PARAMETER), + ], + ), + ]); + } + + test_class_typeParameter_api_tokens_notSame_annotation() async { + await _assertApiTokenSignatureNotSame( + 'T', + DependencyNodeKind.TYPE_PARAMETER, + 'class X<T> {}', + 'class X<@deprecate T> {}', + typeParameterOf: 'X', + ); + } + + test_class_typeParameter_api_tokens_notSame_bound_add() async { + await _assertApiTokenSignatureNotSame( + 'T', + DependencyNodeKind.TYPE_PARAMETER, + 'class X<T> {}', + 'class X<T extends num> {}', + typeParameterOf: 'X', + ); + } + + test_class_typeParameter_api_tokens_notSame_bound_edit() async { + await _assertApiTokenSignatureNotSame( + 'T', + DependencyNodeKind.TYPE_PARAMETER, + 'class X<T extends num> {}', + 'class X<T extends int> {}', + typeParameterOf: 'X', + ); + } + + test_library_export() async { + var library = await buildTestLibrary(a, r''' +export 'dart:math'; +export 'package:aaa/aaa.dart'; +export 'package:bbb/bbb.dart' show b1, b2 hide b3; +'''); + _assertExports(library, [ + Export(Uri.parse('dart:math'), []), + Export(Uri.parse('package:aaa/aaa.dart'), []), + Export(Uri.parse('package:bbb/bbb.dart'), [ + Combinator(true, ['b1', 'b2']), + Combinator(false, ['b3']), + ]), + ]); + } + + test_library_import() async { + var library = await buildTestLibrary(a, r''' +import 'dart:math'; +import 'package:aaa/aaa.dart'; +import 'package:bbb/bbb.dart' as b; +import 'package:ccc/ccc.dart' show c1, c2 hide c3; +'''); + _assertImports(library, [ + Import(Uri.parse('dart:math'), null, []), + Import(Uri.parse('package:aaa/aaa.dart'), null, []), + Import(Uri.parse('package:bbb/bbb.dart'), 'b', []), + Import(Uri.parse('package:ccc/ccc.dart'), null, [ + Combinator(true, ['c1', 'c2']), + Combinator(false, ['c3']), + ]), + Import(Uri.parse('dart:core'), null, []), + ]); + } + + test_library_import_core_explicit() async { + var library = await buildTestLibrary(a, r''' +import 'dart:core' hide List; +'''); + _assertImports(library, [ + Import(Uri.parse('dart:core'), null, [ + Combinator(false, ['List']), + ]), + ]); + } + + test_library_import_core_implicit() async { + var library = await buildTestLibrary(a, ''); + _assertImports(library, [ + Import(Uri.parse('dart:core'), null, []), + ]); + } + + test_unit_class() async { + var library = await buildTestLibrary(a, r''' +class Foo {} +class Bar {} +'''); + assertNodes(library.declaredNodes, [ + ExpectedNode(aUri, 'Foo', DependencyNodeKind.CLASS, classMembers: [ + ExpectedNode(aUri, '', DependencyNodeKind.CONSTRUCTOR), + ]), + ExpectedNode(aUri, 'Bar', DependencyNodeKind.CLASS, classMembers: [ + ExpectedNode(aUri, '', DependencyNodeKind.CONSTRUCTOR), + ]), + ]); + } + + test_unit_class_api_tokens_notSame_annotation() async { + await _assertApiTokenSignatureNotSame( + 'X', + DependencyNodeKind.CLASS, + 'class X {}', + '@deprecated class X {}', + ); + } + + test_unit_class_api_tokens_notSame_extends_add() async { + await _assertApiTokenSignatureNotSame( + 'X', + DependencyNodeKind.CLASS, + 'class X {}', + 'class X extends A {}', + ); + } + + test_unit_class_api_tokens_notSame_extends_edit() async { + await _assertApiTokenSignatureNotSame( + 'X', + DependencyNodeKind.CLASS, + 'class X extends A {}', + 'class X extends B {}', + ); + } + + test_unit_class_api_tokens_notSame_extends_replace() async { + await _assertApiTokenSignatureNotSame( + 'X', + DependencyNodeKind.CLASS, + 'class X extends A {}', + 'class X implements A {}', + ); + } + + test_unit_class_api_tokens_notSame_extends_typeArgument() async { + await _assertApiTokenSignatureNotSame( + 'X', + DependencyNodeKind.CLASS, + 'class X extends A {}', + 'class X extends A<int> {}', + ); + } + + test_unit_class_api_tokens_notSame_implements_add() async { + await _assertApiTokenSignatureNotSame( + 'X', + DependencyNodeKind.CLASS, + 'class X {}', + 'class X implements A {}', + ); + } + + test_unit_class_api_tokens_notSame_implements_edit() async { + await _assertApiTokenSignatureNotSame( + 'X', + DependencyNodeKind.CLASS, + 'class X implements A {}', + 'class X implements B {}', + ); + } + + test_unit_class_api_tokens_notSame_implements_remove() async { + await _assertApiTokenSignatureNotSame( + 'X', + DependencyNodeKind.CLASS, + 'class X implements A {}', + 'class X {}', + ); + } + + test_unit_class_api_tokens_notSame_implements_remove2() async { + await _assertApiTokenSignatureNotSame( + 'X', + DependencyNodeKind.CLASS, + 'class X implements A, B {}', + 'class X implements B {}', + ); + } + + test_unit_class_api_tokens_notSame_implements_typeArgument() async { + await _assertApiTokenSignatureNotSame( + 'X', + DependencyNodeKind.CLASS, + 'class X implements A {}', + 'class X implements A<int> {}', + ); + } + + test_unit_class_api_tokens_notSame_typeParameter_add() async { + await _assertApiTokenSignatureNotSame( + 'X', + DependencyNodeKind.CLASS, + 'class X {}', + 'class X<T> {}', + ); + } + + test_unit_class_api_tokens_notSame_typeParameter_add2() async { + await _assertApiTokenSignatureNotSame( + 'X', + DependencyNodeKind.CLASS, + 'class X<T> {}', + 'class X<T, U> {}', + ); + } + + test_unit_class_api_tokens_notSame_typeParameter_bound_add() async { + await _assertApiTokenSignatureNotSame( + 'X', + DependencyNodeKind.CLASS, + 'class X<T> {}', + 'class X<T extends num> {}', + ); + } + + test_unit_class_api_tokens_notSame_with_add() async { + await _assertApiTokenSignatureNotSame( + 'X', + DependencyNodeKind.CLASS, + 'class X extends A {}', + 'class X extends A with B {}', + ); + } + + test_unit_class_api_tokens_notSame_with_edit() async { + await _assertApiTokenSignatureNotSame( + 'X', + DependencyNodeKind.CLASS, + 'class X extends A with B {}', + 'class X extends A with C {}', + ); + } + + test_unit_class_api_tokens_notSame_with_typeArgument() async { + await _assertApiTokenSignatureNotSame( + 'X', + DependencyNodeKind.CLASS, + 'class X extends A with B {}', + 'class X extends A with B<int> {}', + ); + } + + test_unit_class_api_tokens_same_body() async { + await _assertApiTokenSignatureSame( + 'X', + DependencyNodeKind.CLASS, + 'class X { }', + 'class X { void foo() {} }', + ); + } + + test_unit_classTypeAlias() async { + var library = await buildTestLibrary(a, r''' +class X = Object with M; +'''); + assertNodes(library.declaredNodes, [ + ExpectedNode(aUri, 'X', DependencyNodeKind.CLASS_TYPE_ALIAS), + ]); + } + + test_unit_classTypeAlias_api_tokens_notSame_implements_add() async { + await _assertApiTokenSignatureNotSame( + 'X', + DependencyNodeKind.CLASS_TYPE_ALIAS, + 'class X = A with M;', + 'class X = A with M implements I;', + ); + } + + test_unit_classTypeAlias_api_tokens_notSame_implements_edit() async { + await _assertApiTokenSignatureNotSame( + 'X', + DependencyNodeKind.CLASS_TYPE_ALIAS, + 'class X = A with M implements I;', + 'class X = A with M implements J;', + ); + } + + test_unit_classTypeAlias_api_tokens_notSame_implements_remove() async { + await _assertApiTokenSignatureNotSame( + 'X', + DependencyNodeKind.CLASS_TYPE_ALIAS, + 'class X = A with M implements I;', + 'class X = A with M;', + ); + } + + test_unit_classTypeAlias_api_tokens_notSame_implements_typeArgument() async { + await _assertApiTokenSignatureNotSame( + 'X', + DependencyNodeKind.CLASS_TYPE_ALIAS, + 'class X = A with M implements I;', + 'class X = A with M implements I<int>;', + ); + } + + test_unit_classTypeAlias_api_tokens_notSame_super() async { + await _assertApiTokenSignatureNotSame( + 'X', + DependencyNodeKind.CLASS_TYPE_ALIAS, + 'class X = A with M;', + 'class X = B with M;', + ); + } + + test_unit_classTypeAlias_api_tokens_notSame_super_typeArgument() async { + await _assertApiTokenSignatureNotSame( + 'X', + DependencyNodeKind.CLASS_TYPE_ALIAS, + 'class X = A with M;', + 'class X = A<int> with M;', + ); + } + + test_unit_classTypeAlias_api_tokens_notSame_typeParameter_add() async { + await _assertApiTokenSignatureNotSame( + 'X', + DependencyNodeKind.CLASS_TYPE_ALIAS, + 'class X = A with M;', + 'class X<T> = A with M;', + ); + } + + test_unit_classTypeAlias_api_tokens_notSame_typeParameter_add2() async { + await _assertApiTokenSignatureNotSame( + 'X', + DependencyNodeKind.CLASS_TYPE_ALIAS, + 'class X<T> = A with M;', + 'class X<T, U> = A with M;', + ); + } + + test_unit_classTypeAlias_api_tokens_notSame_typeParameter_bound_add() async { + await _assertApiTokenSignatureNotSame( + 'X', + DependencyNodeKind.CLASS_TYPE_ALIAS, + 'class X<T> = A with M;', + 'class X<T extends num> = A with M;', + ); + } + + test_unit_classTypeAlias_api_tokens_notSame_with_add() async { + await _assertApiTokenSignatureNotSame( + 'X', + DependencyNodeKind.CLASS_TYPE_ALIAS, + 'class X = A with M;', + 'class X = A with M, N;', + ); + } + + test_unit_classTypeAlias_api_tokens_notSame_with_edit() async { + await _assertApiTokenSignatureNotSame( + 'X', + DependencyNodeKind.CLASS_TYPE_ALIAS, + 'class X = A with M;', + 'class X = A with N;', + ); + } + + test_unit_classTypeAlias_api_tokens_notSame_with_typeArgument() async { + await _assertApiTokenSignatureNotSame( + 'X', + DependencyNodeKind.CLASS_TYPE_ALIAS, + 'class X = A with M;', + 'class X = A with M<int>;', + ); + } + + test_unit_enumDeclaration() async { + var library = await buildTestLibrary(a, r''' +enum Foo {a, b, c} +enum Bar {d, e, f} +'''); + assertNodes(library.declaredNodes, [ + ExpectedNode( + aUri, + 'Foo', + DependencyNodeKind.ENUM, + classMembers: [ + ExpectedNode(aUri, 'a', DependencyNodeKind.GETTER), + ExpectedNode(aUri, 'b', DependencyNodeKind.GETTER), + ExpectedNode(aUri, 'c', DependencyNodeKind.GETTER), + ExpectedNode(aUri, 'index', DependencyNodeKind.GETTER), + ExpectedNode(aUri, 'values', DependencyNodeKind.GETTER), + ], + ), + ExpectedNode( + aUri, + 'Bar', + DependencyNodeKind.ENUM, + classMembers: [ + ExpectedNode(aUri, 'd', DependencyNodeKind.GETTER), + ExpectedNode(aUri, 'e', DependencyNodeKind.GETTER), + ExpectedNode(aUri, 'f', DependencyNodeKind.GETTER), + ExpectedNode(aUri, 'index', DependencyNodeKind.GETTER), + ExpectedNode(aUri, 'values', DependencyNodeKind.GETTER), + ], + ), + ]); + } + + test_unit_function() async { + var library = await buildTestLibrary(a, r''' +void foo() {} +void bar() {} +'''); + assertNodes(library.declaredNodes, [ + ExpectedNode(aUri, 'foo', DependencyNodeKind.FUNCTION), + ExpectedNode(aUri, 'bar', DependencyNodeKind.FUNCTION), + ]); + } + + test_unit_function_api_tokens_notSame_annotation() async { + await _assertApiTokenSignatureNotSame( + 'foo', + DependencyNodeKind.FUNCTION, + 'void foo() {}', + '@deprecated void foo() {}', + ); + } + + test_unit_function_api_tokens_notSame_parameter_add() async { + await _assertApiTokenSignatureNotSame( + 'foo', + DependencyNodeKind.FUNCTION, + 'void foo() {}', + 'void foo(int a) {}', + ); + } + + test_unit_function_api_tokens_notSame_parameter_name_edit_named() async { + await _assertApiTokenSignatureNotSame( + 'foo', + DependencyNodeKind.FUNCTION, + 'void foo({int a}) {}', + 'void foo({int b}) {}', + ); + } + + test_unit_function_api_tokens_notSame_parameter_type() async { + await _assertApiTokenSignatureNotSame( + 'foo', + DependencyNodeKind.FUNCTION, + 'void foo(int a) {}', + 'void foo(double a) {}', + ); + } + + test_unit_function_api_tokens_notSame_returnType() async { + await _assertApiTokenSignatureNotSame( + 'foo', + DependencyNodeKind.FUNCTION, + 'int foo() {}', + 'num foo() {}', + ); + } + + test_unit_function_api_tokens_notSame_typeParameter_add() async { + await _assertApiTokenSignatureNotSame( + 'foo', + DependencyNodeKind.FUNCTION, + 'void foo() {}', + 'void foo<T>() {}', + ); + } + + test_unit_function_api_tokens_notSame_typeParameter_bound_add() async { + await _assertApiTokenSignatureNotSame( + 'foo', + DependencyNodeKind.FUNCTION, + 'void foo<T>() {}', + 'void foo<T extends num>() {}', + ); + } + + test_unit_function_api_tokens_same_async_add() async { + await _assertApiTokenSignatureSame( + 'foo', + DependencyNodeKind.FUNCTION, + 'foo() {}', + 'foo() async {}', + ); + } + + test_unit_function_api_tokens_same_body() async { + await _assertApiTokenSignatureSame( + 'foo', + DependencyNodeKind.FUNCTION, + 'void foo() { print(1); }', + 'void foo() { print(2); }', + ); + } + + test_unit_function_api_tokens_same_parameter_name_edit_required() async { + await _assertApiTokenSignatureSame( + 'foo', + DependencyNodeKind.FUNCTION, + 'void foo(int a) {}', + 'void foo(int b) {}', + ); + } + + test_unit_function_api_tokens_same_syncStar_add() async { + await _assertApiTokenSignatureSame( + 'foo', + DependencyNodeKind.FUNCTION, + 'foo() {}', + 'foo() sync* {}', + ); + } + + test_unit_functionTypeAlias() async { + var library = await buildTestLibrary(a, r''' +typedef void Foo(); +typedef void Bar(); +'''); + assertNodes(library.declaredNodes, [ + ExpectedNode(aUri, 'Foo', DependencyNodeKind.FUNCTION_TYPE_ALIAS), + ExpectedNode(aUri, 'Bar', DependencyNodeKind.FUNCTION_TYPE_ALIAS), + ]); + } + + test_unit_functionTypeAlias_api_tokens_notSame_annotation() async { + await _assertApiTokenSignatureNotSame( + 'Foo', + DependencyNodeKind.FUNCTION_TYPE_ALIAS, + 'typedef void Foo();', + '@deprecated typedef void Foo();', + ); + } + + test_unit_functionTypeAlias_api_tokens_notSame_parameter_add() async { + await _assertApiTokenSignatureNotSame( + 'Foo', + DependencyNodeKind.FUNCTION_TYPE_ALIAS, + 'typedef void Foo();', + 'typedef void Foo(int a);', + ); + } + + test_unit_functionTypeAlias_api_tokens_notSame_parameter_name_edit_named() async { + await _assertApiTokenSignatureNotSame( + 'Foo', + DependencyNodeKind.FUNCTION_TYPE_ALIAS, + 'typedef void Foo({int a});', + 'typedef void Foo({int b});', + ); + } + + test_unit_functionTypeAlias_api_tokens_notSame_parameter_type() async { + await _assertApiTokenSignatureNotSame( + 'Foo', + DependencyNodeKind.FUNCTION_TYPE_ALIAS, + 'typedef void Foo(int a);', + 'typedef void Foo(double a);', + ); + } + + test_unit_functionTypeAlias_api_tokens_notSame_returnType() async { + await _assertApiTokenSignatureNotSame( + 'Foo', + DependencyNodeKind.FUNCTION_TYPE_ALIAS, + 'typedef int Foo();', + 'typedef num Foo();', + ); + } + + test_unit_functionTypeAlias_api_tokens_notSame_typeParameter_add() async { + await _assertApiTokenSignatureNotSame( + 'Foo', + DependencyNodeKind.FUNCTION_TYPE_ALIAS, + 'typedef void Foo();', + 'typedef void Foo<T>();', + ); + } + + test_unit_functionTypeAlias_api_tokens_notSame_typeParameter_bound_add() async { + await _assertApiTokenSignatureNotSame( + 'Foo', + DependencyNodeKind.FUNCTION_TYPE_ALIAS, + 'typedef void Foo<T>();', + 'typedef void Foo<T extends num>();', + ); + } + + test_unit_functionTypeAlias_api_tokens_same_comment() async { + await _assertApiTokenSignatureSame( + 'Foo', + DependencyNodeKind.FUNCTION_TYPE_ALIAS, + 'typedef int Foo();', + '/* text */ typedef int Foo();', + ); + } + + test_unit_functionTypeAlias_api_tokens_same_parameter_name_edit_required() async { + await _assertApiTokenSignatureSame( + 'Foo', + DependencyNodeKind.FUNCTION_TYPE_ALIAS, + 'typedef void Foo(int a);', + 'typedef void Foo(int b);', + ); + } + + test_unit_genericTypeAlias() async { + var library = await buildTestLibrary(a, r''' +typedef Foo = void Function(); +typedef Bar = void Function(); +'''); + assertNodes(library.declaredNodes, [ + ExpectedNode(aUri, 'Foo', DependencyNodeKind.GENERIC_TYPE_ALIAS), + ExpectedNode(aUri, 'Bar', DependencyNodeKind.GENERIC_TYPE_ALIAS), + ]); + } + + test_unit_genericTypeAlias_api_tokens_notSame_annotation() async { + await _assertApiTokenSignatureNotSame( + 'Foo', + DependencyNodeKind.GENERIC_TYPE_ALIAS, + 'typedef Foo = void Function();', + '@deprecated typedef Foo = void Function();', + ); + } + + test_unit_genericTypeAlias_api_tokens_notSame_parameter_add() async { + await _assertApiTokenSignatureNotSame( + 'Foo', + DependencyNodeKind.GENERIC_TYPE_ALIAS, + 'typedef Foo = void Function();', + 'typedef Foo = void Function(int);', + ); + } + + test_unit_genericTypeAlias_api_tokens_notSame_parameter_kind() async { + await _assertApiTokenSignatureNotSame( + 'Foo', + DependencyNodeKind.GENERIC_TYPE_ALIAS, + 'typedef Foo = void Function(int a);', + 'typedef Foo = void Function([int a]);', + ); + } + + test_unit_genericTypeAlias_api_tokens_notSame_parameter_name_add_positional() async { + await _assertApiTokenSignatureNotSame( + 'Foo', + DependencyNodeKind.GENERIC_TYPE_ALIAS, + 'typedef Foo = void Function([int]);', + 'typedef Foo = void Function([int a]);', + ); + } + + test_unit_genericTypeAlias_api_tokens_notSame_parameter_name_edit_named() async { + await _assertApiTokenSignatureNotSame( + 'Foo', + DependencyNodeKind.GENERIC_TYPE_ALIAS, + 'typedef Foo = void Function({int a});', + 'typedef Foo = void Function({int b});', + ); + } + + test_unit_genericTypeAlias_api_tokens_notSame_parameter_name_edit_positional() async { + await _assertApiTokenSignatureNotSame( + 'Foo', + DependencyNodeKind.GENERIC_TYPE_ALIAS, + 'typedef Foo = void Function([int]);', + 'typedef Foo = void Function([int a]);', + ); + } + + test_unit_genericTypeAlias_api_tokens_notSame_returnType() async { + await _assertApiTokenSignatureNotSame( + 'Foo', + DependencyNodeKind.GENERIC_TYPE_ALIAS, + 'typedef Foo = int Function();', + 'typedef Foo = double Function();', + ); + } + + test_unit_genericTypeAlias_api_tokens_notSame_typeParameter2_add() async { + await _assertApiTokenSignatureNotSame( + 'Foo', + DependencyNodeKind.GENERIC_TYPE_ALIAS, + 'typedef Foo = void Function();', + 'typedef Foo = void Function<T>();', + ); + } + + test_unit_genericTypeAlias_api_tokens_notSame_typeParameter2_bound_add() async { + await _assertApiTokenSignatureNotSame( + 'Foo', + DependencyNodeKind.GENERIC_TYPE_ALIAS, + 'typedef Foo = void Function<T>();', + 'typedef Foo = void Function<T extends num>();', + ); + } + + test_unit_genericTypeAlias_api_tokens_notSame_typeParameter_add() async { + await _assertApiTokenSignatureNotSame( + 'Foo', + DependencyNodeKind.GENERIC_TYPE_ALIAS, + 'typedef Foo = void Function();', + 'typedef Foo<T> = void Function();', + ); + } + + test_unit_genericTypeAlias_api_tokens_notSame_typeParameter_bound_add() async { + await _assertApiTokenSignatureNotSame( + 'Foo', + DependencyNodeKind.GENERIC_TYPE_ALIAS, + 'typedef Foo<T> = void Function();', + 'typedef Foo<T extends num> = void Function();', + ); + } + + test_unit_genericTypeAlias_api_tokens_same_parameter_name_add_required() async { + await _assertApiTokenSignatureSame( + 'Foo', + DependencyNodeKind.GENERIC_TYPE_ALIAS, + 'typedef Foo = void Function(int);', + 'typedef Foo = void Function(int a);', + ); + } + + test_unit_genericTypeAlias_api_tokens_same_parameter_name_edit_required() async { + await _assertApiTokenSignatureSame( + 'Foo', + DependencyNodeKind.GENERIC_TYPE_ALIAS, + 'typedef Foo = void Function(int a);', + 'typedef Foo = void Function(int b);', + ); + } + + test_unit_getter() async { + var library = await buildTestLibrary(a, r''' +int get foo => 0; +int get bar => 0; +'''); + assertNodes(library.declaredNodes, [ + ExpectedNode(aUri, 'foo', DependencyNodeKind.GETTER), + ExpectedNode(aUri, 'bar', DependencyNodeKind.GETTER), + ]); + } + + test_unit_getter_api_tokens_notSame_annotation() async { + await _assertApiTokenSignatureNotSame( + 'foo', + DependencyNodeKind.GETTER, + 'int get foo => 0;', + '@deprecated int get foo => 0;', + ); + } + + test_unit_getter_api_tokens_notSame_returnType() async { + await _assertApiTokenSignatureNotSame( + 'foo', + DependencyNodeKind.GETTER, + 'int get foo => 0;', + 'num get foo => 0;', + ); + } + + test_unit_getter_api_tokens_same_body() async { + await _assertApiTokenSignatureSame( + 'foo', + DependencyNodeKind.GETTER, + 'int get foo => 0;', + 'int get foo => 1;', + ); + } + + test_unit_mixin() async { + var library = await buildTestLibrary(a, r''' +mixin Foo {} +mixin Bar {} +'''); + assertNodes(library.declaredNodes, [ + ExpectedNode(aUri, 'Foo', DependencyNodeKind.MIXIN, + classMembers: const []), + ExpectedNode(aUri, 'Bar', DependencyNodeKind.MIXIN, + classMembers: const []), + ]); + } + + test_unit_mixin_api_tokens_notSame_annotation() async { + await _assertApiTokenSignatureNotSame( + 'X', + DependencyNodeKind.MIXIN, + 'mixin X {}', + '@deprecated mixin X {}', + ); + } + + test_unit_mixin_api_tokens_notSame_implements_add() async { + await _assertApiTokenSignatureNotSame( + 'X', + DependencyNodeKind.MIXIN, + 'mixin X {}', + 'mixin X implements A {}', + ); + } + + test_unit_mixin_api_tokens_notSame_implements_edit() async { + await _assertApiTokenSignatureNotSame( + 'X', + DependencyNodeKind.MIXIN, + 'mixin X implements A {}', + 'mixin X implements B {}', + ); + } + + test_unit_mixin_api_tokens_notSame_implements_remove() async { + await _assertApiTokenSignatureNotSame( + 'X', + DependencyNodeKind.MIXIN, + 'mixin X implements A {}', + 'mixin X {}', + ); + } + + test_unit_mixin_api_tokens_notSame_implements_remove2() async { + await _assertApiTokenSignatureNotSame( + 'X', + DependencyNodeKind.MIXIN, + 'mixin X implements A, B {}', + 'mixin X implements B {}', + ); + } + + test_unit_mixin_api_tokens_notSame_implements_typeArgument() async { + await _assertApiTokenSignatureNotSame( + 'X', + DependencyNodeKind.MIXIN, + 'mixin X implements A {}', + 'mixin X implements A<int> {}', + ); + } + + test_unit_mixin_api_tokens_notSame_on_add() async { + await _assertApiTokenSignatureNotSame( + 'X', + DependencyNodeKind.MIXIN, + 'mixin X {}', + 'mixin X on A {}', + ); + } + + test_unit_mixin_api_tokens_notSame_on_add2() async { + await _assertApiTokenSignatureNotSame( + 'X', + DependencyNodeKind.MIXIN, + 'mixin X on A {}', + 'mixin X on A, B {}', + ); + } + + test_unit_mixin_api_tokens_notSame_on_edit() async { + await _assertApiTokenSignatureNotSame( + 'X', + DependencyNodeKind.MIXIN, + 'mixin X on A {}', + 'mixin X on B {}', + ); + } + + test_unit_mixin_api_tokens_notSame_on_replace() async { + await _assertApiTokenSignatureNotSame( + 'X', + DependencyNodeKind.MIXIN, + 'mixin X on A {}', + 'mixin X implements A {}', + ); + } + + test_unit_mixin_api_tokens_notSame_on_typeArgument() async { + await _assertApiTokenSignatureNotSame( + 'X', + DependencyNodeKind.MIXIN, + 'mixin X on A {}', + 'mixin X on A<int> {}', + ); + } + + test_unit_mixin_api_tokens_notSame_typeParameter_add() async { + await _assertApiTokenSignatureNotSame( + 'X', + DependencyNodeKind.MIXIN, + 'mixin X {}', + 'mixin X<T> {}', + ); + } + + test_unit_mixin_api_tokens_notSame_typeParameter_add2() async { + await _assertApiTokenSignatureNotSame( + 'X', + DependencyNodeKind.MIXIN, + 'mixin X<T> {}', + 'mixin X<T, U> {}', + ); + } + + test_unit_mixin_api_tokens_notSame_typeParameter_bound_add() async { + await _assertApiTokenSignatureNotSame( + 'X', + DependencyNodeKind.MIXIN, + 'mixin X<T> {}', + 'mixin X<T extends num> {}', + ); + } + + test_unit_mixin_api_tokens_same_body() async { + await _assertApiTokenSignatureSame( + 'X', + DependencyNodeKind.MIXIN, + 'mixin X { }', + 'mixin X { void foo() {} }', + ); + } + + test_unit_setter() async { + var library = await buildTestLibrary(a, r''' +void set foo(_) {} +void set bar(_) {} +'''); + assertNodes(library.declaredNodes, [ + ExpectedNode(aUri, 'foo=', DependencyNodeKind.SETTER), + ExpectedNode(aUri, 'bar=', DependencyNodeKind.SETTER), + ]); + } + + test_unit_setter_api_tokens_notSame_annotation() async { + await _assertApiTokenSignatureNotSame( + 'foo=', + DependencyNodeKind.SETTER, + 'set foo(int a) {}', + '@deprecated set foo(int a) {}', + ); + } + + test_unit_setter_api_tokens_notSame_parameter_type() async { + await _assertApiTokenSignatureNotSame( + 'foo=', + DependencyNodeKind.SETTER, + 'set foo(int a) {}', + 'set foo(num a) {}', + ); + } + + test_unit_setter_api_tokens_same_body() async { + await _assertApiTokenSignatureSame( + 'foo=', + DependencyNodeKind.SETTER, + 'set foo(int a) { print(0); }', + 'set foo(int a) { print(1); }', + ); + } + + test_unit_variable() async { + var library = await buildTestLibrary(a, r''' +int a = 1; +int b = 2, c = 3; +'''); + assertNodes(library.declaredNodes, [ + ExpectedNode(aUri, 'a', DependencyNodeKind.GETTER), + ExpectedNode(aUri, 'b', DependencyNodeKind.GETTER), + ExpectedNode(aUri, 'c', DependencyNodeKind.GETTER), + ExpectedNode(aUri, 'a=', DependencyNodeKind.SETTER), + ExpectedNode(aUri, 'b=', DependencyNodeKind.SETTER), + ExpectedNode(aUri, 'c=', DependencyNodeKind.SETTER), + ]); + } + + test_unit_variable_api_tokens_notSame_annotation() async { + await _assertApiTokenSignatureNotSame( + 'foo', + DependencyNodeKind.GETTER, + 'int foo = 0;', + '@deprecated int foo = 0;', + ); + } + + test_unit_variable_api_tokens_notSame_const() async { + await _assertApiTokenSignatureNotSame( + 'foo', + DependencyNodeKind.GETTER, + 'int foo = 0;', + 'const int foo = 0;', + ); + } + + test_unit_variable_api_tokens_same_final() async { + await _assertApiTokenSignatureSame( + 'foo', + DependencyNodeKind.GETTER, + 'int foo = 0;', + 'final int foo = 0;', + ); + } + + test_unit_variable_api_tokens_typed_notSame_type() async { + await _assertApiTokenSignatureNotSame( + 'foo', + DependencyNodeKind.GETTER, + 'int foo = 0;', + 'num foo = 1;', + ); + } + + test_unit_variable_api_tokens_typed_same_initializer() async { + await _assertApiTokenSignatureSame( + 'foo', + DependencyNodeKind.GETTER, + 'int foo = 0;', + 'int foo = 1;', + ); + } + + test_unit_variable_api_tokens_untyped_notSame_initializer() async { + await _assertApiTokenSignatureNotSame( + 'foo', + DependencyNodeKind.GETTER, + 'var foo = 0;', + 'var foo = 1.0;', + ); + } + + test_unit_variable_const() async { + var library = await buildTestLibrary(a, r''' +const foo = 1; +const bar = 2; +'''); + assertNodes(library.declaredNodes, [ + ExpectedNode(aUri, 'foo', DependencyNodeKind.GETTER), + ExpectedNode(aUri, 'bar', DependencyNodeKind.GETTER), + ]); + } + + test_unit_variable_const_api_tokens_typed_notSame_initializer() async { + await _assertApiTokenSignatureNotSame( + 'foo', + DependencyNodeKind.GETTER, + 'const int foo = 0;', + 'const int foo = 1;', + ); + } + + test_unit_variable_final() async { + var library = await buildTestLibrary(a, r''' +final foo = 1; +final bar = 2; +'''); + assertNodes(library.declaredNodes, [ + ExpectedNode(aUri, 'foo', DependencyNodeKind.GETTER), + ExpectedNode(aUri, 'bar', DependencyNodeKind.GETTER), + ]); + } + + test_unit_variable_final_api_tokens_typed_same_initializer() async { + await _assertApiTokenSignatureSame( + 'foo', + DependencyNodeKind.GETTER, + 'final int foo = 0;', + 'final int foo = 1;', + ); + } + + test_unit_variable_final_api_tokens_untyped_notSame_initializer() async { + await _assertApiTokenSignatureNotSame( + 'foo', + DependencyNodeKind.GETTER, + 'final foo = 0;', + 'final foo = 1.0;', + ); + } + + test_unit_variable_final_withoutValue() async { + var library = await buildTestLibrary(a, r''' +final foo; +final bar; +'''); + assertNodes(library.declaredNodes, [ + ExpectedNode(aUri, 'foo', DependencyNodeKind.GETTER), + ExpectedNode(aUri, 'bar', DependencyNodeKind.GETTER), + ]); + } + + Future<void> _assertApiTokenSignatureNotSame( + String name, DependencyNodeKind kind, String codeBefore, String codeAfter, + {String memberOf, String typeParameterOf}) async { + DependencyNode getNodeA(Library library) { + return getNode( + library, + uri: aUri, + name: name, + kind: kind, + memberOf: memberOf, + typeParameterOf: typeParameterOf, + ); + } + + var libraryBefore = await buildTestLibrary(a, codeBefore); + var nodeBefore = getNodeA(libraryBefore); + + var libraryAfter = await buildTestLibrary(a, codeAfter); + var nodeAfter = getNodeA(libraryAfter); + + expect( + nodeAfter.api.tokenSignatureHex, + isNot(nodeBefore.api.tokenSignatureHex), + ); + } + + Future<void> _assertApiTokenSignatureSame( + String name, DependencyNodeKind kind, String codeBefore, String codeAfter, + {String memberOf, String typeParameterOf}) async { + DependencyNode getNodeA(Library library) { + return getNode( + library, + uri: aUri, + name: name, + kind: kind, + memberOf: memberOf, + typeParameterOf: typeParameterOf, + ); + } + + var libraryBefore = await buildTestLibrary(a, codeBefore); + var nodeBefore = getNodeA(libraryBefore); + + var libraryAfter = await buildTestLibrary(a, codeAfter); + var nodeAfter = getNodeA(libraryAfter); + + expect( + nodeAfter.api.tokenSignatureHex, + nodeBefore.api.tokenSignatureHex, + ); + } + + static void _assertExports(Library library, List<Export> expectedExports) { + var actualExports = library.exports; + expect(actualExports, hasLength(expectedExports.length)); + for (var i = 0; i < actualExports.length; ++i) { + var actual = actualExports[i]; + var expected = expectedExports[i]; + if (actual.uri != expected.uri || + !_equalCombinators(actual.combinators, expected.combinators)) { + fail('Expected: $expected\nActual: $actual'); + } + } + } + + static void _assertImports(Library library, List<Import> expectedImports) { + var actualImports = library.imports; + expect(actualImports, hasLength(expectedImports.length)); + for (var i = 0; i < actualImports.length; ++i) { + var actual = actualImports[i]; + var expected = expectedImports[i]; + if (actual.uri != expected.uri || + actual.prefix != expected.prefix || + !_equalCombinators(actual.combinators, expected.combinators)) { + fail('Expected: $expected\nActual: $actual'); + } + } + } + + static bool _equalCombinators(List<Combinator> actualCombinators, + List<Combinator> expectedCombinators) { + if (actualCombinators.length != expectedCombinators.length) { + return false; + } + + for (var i = 0; i < actualCombinators.length; i++) { + var actualCombinator = actualCombinators[i]; + var expectedCombinator = expectedCombinators[i]; + if (actualCombinator.isShow != expectedCombinator.isShow) { + return false; + } + + var actualNames = actualCombinator.names; + var expectedNames = expectedCombinator.names; + if (actualNames.length != expectedNames.length) { + return false; + } + for (var j = 0; j < actualNames.length; j++) { + if (actualNames[j] != expectedNames[j]) { + return false; + } + } + } + + return true; + } +}
diff --git a/pkg/analyzer/test/src/dart/analysis/driver_resolution_test.dart b/pkg/analyzer/test/src/dart/analysis/driver_resolution_test.dart index 7841c96..2ca7531 100644 --- a/pkg/analyzer/test/src/dart/analysis/driver_resolution_test.dart +++ b/pkg/analyzer/test/src/dart/analysis/driver_resolution_test.dart
@@ -1,17 +1,19 @@ -// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. import 'dart:async'; +import 'package:analyzer/dart/analysis/results.dart'; import 'package:analyzer/dart/ast/ast.dart'; import 'package:analyzer/dart/ast/token.dart'; import 'package:analyzer/dart/element/element.dart'; import 'package:analyzer/dart/element/type.dart'; -import 'package:analyzer/src/dart/analysis/driver.dart'; +import 'package:analyzer/src/dart/analysis/experiments.dart'; import 'package:analyzer/src/dart/element/element.dart'; import 'package:analyzer/src/dart/element/member.dart'; import 'package:analyzer/src/dart/element/type.dart'; +import 'package:analyzer/src/generated/engine.dart'; import 'package:analyzer/src/generated/resolver.dart'; import 'package:analyzer/src/generated/utilities_dart.dart'; import 'package:test/test.dart'; @@ -25,6 +27,7 @@ main() { defineReflectiveSuite(() { defineReflectiveTests(AnalysisDriverResolutionTest); + defineReflectiveTests(DriverResolutionWithExperimentsTest); }); } @@ -41,7 +44,7 @@ */ @reflectiveTest class AnalysisDriverResolutionTest extends BaseAnalysisDriverTest { - AnalysisResult result; + ResolvedUnitResult result; FindNode findNode; FindElement findElement; @@ -376,7 +379,7 @@ } test_annotation_onDirective_part() async { - provider.newFile(_p('/test/lib/a.dart'), r''' + newFile('/test/lib/a.dart', content: r''' part of 'test.dart'; '''); addTestFile(r''' @@ -399,8 +402,7 @@ } test_annotation_onDirective_partOf() async { - var a = _p('/test/lib/a.dart'); - provider.newFile(a, r''' + newFile('/test/lib/a.dart', content: r''' part 'test.dart'; '''); addTestFile(r''' @@ -409,7 +411,6 @@ const a = 1; '''); - driver.addFile(a); await resolveTestFile(); var directive = findNode.partOf('a.dart'); @@ -522,8 +523,7 @@ } test_annotation_prefixed_classField() async { - var a = _p('/test/lib/a.dart'); - provider.newFile(a, r''' + newFile('/test/lib/a.dart', content: r''' class A { static const a = 1; } @@ -563,8 +563,7 @@ } test_annotation_prefixed_constructor() async { - var a = _p('/test/lib/a.dart'); - provider.newFile(a, r''' + newFile('/test/lib/a.dart', content: r''' class A { const A(int a, {int b}); } @@ -605,8 +604,7 @@ } test_annotation_prefixed_constructor_named() async { - var a = _p('/test/lib/a.dart'); - provider.newFile(a, r''' + newFile('/test/lib/a.dart', content: r''' class A { const A.named(int a, {int b}); } @@ -649,8 +647,7 @@ } test_annotation_prefixed_topLevelVariable() async { - var a = _p('/test/lib/a.dart'); - provider.newFile(a, r''' + newFile('/test/lib/a.dart', content: r''' const topAnnotation = 1; '''); addTestFile(r''' @@ -1538,8 +1535,7 @@ @failingTest test_deferredImport_loadLibrary_invocation() async { - var a = _p('/test/lib/a.dart'); - provider.newFile(a, ''); + newFile('/test/lib/a.dart'); addTestFile(r''' import 'a.dart' deferred as a; main() { @@ -1564,8 +1560,7 @@ @failingTest test_deferredImport_loadLibrary_invocation_argument() async { - var a = _p('/test/lib/a.dart'); - provider.newFile(a, ''); + newFile('/test/lib/a.dart'); addTestFile(r''' import 'a.dart' deferred as a; var b = 1; @@ -1599,8 +1594,7 @@ } test_deferredImport_loadLibrary_tearOff() async { - var a = _p('/test/lib/a.dart'); - provider.newFile(a, ''); + newFile('/test/lib/a.dart'); addTestFile(r''' import 'a.dart' deferred as a; main() { @@ -1623,8 +1617,7 @@ } test_deferredImport_variable() async { - var a = _p('/test/lib/a.dart'); - provider.newFile(a, 'var v = 0;'); + newFile('/test/lib/a.dart', content: 'var v = 0;'); addTestFile(r''' import 'a.dart' deferred as a; main() async { @@ -1664,8 +1657,7 @@ } test_directive_export() async { - var a = _p('/test/lib/a.dart'); - provider.newFile(a, r''' + newFile('/test/lib/a.dart', content: r''' class MyClass {} int myVar; int get myGetter => 0; @@ -1713,8 +1705,7 @@ } test_directive_import_hide() async { - var a = _p('/test/lib/a.dart'); - provider.newFile(a, r''' + newFile('/test/lib/a.dart', content: r''' class MyClass {} int myVar; int get myGetter => 0; @@ -1762,8 +1753,7 @@ } test_directive_import_show() async { - var a = _p('/test/lib/a.dart'); - provider.newFile(a, r''' + newFile('/test/lib/a.dart', content: r''' class MyClass {} int myVar; int get myGetter => 0; @@ -2325,8 +2315,7 @@ } test_instanceCreation_prefixed() async { - var a = _p('/test/lib/a.dart'); - provider.newFile(a, r''' + newFile('/test/lib/a.dart', content: r''' class C<T> { C(T p); C.named(T p); @@ -3567,7 +3556,6 @@ assertType(aRef, 'int'); } - @failingTest test_invalid_methodInvocation_simpleIdentifier() async { addTestFile(r''' int foo = 0; @@ -3720,8 +3708,7 @@ @failingTest test_invalid_nonTypeAsType_topLevelFunction_prefixed() async { - var a = _p('/test/lib/a.dart'); - provider.newFile(a, r''' + newFile('/test/lib/a.dart', content: r''' int T() => 0; '''); addTestFile(r''' @@ -3789,8 +3776,7 @@ @failingTest test_invalid_nonTypeAsType_topLevelVariable_prefixed() async { - var a = _p('/test/lib/a.dart'); - provider.newFile(a, r''' + newFile('/test/lib/a.dart', content: r''' int T; '''); addTestFile(r''' @@ -5388,8 +5374,8 @@ expect(target.staticType.toString(), '(int) → double'); SimpleIdentifier methodName = invocation.methodName; - expect(methodName.staticElement, same(parameter)); - expect(methodName.staticType, parameter.type); + expect(methodName.staticElement, isNull); + expect(methodName.staticType, dynamicType); } test_methodInvocation_instanceMethod_forwardingStub() async { @@ -5899,7 +5885,7 @@ @failingTest test_optionalConst_prefixed() async { - provider.newFile(_p('/test/lib/a.dart'), r''' + newFile('/test/lib/a.dart', content: r''' class C { const C(); const C.named(); @@ -6426,8 +6412,7 @@ } test_prefixedIdentifier_importPrefix_className() async { - var libPath = _p('/test/lib/lib.dart'); - provider.newFile(libPath, ''' + newFile('/test/lib/lib.dart', content: ''' class MyClass {} typedef void MyFunctionTypeAlias(); int myTopVariable; @@ -8019,12 +8004,9 @@ } test_typeAnnotation_prefixed() async { - var a = _p('/test/lib/a.dart'); - var b = _p('/test/lib/b.dart'); - var c = _p('/test/lib/c.dart'); - provider.newFile(a, 'class A {}'); - provider.newFile(b, "export 'a.dart';"); - provider.newFile(c, "export 'a.dart';"); + newFile('/test/lib/a.dart', content: 'class A {}'); + newFile('/test/lib/b.dart', content: "export 'a.dart';"); + newFile('/test/lib/c.dart', content: "export 'a.dart';"); addTestFile(r''' import 'b.dart' as b; import 'c.dart' as c; @@ -8737,69 +8719,6 @@ expect(identifier.staticType, isDynamicType); } - test_unresolved_static_call() async { - addTestFile(''' -class C { - static f() => C.g(); -} -'''); - await resolveTestFile(); - expect(result.errors, isNotEmpty); - - var g = findNode.simple('g()'); - assertElementNull(g); - assertTypeDynamic(g); - var invocation = g.parent as MethodInvocation; - assertTypeDynamic(invocation); - expect(invocation.staticInvokeType, isDynamicType); - } - - test_unresolved_static_call_arguments() async { - addTestFile(''' -int x; -class C { - static f() => C.g(x); -} -'''); - await resolveTestFile(); - expect(result.errors, isNotEmpty); - - var x = findNode.simple('x)'); - assertElement(x, findElement.topGet('x')); - assertType(x, 'int'); - } - - test_unresolved_static_call_same_name_as_type_param() async { - addTestFile(''' -class C<T> { - static f() => C.T(); -} -'''); - await resolveTestFile(); - expect(result.errors, isNotEmpty); - - var t = findNode.simple('T()'); - assertElementNull(t); - assertTypeDynamic(t); - var invocation = t.parent as MethodInvocation; - assertTypeDynamic(invocation); - expect(invocation.staticInvokeType, isDynamicType); - } - - test_unresolved_static_call_type_arguments() async { - addTestFile(''' -class C { - static f() => C.g<int>(); -} -'''); - await resolveTestFile(); - expect(result.errors, isNotEmpty); - - var intRef = findNode.simple('int>'); - assertElement(intRef, intType.element); - assertType(intRef, 'int'); - } - /// Assert that the [argument] is associated with the [expected]. If the /// [argument] is a [NamedExpression], the name must be resolved to the /// parameter. @@ -8910,7 +8829,7 @@ expect(identifier.staticType, type); } - List<Statement> _getMainStatements(AnalysisResult result) { + List<Statement> _getMainStatements(ResolvedUnitResult result) { for (var declaration in result.unit.declarations) { if (declaration is FunctionDeclaration && declaration.name.name == 'main') { @@ -8922,7 +8841,7 @@ } TopLevelVariableElement _getTopLevelVariable( - AnalysisResult result, String name) { + ResolvedUnitResult result, String name) { for (var variable in result.unit.declaredElement.topLevelVariables) { if (variable.name == name) { return variable; @@ -8931,8 +8850,39 @@ fail('Not found $name'); } - /** - * Return the [provider] specific path for the given Posix [path]. - */ - String _p(String path) => provider.convertPath(path); +// String _p(String path) => convertPath(path); +} + +/** + * Resolution tests that are run with all of the experiments enabled. + */ +@reflectiveTest +class DriverResolutionWithExperimentsTest extends BaseAnalysisDriverTest { + AnalysisOptionsImpl createAnalysisOptions() => super.createAnalysisOptions() + ..enabledExperiments = Experiments.activeExperimentNames; + + test_binaryExpression_gtGtGt() async { + addTestFile(''' +class A { + A operator >>>(int amount) => this; +} +f(A a) { + a >>> 3; +} +'''); + var result = await driver.getResult(testFile); + CompilationUnit unit = result.unit; + MethodDeclaration declaration = + (unit.declarations[0] as ClassDeclaration).members[0]; + ExecutableElement operatorElement = declaration.declaredElement; + expect(operatorElement.name, '>>>'); + ExpressionStatement statement = + ((unit.declarations[1] as FunctionDeclaration).functionExpression.body + as BlockFunctionBody) + .block + .statements[0]; + BinaryExpression binary = statement.expression; + expect(binary.operator.type, TokenType.GT_GT_GT); + expect(binary.staticElement, operatorElement); + } }
diff --git a/pkg/analyzer/test/src/dart/analysis/driver_test.dart b/pkg/analyzer/test/src/dart/analysis/driver_test.dart index 0345738..50b6094 100644 --- a/pkg/analyzer/test/src/dart/analysis/driver_test.dart +++ b/pkg/analyzer/test/src/dart/analysis/driver_test.dart
@@ -1,16 +1,15 @@ -// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file +// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. import 'dart:async'; -import 'package:analyzer/dart/analysis/results.dart' as results; +import 'package:analyzer/dart/analysis/results.dart'; import 'package:analyzer/dart/ast/ast.dart'; import 'package:analyzer/dart/ast/standard_resolution_map.dart'; import 'package:analyzer/dart/element/element.dart'; import 'package:analyzer/dart/element/type.dart'; import 'package:analyzer/error/error.dart'; -import 'package:analyzer/file_system/memory_file_system.dart'; import 'package:analyzer/src/dart/analysis/byte_store.dart'; import 'package:analyzer/src/dart/analysis/driver.dart'; import 'package:analyzer/src/dart/analysis/file_state.dart'; @@ -27,11 +26,12 @@ import 'package:analyzer/src/generated/source.dart'; import 'package:analyzer/src/summary/idl.dart'; import 'package:analyzer/src/summary/package_bundle_reader.dart'; +import 'package:analyzer/src/test_utilities/mock_sdk.dart'; +import 'package:analyzer/src/test_utilities/resource_provider_mixin.dart'; import 'package:test/test.dart'; import 'package:test_reflective_loader/test_reflective_loader.dart'; import '../../../utils.dart'; -import '../../context/mock_sdk.dart'; import 'base.dart'; main() { @@ -57,8 +57,7 @@ } @reflectiveTest -class AnalysisDriverSchedulerTest { - final MemoryResourceProvider provider = new MemoryResourceProvider(); +class AnalysisDriverSchedulerTest with ResourceProviderMixin { DartSdk sdk; final ByteStore byteStore = new MemoryByteStore(); final FileContentOverlay contentOverlay = new FileContentOverlay(); @@ -68,28 +67,28 @@ AnalysisDriverScheduler scheduler; - List<AnalysisResult> allResults = []; + List<ResolvedUnitResult> allResults = []; AnalysisDriver newDriver() { - sdk = new MockSdk(resourceProvider: provider); + sdk = new MockSdk(resourceProvider: resourceProvider); AnalysisDriver driver = new AnalysisDriver( scheduler, logger, - provider, + resourceProvider, byteStore, contentOverlay, null, - new SourceFactory( - [new DartUriResolver(sdk), new ResourceUriResolver(provider)], - null, - provider), + new SourceFactory([ + new DartUriResolver(sdk), + new ResourceUriResolver(resourceProvider) + ], null, resourceProvider), new AnalysisOptionsImpl()); driver.results.forEach(allResults.add); return driver; } void setUp() { - sdk = new MockSdk(resourceProvider: provider); + sdk = new MockSdk(resourceProvider: resourceProvider); logger = new PerformanceLog(logBuffer); scheduler = new AnalysisDriverScheduler(logger); scheduler.start(); @@ -99,14 +98,14 @@ AnalysisDriver driver1 = newDriver(); AnalysisDriver driver2 = newDriver(); - String a = _p('/a.dart'); - String b = _p('/b.dart'); - String c = _p('/c.dart'); - String d = _p('/d.dart'); - provider.newFile(a, 'class A {}'); - provider.newFile(b, "import 'a.dart';"); - provider.newFile(c, 'class C {}'); - provider.newFile(d, "import 'c.dart';"); + String a = convertPath('/a.dart'); + String b = convertPath('/b.dart'); + String c = convertPath('/c.dart'); + String d = convertPath('/d.dart'); + newFile(a, content: 'class A {}'); + newFile(b, content: "import 'a.dart';"); + newFile(c, content: 'class C {}'); + newFile(d, content: "import 'c.dart';"); driver1.addFile(a); driver1.addFile(b); driver2.addFile(c); @@ -115,8 +114,8 @@ await scheduler.waitForIdle(); allResults.clear(); - provider.updateFile(a, 'class A2 {}'); - provider.updateFile(c, 'class C2 {}'); + modifyFile(a, 'class A2 {}'); + modifyFile(c, 'class C2 {}'); driver1.changeFile(a); driver1.changeFile(c); driver2.changeFile(a); @@ -132,12 +131,12 @@ AnalysisDriver driver1 = newDriver(); AnalysisDriver driver2 = newDriver(); - String a = _p('/a.dart'); - String b = _p('/b.dart'); - String c = _p('/c.dart'); - provider.newFile(a, "import 'c.dart';"); - provider.newFile(b, 'class B {}'); - provider.newFile(c, "import 'b.dart';"); + String a = convertPath('/a.dart'); + String b = convertPath('/b.dart'); + String c = convertPath('/c.dart'); + newFile(a, content: "import 'c.dart';"); + newFile(b, content: 'class B {}'); + newFile(c, content: "import 'b.dart';"); driver1.addFile(a); driver1.addFile(b); driver2.addFile(c); @@ -145,7 +144,7 @@ await scheduler.waitForIdle(); allResults.clear(); - provider.updateFile(b, 'class B2 {}'); + modifyFile(b, 'class B2 {}'); driver1.changeFile(b); driver2.changeFile(b); @@ -159,14 +158,14 @@ AnalysisDriver driver1 = newDriver(); AnalysisDriver driver2 = newDriver(); - String a = _p('/a.dart'); - String b = _p('/b.dart'); - String c = _p('/c.dart'); - String d = _p('/d.dart'); - provider.newFile(a, 'class A {}'); - provider.newFile(b, "export 'a.dart';"); - provider.newFile(c, "import 'b.dart';"); - provider.newFile(d, "import 'b.dart'; class D extends X {}"); + String a = convertPath('/a.dart'); + String b = convertPath('/b.dart'); + String c = convertPath('/c.dart'); + String d = convertPath('/d.dart'); + newFile(a, content: 'class A {}'); + newFile(b, content: "export 'a.dart';"); + newFile(c, content: "import 'b.dart';"); + newFile(d, content: "import 'b.dart'; class D extends X {}"); driver1.addFile(a); driver1.addFile(b); driver2.addFile(c); @@ -175,7 +174,7 @@ await scheduler.waitForIdle(); allResults.clear(); - provider.updateFile(a, 'class A2 {}'); + modifyFile(a, 'class A2 {}'); driver1.changeFile(a); driver2.changeFile(a); @@ -189,19 +188,19 @@ AnalysisDriver driver1 = newDriver(); AnalysisDriver driver2 = newDriver(); - String a = _p('/a.dart'); - String b = _p('/b.dart'); - String c = _p('/c.dart'); - provider.newFile(a, 'class A {}'); - provider.newFile(b, 'class B {}'); - provider.newFile(c, 'class C {}'); + String a = convertPath('/a.dart'); + String b = convertPath('/b.dart'); + String c = convertPath('/c.dart'); + newFile(a, content: 'class A {}'); + newFile(b, content: 'class B {}'); + newFile(c, content: 'class C {}'); driver1.addFile(a); driver2.addFile(b); driver2.addFile(c); driver1.priorityFiles = [a]; driver2.priorityFiles = [a]; - AnalysisResult result = await driver2.getResult(b); + ResolvedUnitResult result = await driver2.getResult(b); expect(result.path, b); await scheduler.status.firstWhere((status) => status.isIdle); @@ -216,10 +215,10 @@ AnalysisDriver driver1 = newDriver(); AnalysisDriver driver2 = newDriver(); - String a = _p('/a.dart'); - String b = _p('/b.dart'); - provider.newFile(a, 'class A {}'); - provider.newFile(b, 'class B {}'); + String a = convertPath('/a.dart'); + String b = convertPath('/b.dart'); + newFile(a, content: 'class A {}'); + newFile(b, content: 'class B {}'); driver1.addFile(a); driver2.addFile(b); driver1.priorityFiles = [a]; @@ -236,10 +235,10 @@ AnalysisDriver driver1 = newDriver(); AnalysisDriver driver2 = newDriver(); - String a = _p('/a.dart'); - String b = _p('/b.dart'); - provider.newFile(a, 'class A {}'); - provider.newFile(b, 'class B {}'); + String a = convertPath('/a.dart'); + String b = convertPath('/b.dart'); + newFile(a, content: 'class A {}'); + newFile(b, content: 'class B {}'); driver1.addFile(a); driver2.addFile(b); driver1.priorityFiles = [b]; @@ -256,12 +255,12 @@ AnalysisDriver driver1 = newDriver(); AnalysisDriver driver2 = newDriver(); - String a = _p('/a.dart'); - String b = _p('/b.dart'); - String c = _p('/c.dart'); - provider.newFile(a, 'class A {}'); - provider.newFile(b, 'class B {}'); - provider.newFile(c, 'class C {}'); + String a = convertPath('/a.dart'); + String b = convertPath('/b.dart'); + String c = convertPath('/c.dart'); + newFile(a, content: 'class A {}'); + newFile(b, content: 'class B {}'); + newFile(c, content: 'class C {}'); driver1.addFile(a); driver1.addFile(b); driver2.addFile(c); @@ -280,12 +279,12 @@ AnalysisDriver driver1 = newDriver(); AnalysisDriver driver2 = newDriver(); - String a = _p('/a.dart'); - String b = _p('/b.dart'); - String c = _p('/c.dart'); - provider.newFile(a, 'class A {}'); - provider.newFile(b, 'class B {}'); - provider.newFile(c, 'class C {}'); + String a = convertPath('/a.dart'); + String b = convertPath('/b.dart'); + String c = convertPath('/c.dart'); + newFile(a, content: 'class A {}'); + newFile(b, content: 'class B {}'); + newFile(c, content: 'class C {}'); driver1.addFile(a); driver2.addFile(b); driver2.addFile(c); @@ -312,10 +311,10 @@ AnalysisDriver driver1 = newDriver(); AnalysisDriver driver2 = newDriver(); - String a = _p('/a.dart'); - String b = _p('/b.dart'); - provider.newFile(a, 'class A {}'); - provider.newFile(b, 'class B {}'); + String a = convertPath('/a.dart'); + String b = convertPath('/b.dart'); + newFile(a, content: 'class A {}'); + newFile(b, content: 'class B {}'); driver1.addFile(a); driver2.addFile(b); @@ -339,21 +338,18 @@ await driver1.getFilesReferencingName('X'); expect(allStatuses, isEmpty); } - - String _p(String path) => provider.convertPath(path); } @reflectiveTest class AnalysisDriverTest extends BaseAnalysisDriverTest { void configurePreviewDart2() { driver.configure( - analysisOptions: new AnalysisOptionsImpl.from(driver.analysisOptions) - ..previewDart2 = true); + analysisOptions: new AnalysisOptionsImpl.from(driver.analysisOptions)); } test_addedFiles() async { - var a = _p('/test/lib/a.dart'); - var b = _p('/test/lib/b.dart'); + var a = convertPath('/test/lib/a.dart'); + var b = convertPath('/test/lib/b.dart'); driver.addFile(a); expect(driver.addedFiles, contains(a)); @@ -372,11 +368,11 @@ } test_addFile_shouldRefresh() async { - var a = _p('/test/lib/a.dart'); - var b = _p('/test/lib/b.dart'); + var a = convertPath('/test/lib/a.dart'); + var b = convertPath('/test/lib/b.dart'); - provider.newFile(a, 'class A {}'); - provider.newFile(b, r''' + newFile(a, content: 'class A {}'); + newFile(b, content: r''' import 'a.dart'; '''); @@ -394,7 +390,7 @@ assertNumberOfErrorsInB(1); // Update 'b' to use 'a', no more hints. - provider.newFile(b, r''' + newFile(b, content: r''' import 'a.dart'; main() { print(A); @@ -407,7 +403,7 @@ // Change 'b' content so that it has a hint. // Remove 'b' and add it again. // The file 'b' must be refreshed, and the hint must be reported. - provider.newFile(b, r''' + newFile(b, content: r''' import 'a.dart'; '''); driver.removeFile(b); @@ -417,10 +413,10 @@ } test_addFile_thenRemove() async { - var a = _p('/test/lib/a.dart'); - var b = _p('/test/lib/b.dart'); - provider.newFile(a, 'class A {}'); - provider.newFile(b, 'class B {}'); + var a = convertPath('/test/lib/a.dart'); + var b = convertPath('/test/lib/b.dart'); + newFile(a, content: 'class A {}'); + newFile(b, content: 'class B {}'); driver.addFile(a); driver.addFile(b); @@ -435,24 +431,24 @@ } test_analyze_resolveDirectives() async { - var lib = _p('/test/lib.dart'); - var part1 = _p('/test/part1.dart'); - var part2 = _p('/test/part2.dart'); - provider.newFile(lib, ''' + var lib = convertPath('/test/lib.dart'); + var part1 = convertPath('/test/part1.dart'); + var part2 = convertPath('/test/part2.dart'); + newFile(lib, content: ''' library lib; part 'part1.dart'; part 'part2.dart'; '''); - provider.newFile(part1, ''' + newFile(part1, content: ''' part of lib; '''); - provider.newFile(part2, ''' + newFile(part2, content: ''' part of 'lib.dart'; '''); - AnalysisResult libResult = await driver.getResult(lib); - AnalysisResult partResult1 = await driver.getResult(part1); - AnalysisResult partResult2 = await driver.getResult(part2); + ResolvedUnitResult libResult = await driver.getResult(lib); + ResolvedUnitResult partResult1 = await driver.getResult(part1); + ResolvedUnitResult partResult2 = await driver.getResult(part2); CompilationUnit libUnit = libResult.unit; CompilationUnit partUnit1 = partResult1.unit; @@ -486,189 +482,87 @@ } test_analyze_resolveDirectives_error_missingLibraryDirective() async { - var lib = _p('/test/lib.dart'); - var part = _p('/test/part.dart'); - provider.newFile(lib, ''' + var lib = convertPath('/test/lib.dart'); + var part = convertPath('/test/part.dart'); + newFile(lib, content: ''' part 'part.dart'; '''); - provider.newFile(part, ''' + newFile(part, content: ''' part of lib; '''); driver.addFile(lib); - AnalysisResult libResult = await driver.getResult(lib); + ResolvedUnitResult libResult = await driver.getResult(lib); List<AnalysisError> errors = libResult.errors; expect(errors, hasLength(1)); expect(errors[0].errorCode, ResolverErrorCode.PART_OF_UNNAMED_LIBRARY); } test_analyze_resolveDirectives_error_partOfDifferentLibrary_byName() async { - var lib = _p('/test/lib.dart'); - var part = _p('/test/part.dart'); - provider.newFile(lib, ''' + var lib = convertPath('/test/lib.dart'); + var part = convertPath('/test/part.dart'); + newFile(lib, content: ''' library lib; part 'part.dart'; '''); - provider.newFile(part, ''' + newFile(part, content: ''' part of someOtherLib; '''); driver.addFile(lib); - AnalysisResult libResult = await driver.getResult(lib); + ResolvedUnitResult libResult = await driver.getResult(lib); List<AnalysisError> errors = libResult.errors; expect(errors, hasLength(1)); expect(errors[0].errorCode, StaticWarningCode.PART_OF_DIFFERENT_LIBRARY); } test_analyze_resolveDirectives_error_partOfDifferentLibrary_byUri() async { - var lib = _p('/test/lib.dart'); - var part = _p('/test/part.dart'); - provider.newFile(lib, ''' + var lib = convertPath('/test/lib.dart'); + var part = convertPath('/test/part.dart'); + newFile(lib, content: ''' library lib; part 'part.dart'; '''); - provider.newFile(part, ''' + newFile(part, content: ''' part of 'other_lib.dart'; '''); driver.addFile(lib); - AnalysisResult libResult = await driver.getResult(lib); + ResolvedUnitResult libResult = await driver.getResult(lib); List<AnalysisError> errors = libResult.errors; expect(errors, hasLength(1)); expect(errors[0].errorCode, StaticWarningCode.PART_OF_DIFFERENT_LIBRARY); } test_analyze_resolveDirectives_error_partOfNonPart() async { - var lib = _p('/test/lib.dart'); - var part = _p('/test/part.dart'); - provider.newFile(lib, ''' + var lib = convertPath('/test/lib.dart'); + var part = convertPath('/test/part.dart'); + newFile(lib, content: ''' library lib; part 'part.dart'; '''); - provider.newFile(part, ''' + newFile(part, content: ''' // no part of directive '''); driver.addFile(lib); - AnalysisResult libResult = await driver.getResult(lib); + ResolvedUnitResult libResult = await driver.getResult(lib); List<AnalysisError> errors = libResult.errors; expect(errors, hasLength(1)); expect(errors[0].errorCode, CompileTimeErrorCode.PART_OF_NON_PART); } - test_asyncChangesDuringAnalysis_getErrors() async { - var path = _p('/test/lib/test.dart'); - provider.newFile(path, 'class A {}'); - driver.addFile(path); - - // Compute and cache errors. - await driver.getErrors(path); - await waitForIdleWithoutExceptions(); - - // Simulate a change that happens during reading the cached errors. - bool asyncWorkExecuted = false; - driver.test.workToWaitAfterComputingResult = (path) async { - await new Future.value(); // the rest will be executed asynchronously - provider.updateFile(path, 'class B'); - driver.changeFile(path); - asyncWorkExecuted = true; - }; - - ErrorsResult result = await driver.getErrors(testFile); - expect(asyncWorkExecuted, isTrue); - expect(result.errors, isNotEmpty); - } - - test_asyncChangesDuringAnalysis_getResult() async { - var path = _p('/test/lib/test.dart'); - provider.newFile(path, 'class A {}'); - driver.addFile(path); - - // Schedule the result to be computed. - Future<AnalysisResult> future1 = driver.getResult(testFile); - - // Simulate a change that happens during computing the result. - // We also request a new result, which must include the change. - Future<AnalysisResult> future2; - bool asyncWorkExecuted = false; - driver.test.workToWaitAfterComputingResult = (path) async { - provider.updateFile(path, 'class B {}'); - driver.changeFile(path); - future2 = driver.getResult(testFile); - asyncWorkExecuted = true; - }; - - // Both futures complete, with the same result. - // The result must be with the new changes. - // - // It would not be wrong to have "class A {}" in result1, and "class B {}" - // in result2, but we test here the actual implementation behaviour. - AnalysisResult result1 = await future1; - AnalysisResult result2 = await future2; - expect(asyncWorkExecuted, isTrue); - expect(result2, same(result1)); - expect(result1.path, testFile); - expect(result1.unit, isNotNull); - expect((result1.unit.declarations[0] as ClassDeclaration).name.name, 'B'); - } - - test_asyncChangesDuringAnalysis_resultsStream() async { - var path = _p('/test/lib/test.dart'); - provider.newFile(path, 'class A {}'); - driver.addFile(path); - - // Simulate a change that happens during computing the result. - bool asyncWorkExecuted = false; - driver.test.workToWaitAfterComputingResult = (p) async { - if (p == path && !asyncWorkExecuted) { - provider.updateFile(path, 'class B'); - driver.changeFile(path); - asyncWorkExecuted = true; - } - }; - - await waitForIdleWithoutExceptions(); - expect(asyncWorkExecuted, isTrue); - - // The last result must have an error. - expect(allResults.last.errors, isNotEmpty); - } - - test_asyncChangesDuringAnalysis_resultsStream_priority() async { - var path = _p('/test/lib/test.dart'); - provider.newFile(path, 'class A {}'); - driver.addFile(path); - driver.priorityFiles = [path]; - - // Simulate a change that happens during computing the result. - bool asyncWorkExecuted = false; - driver.test.workToWaitAfterComputingResult = (p) async { - if (p == path && !asyncWorkExecuted) { - provider.updateFile(path, 'class B {}'); - driver.changeFile(path); - asyncWorkExecuted = true; - } - }; - - await waitForIdleWithoutExceptions(); - expect(asyncWorkExecuted, isTrue); - - // The last unit must have "class B {}". - var lastUnit = allResults.last.unit; - expect((lastUnit.declarations[0] as ClassDeclaration).name.name, 'B'); - } - test_cachedPriorityResults() async { - var a = _p('/test/bin/a.dart'); - provider.newFile(a, 'var a = 1;'); + var a = convertPath('/test/bin/a.dart'); + newFile(a, content: 'var a = 1;'); driver.priorityFiles = [a]; - AnalysisResult result1 = await driver.getResult(a); + ResolvedUnitResult result1 = await driver.getResult(a); expect(driver.test.priorityResults, containsPair(a, result1)); await waitForIdleWithoutExceptions(); @@ -676,14 +570,14 @@ // Get the (cached) result, not reported to the stream. { - AnalysisResult result2 = await driver.getResult(a); + ResolvedUnitResult result2 = await driver.getResult(a); expect(result2, same(result1)); expect(allResults, isEmpty); } // Get the (cached) result, reported to the stream. { - AnalysisResult result2 = + ResolvedUnitResult result2 = await driver.getResult(a, sendCachedToStream: true); expect(result2, same(result1)); @@ -693,28 +587,28 @@ } test_cachedPriorityResults_flush_onAnyFileChange() async { - var a = _p('/test/bin/a.dart'); - var b = _p('/test/bin/b.dart'); - provider.newFile(a, 'var a = 1;'); - provider.newFile(a, 'var b = 2;'); + var a = convertPath('/test/bin/a.dart'); + var b = convertPath('/test/bin/b.dart'); + newFile(a, content: 'var a = 1;'); + newFile(a, content: 'var b = 2;'); driver.priorityFiles = [a]; - AnalysisResult result1 = await driver.getResult(a); + ResolvedUnitResult result1 = await driver.getResult(a); expect(driver.test.priorityResults, containsPair(a, result1)); // Change a file. // The cache is flushed. driver.changeFile(a); expect(driver.test.priorityResults, isEmpty); - AnalysisResult result2 = await driver.getResult(a); + ResolvedUnitResult result2 = await driver.getResult(a); expect(driver.test.priorityResults, containsPair(a, result2)); // Add a file. // The cache is flushed. driver.addFile(b); expect(driver.test.priorityResults, isEmpty); - AnalysisResult result3 = await driver.getResult(a); + ResolvedUnitResult result3 = await driver.getResult(a); expect(driver.test.priorityResults, containsPair(a, result3)); // Remove a file. @@ -724,14 +618,14 @@ } test_cachedPriorityResults_flush_onPrioritySetChange() async { - var a = _p('/test/bin/a.dart'); - var b = _p('/test/bin/b.dart'); - provider.newFile(a, 'var a = 1;'); - provider.newFile(b, 'var b = 2;'); + var a = convertPath('/test/bin/a.dart'); + var b = convertPath('/test/bin/b.dart'); + newFile(a, content: 'var a = 1;'); + newFile(b, content: 'var b = 2;'); driver.priorityFiles = [a]; - AnalysisResult result1 = await driver.getResult(a); + ResolvedUnitResult result1 = await driver.getResult(a); expect(driver.test.priorityResults, hasLength(1)); expect(driver.test.priorityResults, containsPair(a, result1)); @@ -742,7 +636,7 @@ expect(driver.test.priorityResults, containsPair(a, result1)); // Get the result for "b". - AnalysisResult result2 = await driver.getResult(b); + ResolvedUnitResult result2 = await driver.getResult(b); expect(driver.test.priorityResults, hasLength(2)); expect(driver.test.priorityResults, containsPair(a, result1)); expect(driver.test.priorityResults, containsPair(b, result2)); @@ -755,25 +649,25 @@ } test_cachedPriorityResults_notPriority() async { - var a = _p('/test/bin/a.dart'); - provider.newFile(a, 'var a = 1;'); + var a = convertPath('/test/bin/a.dart'); + newFile(a, content: 'var a = 1;'); - AnalysisResult result1 = await driver.getResult(a); + ResolvedUnitResult result1 = await driver.getResult(a); expect(driver.test.priorityResults, isEmpty); // The file is not priority, so its result is not cached. - AnalysisResult result2 = await driver.getResult(a); + ResolvedUnitResult result2 = await driver.getResult(a); expect(result2, isNot(same(result1))); } test_changeFile_implicitlyAnalyzed() async { - var a = _p('/test/lib/a.dart'); - var b = _p('/test/lib/b.dart'); - provider.newFile(a, r''' + var a = convertPath('/test/lib/a.dart'); + var b = convertPath('/test/lib/b.dart'); + newFile(a, content: r''' import 'b.dart'; var A = B; '''); - provider.newFile(b, 'var B = 1;'); + newFile(b, content: 'var B = 1;'); driver.priorityFiles = [a]; driver.addFile(a); @@ -782,13 +676,13 @@ await waitForIdleWithoutExceptions(); expect(allResults, hasLength(1)); { - AnalysisResult ar = allResults.firstWhere((r) => r.path == a); + ResolvedUnitResult ar = allResults.firstWhere((r) => r.path == a); expect(_getTopLevelVarType(ar.unit, 'A'), 'int'); } allResults.clear(); // Change "b" and notify. - provider.updateFile(b, 'var B = 1.2;'); + modifyFile(b, 'var B = 1.2;'); driver.changeFile(b); // "b" is not an added file, so it is not scheduled for analysis. @@ -799,7 +693,7 @@ await waitForIdleWithoutExceptions(); expect(allResults, hasLength(1)); { - AnalysisResult ar = allResults.firstWhere((r) => r.path == a); + ResolvedUnitResult ar = allResults.firstWhere((r) => r.path == a); expect(_getTopLevelVarType(ar.unit, 'A'), 'double'); } } @@ -812,10 +706,10 @@ } test_changeFile_notUsed() async { - var a = _p('/test/lib/a.dart'); - var b = _p('/other/b.dart'); - provider.newFile(a, ''); - provider.newFile(b, 'class B1 {}'); + var a = convertPath('/test/lib/a.dart'); + var b = convertPath('/other/b.dart'); + newFile(a); + newFile(b, content: 'class B1 {}'); driver.addFile(a); @@ -824,7 +718,7 @@ // Change "b" and notify. // Nothing depends on "b", so nothing is analyzed. - provider.updateFile(b, 'class B2 {}'); + modifyFile(b, 'class B2 {}'); driver.changeFile(b); await waitForIdleWithoutExceptions(); expect(allResults, isEmpty); @@ -834,14 +728,14 @@ } test_changeFile_selfConsistent() async { - var a = _p('/test/lib/a.dart'); - var b = _p('/test/lib/b.dart'); - provider.newFile(a, r''' + var a = convertPath('/test/lib/a.dart'); + var b = convertPath('/test/lib/b.dart'); + newFile(a, content: r''' import 'b.dart'; var A1 = 1; var A2 = B1; '''); - provider.newFile(b, r''' + newFile(b, content: r''' import 'a.dart'; var B1 = A1; '''); @@ -854,18 +748,18 @@ // We have results for both "a" and "b". expect(allResults, hasLength(2)); { - AnalysisResult ar = allResults.firstWhere((r) => r.path == a); + ResolvedUnitResult ar = allResults.firstWhere((r) => r.path == a); expect(_getTopLevelVarType(ar.unit, 'A1'), 'int'); expect(_getTopLevelVarType(ar.unit, 'A2'), 'int'); } { - AnalysisResult br = allResults.firstWhere((r) => r.path == b); + ResolvedUnitResult br = allResults.firstWhere((r) => r.path == b); expect(_getTopLevelVarType(br.unit, 'B1'), 'int'); } // Clear the results and update "a". allResults.clear(); - provider.updateFile(a, r''' + modifyFile(a, r''' import 'b.dart'; var A1 = 1.2; var A2 = B1; @@ -877,12 +771,12 @@ await waitForIdleWithoutExceptions(); expect(allResults, hasLength(2)); { - AnalysisResult ar = allResults.firstWhere((r) => r.path == a); + ResolvedUnitResult ar = allResults.firstWhere((r) => r.path == a); expect(_getTopLevelVarType(ar.unit, 'A1'), 'double'); expect(_getTopLevelVarType(ar.unit, 'A2'), 'double'); } { - AnalysisResult br = allResults.firstWhere((r) => r.path == b); + ResolvedUnitResult br = allResults.firstWhere((r) => r.path == b); expect(_getTopLevelVarType(br.unit, 'B1'), 'double'); } } @@ -894,14 +788,14 @@ { await waitForIdleWithoutExceptions(); expect(allResults, hasLength(1)); - AnalysisResult result = allResults[0]; + ResolvedUnitResult result = allResults[0]; expect(result.path, testFile); expect(_getTopLevelVarType(result.unit, 'V'), 'int'); } // Update the file, but don't notify the driver. allResults.clear(); - provider.updateFile(testFile, 'var V = 1.2;'); + modifyFile(testFile, 'var V = 1.2;'); // No new results. await pumpEventQueue(); @@ -917,7 +811,7 @@ { await waitForIdleWithoutExceptions(); expect(allResults, hasLength(1)); - AnalysisResult result = allResults[0]; + ResolvedUnitResult result = allResults[0]; expect(result.path, testFile); expect(_getTopLevelVarType(result.unit, 'V'), 'double'); } @@ -1013,15 +907,15 @@ test_const_implicitCreation() async { configurePreviewDart2(); - var a = _p('/test/bin/a.dart'); - var b = _p('/test/bin/b.dart'); - provider.newFile(a, r''' + var a = convertPath('/test/bin/a.dart'); + var b = convertPath('/test/bin/b.dart'); + newFile(a, content: r''' class C { const C(); static const C WARNING = C(); } '''); - provider.newFile(b, r''' + newFile(b, content: r''' import 'a.dart'; class D { @@ -1032,16 +926,16 @@ const c = C.WARNING; const d = D.WARNING; '''); - AnalysisResult result = await driver.getResult(b); + ResolvedUnitResult result = await driver.getResult(b); expect(result.errors, isEmpty); } test_const_implicitCreation_rewrite() async { configurePreviewDart2(); - var a = _p('/test/bin/a.dart'); - var b = _p('/test/bin/b.dart'); - provider.newFile(a, r''' + var a = convertPath('/test/bin/a.dart'); + var b = convertPath('/test/bin/b.dart'); + newFile(a, content: r''' class A { const A(); } @@ -1056,14 +950,14 @@ const C(); } '''); - provider.newFile(b, r''' + newFile(b, content: r''' import 'a.dart'; main() { const C(); } '''); - AnalysisResult result = await driver.getResult(b); + ResolvedUnitResult result = await driver.getResult(b); expect(result.errors, isEmpty); } @@ -1090,15 +984,15 @@ } test_currentSession() async { - var a = _p('/a.dart'); + var a = convertPath('/a.dart'); - provider.newFile(a, 'var V = 1;'); + newFile(a, content: 'var V = 1;'); await driver.getResult(a); var session1 = driver.currentSession; expect(session1, isNotNull); - provider.updateFile(a, 'var V = 2;'); + modifyFile(a, 'var V = 2;'); driver.changeFile(a); await driver.getResult(a); @@ -1110,19 +1004,19 @@ } test_discoverAvailableFiles_packages() async { - var t = _p('/test/lib/test.dart'); - var a1 = _p('/aaa/lib/a1.dart'); - var a2 = _p('/aaa/lib/src/a2.dart'); - var a3 = _p('/aaa/lib/a3.txt'); - var b = _p('/bbb/lib/b.dart'); - var c = _p('/ccc/lib/c.dart'); + var t = convertPath('/test/lib/test.dart'); + var a1 = convertPath('/aaa/lib/a1.dart'); + var a2 = convertPath('/aaa/lib/src/a2.dart'); + var a3 = convertPath('/aaa/lib/a3.txt'); + var b = convertPath('/bbb/lib/b.dart'); + var c = convertPath('/ccc/lib/c.dart'); - provider.newFile(t, 'class T {}'); - provider.newFile(a1, 'class A1 {}'); - provider.newFile(a2, 'class A2 {}'); - provider.newFile(a3, 'text'); - provider.newFile(b, 'class B {}'); - provider.newFile(c, 'class C {}'); + newFile(t, content: 'class T {}'); + newFile(a1, content: 'class A1 {}'); + newFile(a2, content: 'class A2 {}'); + newFile(a3, content: 'text'); + newFile(b, content: 'class B {}'); + newFile(c, content: 'class C {}'); driver.addFile(t); // Don't add a1.dart, a2.dart, or b.dart - they should be discovered. @@ -1161,7 +1055,7 @@ export 'foo.dart'; '''); - AnalysisResult result = await driver.getResult(testFile); + ResolvedUnitResult result = await driver.getResult(testFile); List<AnalysisError> errors = result.errors; expect(errors, hasLength(1)); expect(errors[0].errorCode, CompileTimeErrorCode.URI_DOES_NOT_EXIST); @@ -1172,7 +1066,7 @@ import 'foo.dart'; '''); - AnalysisResult result = await driver.getResult(testFile); + ResolvedUnitResult result = await driver.getResult(testFile); List<AnalysisError> errors = result.errors; expect(errors, hasLength(1)); expect(errors[0].errorCode, CompileTimeErrorCode.URI_DOES_NOT_EXIST); @@ -1186,7 +1080,7 @@ } ''', priority: true); - AnalysisResult result = await driver.getResult(testFile); + ResolvedUnitResult result = await driver.getResult(testFile); List<AnalysisError> errors = result.errors; expect(errors, hasLength(1)); expect(errors[0].errorCode, CompileTimeErrorCode.URI_DOES_NOT_EXIST); @@ -1198,19 +1092,19 @@ part 'foo.dart'; '''); - AnalysisResult result = await driver.getResult(testFile); + ResolvedUnitResult result = await driver.getResult(testFile); List<AnalysisError> errors = result.errors; expect(errors, hasLength(1)); expect(errors[0].errorCode, CompileTimeErrorCode.URI_DOES_NOT_EXIST); } test_externalSummaries() async { - var a = _p('/a.dart'); - var b = _p('/b.dart'); - provider.newFile(a, r''' + var a = convertPath('/a.dart'); + var b = convertPath('/b.dart'); + newFile(a, content: r''' class A {} '''); - provider.newFile(b, r''' + newFile(b, content: r''' import 'a.dart'; var a = new A(); '''); @@ -1220,37 +1114,37 @@ await createAnalysisDriver().test.getSummaryStore(a); // There are at least a.dart and dart:core libraries. - String aUri = provider.pathContext.toUri(a).toString(); + String aUri = toUri(a).toString(); expect(summaryStore.unlinkedMap.keys, contains(aUri)); expect(summaryStore.linkedMap.keys, contains(aUri)); expect(summaryStore.unlinkedMap.keys, contains('dart:core')); expect(summaryStore.linkedMap.keys, contains('dart:core')); // Remove a.dart from the file system. - provider.deleteFile(a); + deleteFile(a); // We don't need a.dart file when we analyze with the summary store. // Still no analysis errors. AnalysisDriver driver = createAnalysisDriver(externalSummaries: summaryStore); - AnalysisResult result = await driver.getResult(b); + ResolvedUnitResult result = await driver.getResult(b); expect(result.errors, isEmpty); } test_externalSummaries_partReuse() async { - var a = _p('/a.dart'); - var b = _p('/b.dart'); - var c = _p('/c.dart'); - provider.newFile(a, r''' + var a = convertPath('/a.dart'); + var b = convertPath('/b.dart'); + var c = convertPath('/c.dart'); + newFile(a, content: r''' library a; part 'b.dart'; class A {} '''); - provider.newFile(b, r''' + newFile(b, content: r''' part of a; class _B {} '''); - provider.newFile(c, r''' + newFile(c, content: r''' library a; import 'a.dart'; part 'b.dart'; @@ -1262,8 +1156,8 @@ SummaryDataStore summaryStore = await createAnalysisDriver().test.getSummaryStore(a); - String aUri = provider.pathContext.toUri(a).toString(); - String bUri = provider.pathContext.toUri(b).toString(); + String aUri = toUri(a).toString(); + String bUri = toUri(b).toString(); // There are unlinked units for a.dart and b.dart files. expect(summaryStore.hasUnlinkedUnit(aUri), isTrue); expect(summaryStore.hasUnlinkedUnit(bUri), isTrue); @@ -1273,28 +1167,28 @@ // Remove a.dart from the file system. // Keep b.dart, because we (re)use it as a part. - provider.deleteFile(a); + deleteFile(a); // We don't need a.dart file when we analyze with the summary store. // We can instantiate the class A the library a.dart. // We can instantiate the class _A the part b.dart. AnalysisDriver driver = createAnalysisDriver(externalSummaries: summaryStore); - AnalysisResult result = await driver.getResult(c); + ResolvedUnitResult result = await driver.getResult(c); expect(result.errors, isEmpty); } test_generatedFile() async { Uri uri = Uri.parse('package:aaa/foo.dart'); - String templatePath = _p('/aaa/lib/foo.dart'); - String generatedPath = _p('/generated/aaa/lib/foo.dart'); + String templatePath = convertPath('/aaa/lib/foo.dart'); + String generatedPath = convertPath('/generated/aaa/lib/foo.dart'); - provider.newFile(templatePath, r''' + newFile(templatePath, content: r''' a() {} b() {} '''); - provider.newFile(generatedPath, r''' + newFile(generatedPath, content: r''' aaa() {} bbb() {} '''); @@ -1338,13 +1232,13 @@ } test_getCachedResult() async { - var a = _p('/test/bin/a.dart'); - provider.newFile(a, 'var a = 1;'); + var a = convertPath('/test/bin/a.dart'); + newFile(a, content: 'var a = 1;'); expect(driver.getCachedResult(a), isNull); driver.priorityFiles = [a]; - AnalysisResult result = await driver.getResult(a); + ResolvedUnitResult result = await driver.getResult(a); expect(driver.getCachedResult(a), same(result)); } @@ -1367,15 +1261,15 @@ } test_getFilesDefiningClassMemberName_class() async { - var a = _p('/test/bin/a.dart'); - var b = _p('/test/bin/b.dart'); - var c = _p('/test/bin/c.dart'); - var d = _p('/test/bin/d.dart'); + var a = convertPath('/test/bin/a.dart'); + var b = convertPath('/test/bin/b.dart'); + var c = convertPath('/test/bin/c.dart'); + var d = convertPath('/test/bin/d.dart'); - provider.newFile(a, 'class A { m1() {} }'); - provider.newFile(b, 'class B { m2() {} }'); - provider.newFile(c, 'class C { m2() {} }'); - provider.newFile(d, 'class D { m3() {} }'); + newFile(a, content: 'class A { m1() {} }'); + newFile(b, content: 'class B { m2() {} }'); + newFile(c, content: 'class C { m2() {} }'); + newFile(d, content: 'class D { m3() {} }'); driver.addFile(a); driver.addFile(b); @@ -1393,15 +1287,15 @@ } test_getFilesDefiningClassMemberName_mixin() async { - var a = _p('/test/bin/a.dart'); - var b = _p('/test/bin/b.dart'); - var c = _p('/test/bin/c.dart'); - var d = _p('/test/bin/d.dart'); + var a = convertPath('/test/bin/a.dart'); + var b = convertPath('/test/bin/b.dart'); + var c = convertPath('/test/bin/c.dart'); + var d = convertPath('/test/bin/d.dart'); - provider.newFile(a, 'mixin A { m1() {} }'); - provider.newFile(b, 'mixin B { m2() {} }'); - provider.newFile(c, 'mixin C { m2() {} }'); - provider.newFile(d, 'mixin D { m3() {} }'); + newFile(a, content: 'mixin A { m1() {} }'); + newFile(b, content: 'mixin B { m2() {} }'); + newFile(c, content: 'mixin C { m2() {} }'); + newFile(d, content: 'mixin D { m3() {} }'); driver.addFile(a); driver.addFile(b); @@ -1419,17 +1313,17 @@ } test_getFilesReferencingName() async { - var a = _p('/test/bin/a.dart'); - var b = _p('/test/bin/b.dart'); - var c = _p('/test/bin/c.dart'); - var d = _p('/test/bin/d.dart'); - var e = _p('/test/bin/e.dart'); + var a = convertPath('/test/bin/a.dart'); + var b = convertPath('/test/bin/b.dart'); + var c = convertPath('/test/bin/c.dart'); + var d = convertPath('/test/bin/d.dart'); + var e = convertPath('/test/bin/e.dart'); - provider.newFile(a, 'class A {}'); - provider.newFile(b, "import 'a.dart'; A a;"); - provider.newFile(c, "import 'a.dart'; var a = new A();"); - provider.newFile(d, "class A{} A a;"); - provider.newFile(e, "import 'a.dart'; main() {}"); + newFile(a, content: 'class A {}'); + newFile(b, content: "import 'a.dart'; A a;"); + newFile(c, content: "import 'a.dart'; var a = new A();"); + newFile(d, content: "class A{} A a;"); + newFile(e, content: "import 'a.dart'; main() {}"); driver.addFile(a); driver.addFile(b); @@ -1450,15 +1344,15 @@ } test_getFilesReferencingName_discover() async { - var t = _p('/test/lib/test.dart'); - var a = _p('/aaa/lib/a.dart'); - var b = _p('/bbb/lib/b.dart'); - var c = _p('/ccc/lib/c.dart'); + var t = convertPath('/test/lib/test.dart'); + var a = convertPath('/aaa/lib/a.dart'); + var b = convertPath('/bbb/lib/b.dart'); + var c = convertPath('/ccc/lib/c.dart'); - provider.newFile(t, 'int t;'); - provider.newFile(a, 'int a;'); - provider.newFile(b, 'int b;'); - provider.newFile(c, 'int c;'); + newFile(t, content: 'int t;'); + newFile(a, content: 'int a;'); + newFile(b, content: 'int b;'); + newFile(c, content: 'int c;'); driver.addFile(t); @@ -1470,8 +1364,8 @@ } test_getFileSync_library() async { - var path = _p('/test/lib/a.dart'); - provider.newFile(path, ''); + var path = convertPath('/test/lib/a.dart'); + newFile(path); var file = driver.getFileSync(path); expect(file.path, path); expect(file.uri.toString(), 'package:test/a.dart'); @@ -1486,8 +1380,8 @@ } test_getFileSync_part() async { - var path = _p('/test/lib/a.dart'); - provider.newFile(path, 'part of lib;'); + var path = convertPath('/test/lib/a.dart'); + newFile(path, content: 'part of lib;'); var file = driver.getFileSync(path); expect(file.path, path); expect(file.uri.toString(), 'package:test/a.dart'); @@ -1518,29 +1412,86 @@ } on ArgumentError {} } - test_getLibraryByUri_external_resynthesize() async { - provider.newFile(testFile, r''' -class Test {} + test_getLibraryByUri() async { + var a = '/test/lib/a.dart'; + var b = '/test/lib/b.dart'; + + String aUriStr = 'package:test/a.dart'; + String bUriStr = 'package:test/b.dart'; + + newFile(a, content: r''' +part 'b.dart'; + +class A {} +'''); + + newFile(b, content: r''' +part of 'a.dart'; + +class B {} +'''); + + var library = await driver.getLibraryByUri(aUriStr); + expect(library.getType('A'), isNotNull); + expect(library.getType('B'), isNotNull); + + // It is an error to ask for a library when we know that it is a part. + expect(() async { + await driver.getLibraryByUri(bUriStr); + }, throwsArgumentError); + } + + test_getLibraryByUri_external() async { + var a = convertPath('/test/lib/a.dart'); + var b = convertPath('/test/lib/b.dart'); + + String aUriStr = 'package:test/a.dart'; + String bUriStr = 'package:test/b.dart'; + + newFile(a, content: r''' +part 'b.dart'; + +class A {} +'''); + + newFile(b, content: r''' +part of 'a.dart'; + +class B {} '''); // Prepare the store with package:test/test.dart URI. - SummaryDataStore summaryStore = - await createAnalysisDriver().test.getSummaryStore(testFile); + var store = await createAnalysisDriver().test.getSummaryStore(a); // package:test/test.dart is in the store. - String uri = 'package:test/test.dart'; - expect(summaryStore.unlinkedMap.keys, contains(uri)); - expect(summaryStore.linkedMap.keys, contains(uri)); + expect(store.unlinkedMap.keys, contains(aUriStr)); + expect(store.unlinkedMap.keys, contains(bUriStr)); + expect(store.linkedMap.keys, contains(aUriStr)); + expect(store.linkedMap.keys, isNot(contains(bUriStr))); - // Remove the file from the file system. - provider.deleteFile(testFile); + // Remove the files from the file system. + deleteFile(a); + deleteFile(b); - // We can resynthesize the library from the store without reading the file. - AnalysisDriver driver = - createAnalysisDriver(externalSummaries: summaryStore); - expect(driver.test.numOfCreatedLibraryContexts, 0); - LibraryElement library = await driver.getLibraryByUri(uri); - expect(library.getType('Test'), isNotNull); + // We can resynthesize the library from the store. + var driver = createAnalysisDriver(externalSummaries: store); + + // Ask by URI, so we get the "external" FileState. + var aUri = Uri.parse(aUriStr); + var aFile = driver.fsState.getFileForUri(aUri); + expect(aFile.uri, aUri); + expect(aFile.path, isNull); + + // We still can resynthesize the library. + // The URI is known to be external, so we don't talk to the file. + var library = await driver.getLibraryByUri(aUriStr); + expect(library.getType('A'), isNotNull); + expect(library.getType('B'), isNotNull); + + // It is an error to ask for a library when we know that it is a part. + expect(() async { + await driver.getLibraryByUri(bUriStr); + }, throwsArgumentError); } test_getLibraryByUri_sdk_analyze() async { @@ -1551,11 +1502,9 @@ } test_getLibraryByUri_sdk_resynthesize() async { - SummaryDataStore sdkStore; - { - String corePath = sdk.mapDartUri('dart:core').fullName; - sdkStore = await createAnalysisDriver().test.getSummaryStore(corePath); - } + String corePath = sdk.mapDartUri('dart:core').fullName; + String asyncPath = sdk.mapDartUri('dart:async').fullName; + var sdkStore = await createAnalysisDriver().test.getSummaryStore(corePath); // There are dart:core and dart:async in the store. expect(sdkStore.unlinkedMap.keys, contains('dart:core')); @@ -1563,25 +1512,109 @@ expect(sdkStore.linkedMap.keys, contains('dart:core')); expect(sdkStore.linkedMap.keys, contains('dart:async')); - // We don't create new library context (so, don't parse, summarize and - // link) for dart:core. The library is resynthesized from the provided - // external store. + // Remove dart:core and dart:async. + // So, the new driver below cannot parse and summarize them. + deleteFile(corePath); + deleteFile(asyncPath); + + // We still get get dart:core library element. AnalysisDriver driver = createAnalysisDriver(externalSummaries: sdkStore); LibraryElement coreLibrary = await driver.getLibraryByUri('dart:core'); - expect(driver.test.numOfCreatedLibraryContexts, 0); expect(coreLibrary, isNotNull); expect(coreLibrary.getType('Object'), isNotNull); } - test_getResolvedLibrary_external() async { - var a1 = _p('/aaa/lib/a1.dart'); - var a2 = _p('/aaa/lib/a2.dart'); + test_getParsedLibrary_external() async { + var a1 = convertPath('/aaa/lib/a1.dart'); + var a2 = convertPath('/aaa/lib/a2.dart'); var a1UriStr = 'package:aaa/a1.dart'; var a2UriStr = 'package:aaa/a2.dart'; - provider.newFile(a1, "part 'a2.dart'; class A {}"); - provider.newFile(a2, "part of 'a1.dart';"); + newFile(a1, content: "part 'a2.dart'; class A {}"); + newFile(a2, content: "part of 'a1.dart';"); + + // Build the store with the library. + var store = await createAnalysisDriver().test.getSummaryStore(a1); + expect(store.unlinkedMap.keys, contains(a1UriStr)); + expect(store.unlinkedMap.keys, contains(a2UriStr)); + expect(store.linkedMap.keys, contains(a1UriStr)); + + var driver = createAnalysisDriver(externalSummaries: store); + var libraryElement = await driver.getLibraryByUri(a1UriStr); + var classA = libraryElement.library.getType('A'); + + var parsedLibrary = driver.getParsedLibrary(a1); + expect(parsedLibrary, isNotNull); + expect(parsedLibrary.state, ResultState.NOT_A_FILE); + expect(() { + parsedLibrary.getElementDeclaration(classA); + }, throwsStateError); + + // It is an error to ask for a library when we know that it is a part. + expect(() { + driver.getParsedLibrary(a2); + }, throwsArgumentError); + } + + test_getParsedLibraryByUri_external() async { + var a1 = convertPath('/aaa/lib/a1.dart'); + var a2 = convertPath('/aaa/lib/a2.dart'); + + var a1UriStr = 'package:aaa/a1.dart'; + var a2UriStr = 'package:aaa/a2.dart'; + + var a1Uri = Uri.parse(a1UriStr); + var a2Uri = Uri.parse(a2UriStr); + + newFile(a1, content: "part 'a2.dart'; class A {}"); + newFile(a2, content: "part of 'a1.dart';"); + + // Build the store with the library. + var store = await createAnalysisDriver().test.getSummaryStore(a1); + expect(store.unlinkedMap.keys, contains(a1UriStr)); + expect(store.unlinkedMap.keys, contains(a2UriStr)); + expect(store.linkedMap.keys, contains(a1UriStr)); + + var driver = createAnalysisDriver(externalSummaries: store); + var libraryElement = await driver.getLibraryByUri(a1UriStr); + var classA = libraryElement.library.getType('A'); + + { + var parsedLibrary = driver.getParsedLibraryByUri(a1Uri); + expect(parsedLibrary, isNotNull); + expect(parsedLibrary.state, ResultState.NOT_A_FILE); + expect(() { + parsedLibrary.getElementDeclaration(classA); + }, throwsStateError); + } + + // We can also get the result from the session. + { + var session = driver.currentSession; + var parsedLibrary = session.getParsedLibraryByElement(libraryElement); + expect(parsedLibrary, isNotNull); + expect(parsedLibrary.state, ResultState.NOT_A_FILE); + expect(() { + parsedLibrary.getElementDeclaration(classA); + }, throwsStateError); + } + + // It is an error to ask for a library when we know that it is a part. + expect(() { + driver.getParsedLibraryByUri(a2Uri); + }, throwsArgumentError); + } + + test_getResolvedLibrary_external() async { + var a1 = convertPath('/aaa/lib/a1.dart'); + var a2 = convertPath('/aaa/lib/a2.dart'); + + var a1UriStr = 'package:aaa/a1.dart'; + var a2UriStr = 'package:aaa/a2.dart'; + + newFile(a1, content: "part 'a2.dart'; class A {}"); + newFile(a2, content: "part of 'a1.dart';"); // Build the store with the library. var store = await createAnalysisDriver().test.getSummaryStore(a1); @@ -1595,7 +1628,7 @@ var resolvedLibrary = await driver.getResolvedLibrary(a1); expect(resolvedLibrary, isNotNull); - expect(resolvedLibrary.state, results.ResultState.NOT_A_FILE); + expect(resolvedLibrary.state, ResultState.NOT_A_FILE); expect(() { resolvedLibrary.getElementDeclaration(classA); }, throwsStateError); @@ -1607,8 +1640,8 @@ } test_getResolvedLibraryByUri_external() async { - var a1 = _p('/aaa/lib/a1.dart'); - var a2 = _p('/aaa/lib/a2.dart'); + var a1 = convertPath('/aaa/lib/a1.dart'); + var a2 = convertPath('/aaa/lib/a2.dart'); var a1UriStr = 'package:aaa/a1.dart'; var a2UriStr = 'package:aaa/a2.dart'; @@ -1616,8 +1649,8 @@ var a1Uri = Uri.parse(a1UriStr); var a2Uri = Uri.parse(a2UriStr); - provider.newFile(a1, "part 'a2.dart'; class A {}"); - provider.newFile(a2, "part of 'a1.dart';"); + newFile(a1, content: "part 'a2.dart'; class A {}"); + newFile(a2, content: "part of 'a1.dart';"); // Build the store with the library. var store = await createAnalysisDriver().test.getSummaryStore(a1); @@ -1632,7 +1665,7 @@ { var resolvedLibrary = await driver.getResolvedLibraryByUri(a1Uri); expect(resolvedLibrary, isNotNull); - expect(resolvedLibrary.state, results.ResultState.NOT_A_FILE); + expect(resolvedLibrary.state, ResultState.NOT_A_FILE); expect(() { resolvedLibrary.getElementDeclaration(classA); }, throwsStateError); @@ -1644,7 +1677,7 @@ var resolvedLibrary = await session.getResolvedLibraryByElement(libraryElement); expect(resolvedLibrary, isNotNull); - expect(resolvedLibrary.state, results.ResultState.NOT_A_FILE); + expect(resolvedLibrary.state, ResultState.NOT_A_FILE); expect(() { resolvedLibrary.getElementDeclaration(classA); }, throwsStateError); @@ -1660,10 +1693,10 @@ String content = 'int f() => 42;'; addTestFile(content, priority: true); - AnalysisResult result = await driver.getResult(testFile); + ResolvedUnitResult result = await driver.getResult(testFile); expect(result.path, testFile); expect(result.uri.toString(), 'package:test/test.dart'); - expect(result.exists, isTrue); + expect(result.state, ResultState.VALID); expect(result.content, content); expect(result.unit, isNotNull); expect(result.errors, hasLength(0)); @@ -1678,10 +1711,10 @@ } test_getResult_constants_defaultParameterValue_localFunction() async { - var a = _p('/test/bin/a.dart'); - var b = _p('/test/bin/b.dart'); - provider.newFile(a, 'const C = 42;'); - provider.newFile(b, r''' + var a = convertPath('/test/bin/a.dart'); + var b = convertPath('/test/bin/b.dart'); + newFile(a, content: 'const C = 42;'); + newFile(b, content: r''' import 'a.dart'; main() { foo({int p: C}) {} @@ -1692,17 +1725,17 @@ driver.addFile(b); await waitForIdleWithoutExceptions(); - AnalysisResult result = await driver.getResult(b); + ResolvedUnitResult result = await driver.getResult(b); expect(result.errors, isEmpty); } test_getResult_doesNotExist() async { - var a = _p('/test/lib/a.dart'); + var a = convertPath('/test/lib/a.dart'); - AnalysisResult result = await driver.getResult(a); + ResolvedUnitResult result = await driver.getResult(a); expect(result.path, a); expect(result.uri.toString(), 'package:test/a.dart'); - expect(result.exists, isFalse); + expect(result.state, ResultState.NOT_A_FILE); expect(result.content, ''); } @@ -1710,7 +1743,7 @@ String content = 'main() { int vv; }'; addTestFile(content, priority: true); - AnalysisResult result = await driver.getResult(testFile); + ResolvedUnitResult result = await driver.getResult(testFile); expect(result.path, testFile); expect(result.errors, hasLength(1)); { @@ -1723,23 +1756,6 @@ } } - test_getResult_fileContentOverlay_throughAnalysisContext() async { - var a = _p('/test/bin/a.dart'); - var b = _p('/test/bin/b.dart'); - - provider.newFile(a, 'import "b.dart";'); - provider.newFile(b, 'var v = 1;'); - contentOverlay[b] = 'var v = 2;'; - - var result = await driver.getResult(a); - - // The content that was set into the overlay for "b" should be visible - // through the AnalysisContext that was used to analyze "a". - CompilationUnitElement unitA = result.unit.declaredElement; - Source sourceB = unitA.library.imports[0].importedLibrary.source; - expect(unitA.context.getContents(sourceB).data, 'var v = 2;'); - } - test_getResult_functionTypeFormalParameter_withTypeParameter() async { // This was code crashing because of incomplete implementation. // Consider (re)moving after fixing dartbug.com/28515 @@ -1750,7 +1766,7 @@ class B {} '''); - AnalysisResult result = await driver.getResult(testFile); + ResolvedUnitResult result = await driver.getResult(testFile); expect(result.path, testFile); } @@ -1767,10 +1783,10 @@ } test_getResult_importLibrary_thenRemoveIt() async { - var a = _p('/test/lib/a.dart'); - var b = _p('/test/lib/b.dart'); - provider.newFile(a, 'class A {}'); - provider.newFile(b, r''' + var a = convertPath('/test/lib/a.dart'); + var b = convertPath('/test/lib/b.dart'); + newFile(a, content: 'class A {}'); + newFile(b, content: r''' import 'a.dart'; class B extends A {} '''); @@ -1781,17 +1797,17 @@ // No errors in b.dart { - AnalysisResult result = await driver.getResult(b); + ResolvedUnitResult result = await driver.getResult(b); expect(result.errors, isEmpty); } // Remove a.dart and reanalyze. - provider.deleteFile(a); + deleteFile(a); driver.removeFile(a); // The unresolved URI error must be reported. { - AnalysisResult result = await driver.getResult(b); + ResolvedUnitResult result = await driver.getResult(b); expect( result.errors, contains(predicate((AnalysisError e) => @@ -1799,12 +1815,12 @@ } // Restore a.dart and reanalyze. - provider.newFile(a, 'class A {}'); + newFile(a, content: 'class A {}'); driver.addFile(a); // No errors in b.dart again. { - AnalysisResult result = await driver.getResult(b); + ResolvedUnitResult result = await driver.getResult(b); expect(result.errors, isEmpty); } } @@ -1817,7 +1833,7 @@ ''', priority: true); await waitForIdleWithoutExceptions(); - AnalysisResult result = await driver.getResult(testFile); + ResolvedUnitResult result = await driver.getResult(testFile); expect(_getClassFieldType(result.unit, 'C', 'f'), 'int'); } @@ -1832,7 +1848,7 @@ ''', priority: true); await waitForIdleWithoutExceptions(); - AnalysisResult result = await driver.getResult(testFile); + ResolvedUnitResult result = await driver.getResult(testFile); expect(_getClassMethodReturnType(result.unit, 'A', 'm'), 'int'); expect(_getClassMethodReturnType(result.unit, 'B', 'm'), 'int'); } @@ -1845,7 +1861,7 @@ class C {} ''', priority: true); - AnalysisResult result = await driver.getResult(testFile); + ResolvedUnitResult result = await driver.getResult(testFile); ClassDeclaration c = result.unit.declarations[1] as ClassDeclaration; Annotation a = c.metadata[0]; expect(a.name.name, 'fff'); @@ -1872,7 +1888,7 @@ '''; addTestFile(content); - AnalysisResult result = await driver.getResult(testFile); + ResolvedUnitResult result = await driver.getResult(testFile); expect(result.path, testFile); } @@ -1884,7 +1900,7 @@ '''; addTestFile(content, priority: true); - AnalysisResult result = await driver.getResult(testFile); + ResolvedUnitResult result = await driver.getResult(testFile); expect(result.path, testFile); // Has only exports for valid URIs. List<ExportElement> imports = resolutionMap @@ -1904,7 +1920,7 @@ '''; addTestFile(content, priority: true); - AnalysisResult result = await driver.getResult(testFile); + ResolvedUnitResult result = await driver.getResult(testFile); expect(result.path, testFile); // Has only imports for valid URIs. List<ImportElement> imports = resolutionMap @@ -1932,23 +1948,23 @@ } test_getResult_mix_fileAndPackageUris() async { - var a = _p('/test/bin/a.dart'); - var b = _p('/test/bin/b.dart'); - var c = _p('/test/lib/c.dart'); - var d = _p('/test/test/d.dart'); - provider.newFile(a, r''' + var a = convertPath('/test/bin/a.dart'); + var b = convertPath('/test/bin/b.dart'); + var c = convertPath('/test/lib/c.dart'); + var d = convertPath('/test/test/d.dart'); + newFile(a, content: r''' import 'package:test/c.dart'; int x = y; '''); - provider.newFile(b, r''' + newFile(b, content: r''' import '../lib/c.dart'; int x = y; '''); - provider.newFile(c, r''' + newFile(c, content: r''' import '../test/d.dart'; var y = z; '''); - provider.newFile(d, r''' + newFile(d, content: r''' String z = "string"; '''); @@ -1962,7 +1978,7 @@ // package:my_pkg/c.dart's import is erroneous, causing y's reference to z // to be unresolved (and therefore have type dynamic). { - AnalysisResult result = await driver.getResult(a); + ResolvedUnitResult result = await driver.getResult(a); expect(result.errors, isEmpty); } @@ -1972,7 +1988,7 @@ // successfully imports file:///my_pkg/test/d.dart, causing y to have an // inferred type of String. { - AnalysisResult result = await driver.getResult(b); + ResolvedUnitResult result = await driver.getResult(b); List<AnalysisError> errors = result.errors; expect(errors, hasLength(1)); expect(errors[0].errorCode, StaticTypeWarningCode.INVALID_ASSIGNMENT); @@ -2011,10 +2027,10 @@ } test_getResult_notDartFile() async { - var path = _p('/test/lib/test.txt'); - provider.newFile(path, 'class A {}'); + var path = convertPath('/test/lib/test.txt'); + newFile(path, content: 'class A {}'); - AnalysisResult result = await driver.getResult(path); + ResolvedUnitResult result = await driver.getResult(path); expect(result, isNotNull); expect(result.unit.declaredElement.types.map((e) => e.name), ['A']); } @@ -2030,15 +2046,15 @@ } test_getResult_sameFile_twoUris() async { - var a = _p('/test/lib/a.dart'); - var b = _p('/test/lib/b.dart'); - var c = _p('/test/test/c.dart'); - provider.newFile(a, 'class A<T> {}'); - provider.newFile(b, r''' + var a = convertPath('/test/lib/a.dart'); + var b = convertPath('/test/lib/b.dart'); + var c = convertPath('/test/test/c.dart'); + newFile(a, content: 'class A<T> {}'); + newFile(b, content: r''' import 'a.dart'; var VB = new A<int>(); '''); - provider.newFile(c, r''' + newFile(c, content: r''' import '../lib/a.dart'; var VC = new A<double>(); '''); @@ -2048,29 +2064,31 @@ await waitForIdleWithoutExceptions(); { - AnalysisResult result = await driver.getResult(b); + ResolvedUnitResult result = await driver.getResult(b); expect(_getImportSource(result.unit, 0).uri.toString(), 'package:test/a.dart'); expect(_getTopLevelVarType(result.unit, 'VB'), 'A<int>'); } { - AnalysisResult result = await driver.getResult(c); - expect(_getImportSource(result.unit, 0).uri, - provider.pathContext.toUri(_p('/test/lib/a.dart'))); + ResolvedUnitResult result = await driver.getResult(c); + expect( + _getImportSource(result.unit, 0).uri, + toUri(convertPath('/test/lib/a.dart')), + ); expect(_getTopLevelVarType(result.unit, 'VC'), 'A<double>'); } } test_getResult_selfConsistent() async { - var a = _p('/test/lib/a.dart'); - var b = _p('/test/lib/b.dart'); - provider.newFile(a, r''' + var a = convertPath('/test/lib/a.dart'); + var b = convertPath('/test/lib/b.dart'); + newFile(a, content: r''' import 'b.dart'; var A1 = 1; var A2 = B1; '''); - provider.newFile(b, r''' + newFile(b, content: r''' import 'a.dart'; var B1 = A1; '''); @@ -2080,7 +2098,7 @@ await waitForIdleWithoutExceptions(); { - AnalysisResult result = await driver.getResult(a); + ResolvedUnitResult result = await driver.getResult(a); expect(_getTopLevelVarType(result.unit, 'A1'), 'int'); expect(_getTopLevelVarType(result.unit, 'A2'), 'int'); } @@ -2092,7 +2110,7 @@ // That's because we check for "a" API signature consistency, and because // it has changed, we invalidated the dependency cache, relinked libraries // and recomputed types. - provider.updateFile(a, r''' + modifyFile(a, r''' import 'b.dart'; var A1 = 1.2; var A2 = B1; @@ -2100,7 +2118,7 @@ driver.changeFile(a); { - AnalysisResult result = await driver.getResult(a); + ResolvedUnitResult result = await driver.getResult(a); expect(_getTopLevelVarType(result.unit, 'A1'), 'double'); expect(_getTopLevelVarType(result.unit, 'A2'), 'double'); } @@ -2109,10 +2127,10 @@ test_getResult_thenRemove() async { addTestFile('main() {}', priority: true); - Future<AnalysisResult> resultFuture = driver.getResult(testFile); + Future<ResolvedUnitResult> resultFuture = driver.getResult(testFile); driver.removeFile(testFile); - AnalysisResult result = await resultFuture; + ResolvedUnitResult result = await resultFuture; expect(result, isNotNull); expect(result.path, testFile); expect(result.unit, isNotNull); @@ -2122,20 +2140,20 @@ String content = 'main() {}'; addTestFile(content, priority: true); - Future<AnalysisResult> future1 = driver.getResult(testFile); - Future<AnalysisResult> future2 = driver.getResult(testFile); + Future<ResolvedUnitResult> future1 = driver.getResult(testFile); + Future<ResolvedUnitResult> future2 = driver.getResult(testFile); // Both futures complete, with the same result. - AnalysisResult result1 = await future1; - AnalysisResult result2 = await future2; + ResolvedUnitResult result1 = await future1; + ResolvedUnitResult result2 = await future2; expect(result2, same(result1)); expect(result1.path, testFile); expect(result1.unit, isNotNull); } test_getSourceKind_library() async { - var path = _p('/test/lib/test.dart'); - provider.newFile(path, 'class A {}'); + var path = convertPath('/test/lib/test.dart'); + newFile(path, content: 'class A {}'); expect(await driver.getSourceKind(path), SourceKind.LIBRARY); } @@ -2147,27 +2165,27 @@ } test_getSourceKind_notDartFile() async { - var path = _p('/test/lib/test.txt'); - provider.newFile(path, 'class A {}'); + var path = convertPath('/test/lib/test.txt'); + newFile(path, content: 'class A {}'); expect(await driver.getSourceKind(path), isNull); } test_getSourceKind_part() async { - var path = _p('/test/lib/test.dart'); - provider.newFile(path, 'part of lib; class A {}'); + var path = convertPath('/test/lib/test.dart'); + newFile(path, content: 'part of lib; class A {}'); expect(await driver.getSourceKind(path), SourceKind.PART); } test_getTopLevelNameDeclarations() async { - var a = _p('/test/lib/a.dart'); - var b = _p('/test/lib/b.dart'); - var c = _p('/test/lib/c.dart'); - var d = _p('/test/lib/d.dart'); + var a = convertPath('/test/lib/a.dart'); + var b = convertPath('/test/lib/b.dart'); + var c = convertPath('/test/lib/c.dart'); + var d = convertPath('/test/lib/d.dart'); - provider.newFile(a, 'class A {}'); - provider.newFile(b, 'export "a.dart"; class B {}'); - provider.newFile(c, 'import "d.dart"; class C {}'); - provider.newFile(d, 'class D {}'); + newFile(a, content: 'class A {}'); + newFile(b, content: 'export "a.dart"; class B {}'); + newFile(c, content: 'import "d.dart"; class C {}'); + newFile(d, content: 'class D {}'); driver.addFile(a); driver.addFile(b); @@ -2191,17 +2209,17 @@ } test_getTopLevelNameDeclarations_discover() async { - var t = _p('/test/lib/test.dart'); - var a1 = _p('/aaa/lib/a1.dart'); - var a2 = _p('/aaa/lib/src/a2.dart'); - var b = _p('/bbb/lib/b.dart'); - var c = _p('/ccc/lib/c.dart'); + var t = convertPath('/test/lib/test.dart'); + var a1 = convertPath('/aaa/lib/a1.dart'); + var a2 = convertPath('/aaa/lib/src/a2.dart'); + var b = convertPath('/bbb/lib/b.dart'); + var c = convertPath('/ccc/lib/c.dart'); - provider.newFile(t, 'class T {}'); - provider.newFile(a1, 'class A1 {}'); - provider.newFile(a2, 'class A2 {}'); - provider.newFile(b, 'class B {}'); - provider.newFile(c, 'class C {}'); + newFile(t, content: 'class T {}'); + newFile(a1, content: 'class A1 {}'); + newFile(a2, content: 'class A2 {}'); + newFile(b, content: 'class B {}'); + newFile(c, content: 'class C {}'); driver.addFile(t); // Don't add a1.dart, a2.dart, or b.dart - they should be discovered. @@ -2224,18 +2242,18 @@ } test_getTopLevelNameDeclarations_parts() async { - var a = _p('/test/lib/a.dart'); - var b = _p('/test/lib/b.dart'); - var c = _p('/test/lib/c.dart'); + var a = convertPath('/test/lib/a.dart'); + var b = convertPath('/test/lib/b.dart'); + var c = convertPath('/test/lib/c.dart'); - provider.newFile(a, r''' + newFile(a, content: r''' library lib; part 'b.dart'; part 'c.dart'; class A {} '''); - provider.newFile(b, 'part of lib; class B {}'); - provider.newFile(c, 'part of lib; class C {}'); + newFile(b, content: 'part of lib; class B {}'); + newFile(c, content: 'part of lib; class C {}'); driver.addFile(a); driver.addFile(b); @@ -2279,17 +2297,17 @@ } test_getUnitElement_notDart() async { - var path = _p('/test.txt'); - provider.newFile(path, 'class A {}'); + var path = convertPath('/test.txt'); + newFile(path, content: 'class A {}'); UnitElementResult unitResult = await driver.getUnitElement(path); expect(unitResult, isNotNull); expect(unitResult.element.types.map((e) => e.name), ['A']); } test_getUnitElementSignature() async { - var a = _p('/test/lib/a.dart'); + var a = convertPath('/test/lib/a.dart'); - provider.newFile(a, 'foo() {}'); + newFile(a, content: 'foo() {}'); String signature = await driver.getUnitElementSignature(a); expect(signature, isNotNull); @@ -2298,7 +2316,7 @@ expect(unitResult.path, a); expect(unitResult.signature, signature); - provider.updateFile(a, 'bar() {}'); + modifyFile(a, 'bar() {}'); driver.changeFile(a); String signature2 = await driver.getUnitElementSignature(a); @@ -2307,11 +2325,19 @@ } test_hasFilesToAnalyze() async { + var a = convertPath('/test/lib/a.dart'); + var b = convertPath('/test/lib/b.dart'); + var c = convertPath('/test/lib/c.dart'); + // No files yet, nothing to analyze. expect(driver.hasFilesToAnalyze, isFalse); // Add a new file, it should be analyzed. - addTestFile('main() {}', priority: false); + newFile(a, content: r''' +import 'b.dart'; +main() {} +'''); + driver.addFile(a); expect(driver.hasFilesToAnalyze, isTrue); // Wait for idle, nothing to do. @@ -2319,36 +2345,42 @@ expect(driver.hasFilesToAnalyze, isFalse); // Ask to analyze the file, so there is a file to analyze. - Future<AnalysisResult> future = driver.getResult(testFile); + Future<ResolvedUnitResult> future = driver.getResult(a); expect(driver.hasFilesToAnalyze, isTrue); // Once analysis is done, there is nothing to analyze. await future; expect(driver.hasFilesToAnalyze, isFalse); - // Change a file, even if not added, it still might affect analysis. - driver.changeFile(_p('/not/added.dart')); + // Change a file that is not added, but referenced, so known. + driver.changeFile(b); expect(driver.hasFilesToAnalyze, isTrue); await waitForIdleWithoutExceptions(); expect(driver.hasFilesToAnalyze, isFalse); + // Change a file that is not known - neither added, nor referenced. + driver.changeFile(c); + expect(driver.hasFilesToAnalyze, isFalse); + await waitForIdleWithoutExceptions(); + expect(driver.hasFilesToAnalyze, isFalse); + // Request of referenced names is not analysis of a file. driver.getFilesReferencingName('X'); expect(driver.hasFilesToAnalyze, isFalse); } test_hermetic_modifyLibraryFile_resolvePart() async { - var a = _p('/test/lib/a.dart'); - var b = _p('/test/lib/b.dart'); + var a = convertPath('/test/lib/a.dart'); + var b = convertPath('/test/lib/b.dart'); - provider.newFile(a, r''' + newFile(a, content: r''' library a; part 'b.dart'; class C { int foo; } '''); - provider.newFile(b, r''' + newFile(b, content: r''' part of a; var c = new C(); '''); @@ -2360,7 +2392,7 @@ // Modify the library, but don't notify the driver. // The driver should use the previous library content and elements. - provider.newFile(a, r''' + newFile(a, content: r''' library a; part 'b.dart'; class C { @@ -2377,8 +2409,8 @@ } test_hermetic_overlayOnly_part() async { - var a = _p('/test/lib/a.dart'); - var b = _p('/test/lib/b.dart'); + var a = convertPath('/test/lib/a.dart'); + var b = convertPath('/test/lib/b.dart'); contentOverlay[a] = r''' library a; part 'b.dart'; @@ -2390,14 +2422,14 @@ driver.addFile(a); driver.addFile(b); - AnalysisResult result = await driver.getResult(a); + ResolvedUnitResult result = await driver.getResult(a); expect(result.errors, isEmpty); expect(_getTopLevelVarType(result.unit, 'b'), 'B'); } test_instantiateToBounds_invalid() async { - var a = _p('/test/lib/a.dart'); - provider.newFile(a, r''' + var a = convertPath('/test/lib/a.dart'); + newFile(a, content: r''' class A<T extends B> {} class B<T extends A<B>> {} '''); @@ -2407,30 +2439,31 @@ } test_isLibraryByUri() async { - var a1 = _p('/aaa/lib/a1.dart'); - var a2 = _p('/aaa/lib/a2.dart'); - var b1 = _p('/bbb/lib/b1.dart'); - var b2 = _p('/bbb/lib/b2.dart'); + var a1 = '/aaa/lib/a1.dart'; + var a2 = '/aaa/lib/a2.dart'; + var b1 = '/bbb/lib/b1.dart'; + var b2 = '/bbb/lib/b2.dart'; String a1UriStr = 'package:aaa/a1.dart'; String a2UriStr = 'package:aaa/a2.dart'; String b1UriStr = 'package:bbb/b1.dart'; String b2UriStr = 'package:bbb/b2.dart'; - provider.newFile(a1, "part 'a2.dart';"); - provider.newFile(a2, "part of 'a1.dart';"); - provider.newFile(b1, "part 'b2.dart';"); - provider.newFile(b2, "part of 'b1.dart';"); + newFile(a1, content: "part 'a2.dart';"); + newFile(a2, content: "part of 'a1.dart';"); + newFile(b1, content: "part 'b2.dart';"); + newFile(b2, content: "part of 'b1.dart';"); // Build the store with the library. - var store = await createAnalysisDriver().test.getSummaryStore(a1); + var store = + await createAnalysisDriver().test.getSummaryStore(convertPath(a1)); expect(store.unlinkedMap.keys, contains(a1UriStr)); expect(store.unlinkedMap.keys, contains(a2UriStr)); expect(store.linkedMap.keys, contains(a1UriStr)); // Remove the stored files from the file system. - provider.deleteFile(a1); - provider.deleteFile(a2); + deleteFile(a1); + deleteFile(a2); // We can ask isLibraryByUri() for both external and local units. AnalysisDriver driver = createAnalysisDriver(externalSummaries: store); @@ -2451,8 +2484,8 @@ } test_issue34619() async { - var a = _p('/test/lib/a.dart'); - provider.newFile(a, r''' + var a = convertPath('/test/lib/a.dart'); + newFile(a, content: r''' class C { final Set<String> f = new Set<String>(); @@ -2465,7 +2498,7 @@ await waitForIdleWithoutExceptions(); // Update the file in a - provider.updateFile(a, r''' + modifyFile(a, r''' class C { final Set<String> f = a + b + c; @@ -2478,15 +2511,15 @@ } test_knownFiles() async { - var a = _p('/test/lib/a.dart'); - var b = _p('/test/lib/b.dart'); - var c = _p('/test/lib/c.dart'); + var a = convertPath('/test/lib/a.dart'); + var b = convertPath('/test/lib/b.dart'); + var c = convertPath('/test/lib/c.dart'); - provider.newFile(a, r''' + newFile(a, content: r''' import 'b.dart'; '''); - provider.newFile(b, ''); - provider.newFile(c, ''); + newFile(b); + newFile(c); driver.addFile(a); driver.addFile(c); @@ -2506,10 +2539,10 @@ } test_knownFiles_beforeAnalysis() async { - var a = _p('/test/lib/a.dart'); - var b = _p('/test/lib/b.dart'); + var a = convertPath('/test/lib/a.dart'); + var b = convertPath('/test/lib/b.dart'); - provider.newFile(a, ''); + newFile(a); // 'a.dart' is added, but not processed yet. // So, the set of known files is empty yet. @@ -2526,7 +2559,7 @@ test_missingDartLibrary_async() async { var asyncPath = sdk.mapDartUri('dart:async').fullName; - provider.getFile(asyncPath).delete(); + getFile(asyncPath).delete(); addTestFile('class C {}'); ErrorsResult result = await driver.getErrors(testFile); @@ -2538,7 +2571,7 @@ test_missingDartLibrary_core() async { var corePath = sdk.mapDartUri('dart:core').fullName; - provider.getFile(corePath).delete(); + getFile(corePath).delete(); addTestFile('class C {}'); ErrorsResult result = await driver.getErrors(testFile); @@ -2556,27 +2589,27 @@ } test_parseFile_notDart() async { - var p = _p('/test/bin/a.txt'); - provider.newFile(p, 'class A {}'); + var p = convertPath('/test/bin/a.txt'); + newFile(p, content: 'class A {}'); - ParseResult parseResult = await driver.parseFile(p); + ParsedUnitResult parseResult = await driver.parseFile(p); expect(parseResult, isNotNull); expect(driver.knownFiles, contains(p)); } test_parseFile_shouldRefresh() async { - var p = _p('/test/bin/a.dart'); + var p = convertPath('/test/bin/a.dart'); - provider.newFile(p, 'class A {}'); + newFile(p, content: 'class A {}'); driver.addFile(p); // Get the result, so force the file reading. await driver.getResult(p); // Update the file. - provider.newFile(p, 'class A2 {}'); + newFile(p, content: 'class A2 {}'); - ParseResult parseResult = await driver.parseFile(p); + ParsedUnitResult parseResult = await driver.parseFile(p); var clazz = parseResult.unit.declarations[0] as ClassDeclaration; expect(clazz.name.name, 'A2'); } @@ -2589,44 +2622,44 @@ } test_parseFileSync_notDart() { - var p = _p('/test/bin/a.txt'); - provider.newFile(p, 'class A {}'); + var p = convertPath('/test/bin/a.txt'); + newFile(p, content: 'class A {}'); - ParseResult parseResult = driver.parseFileSync(p); + ParsedUnitResult parseResult = driver.parseFileSync(p); expect(parseResult, isNotNull); expect(driver.knownFiles, contains(p)); } test_parseFileSync_shouldRefresh() async { - var p = _p('/test/bin/a.dart'); + var p = convertPath('/test/bin/a.dart'); - provider.newFile(p, 'class A {}'); + newFile(p, content: 'class A {}'); driver.addFile(p); // Get the result, so force the file reading. await driver.getResult(p); // Update the file. - provider.newFile(p, 'class A2 {}'); + newFile(p, content: 'class A2 {}'); - ParseResult parseResult = driver.parseFileSync(p); + ParsedUnitResult parseResult = driver.parseFileSync(p); var clazz = parseResult.unit.declarations[0] as ClassDeclaration; expect(clazz.name.name, 'A2'); } test_part_getErrors_afterLibrary() async { - var a = _p('/test/lib/a.dart'); - var b = _p('/test/lib/b.dart'); - var c = _p('/test/lib/c.dart'); - provider.newFile(a, r''' + var a = convertPath('/test/lib/a.dart'); + var b = convertPath('/test/lib/b.dart'); + var c = convertPath('/test/lib/c.dart'); + newFile(a, content: r''' library a; import 'b.dart'; part 'c.dart'; class A {} var c = new C(); '''); - provider.newFile(b, 'class B {}'); - provider.newFile(c, r''' + newFile(b, content: 'class B {}'); + newFile(c, content: r''' part of a; class C {} var a = new A(); @@ -2651,18 +2684,18 @@ } test_part_getErrors_beforeLibrary() async { - var a = _p('/test/lib/a.dart'); - var b = _p('/test/lib/b.dart'); - var c = _p('/test/lib/c.dart'); - provider.newFile(a, r''' + var a = convertPath('/test/lib/a.dart'); + var b = convertPath('/test/lib/b.dart'); + var c = convertPath('/test/lib/c.dart'); + newFile(a, content: r''' library a; import 'b.dart'; part 'c.dart'; class A {} var c = new C(); '''); - provider.newFile(b, 'class B {}'); - provider.newFile(c, r''' + newFile(b, content: 'class B {}'); + newFile(c, content: r''' part of a; class C {} var a = new A(); @@ -2681,18 +2714,18 @@ } test_part_getResult_afterLibrary() async { - var a = _p('/test/lib/a.dart'); - var b = _p('/test/lib/b.dart'); - var c = _p('/test/lib/c.dart'); - provider.newFile(a, r''' + var a = convertPath('/test/lib/a.dart'); + var b = convertPath('/test/lib/b.dart'); + var c = convertPath('/test/lib/c.dart'); + newFile(a, content: r''' library a; import 'b.dart'; part 'c.dart'; class A {} var c = new C(); '''); - provider.newFile(b, 'class B {}'); - provider.newFile(c, r''' + newFile(b, content: 'class B {}'); + newFile(c, content: r''' part of a; class C {} var a = new A(); @@ -2705,14 +2738,14 @@ // Process a.dart so that we know that it's a library for c.dart later. { - AnalysisResult result = await driver.getResult(a); + ResolvedUnitResult result = await driver.getResult(a); expect(result.errors, isEmpty); expect(_getTopLevelVarType(result.unit, 'c'), 'C'); } // Now c.dart can be resolved without errors in the context of a.dart { - AnalysisResult result = await driver.getResult(c); + ResolvedUnitResult result = await driver.getResult(c); expect(result.errors, isEmpty); expect(_getTopLevelVarType(result.unit, 'a'), 'A'); expect(_getTopLevelVarType(result.unit, 'b'), 'B'); @@ -2720,18 +2753,18 @@ } test_part_getResult_beforeLibrary() async { - var a = _p('/test/lib/a.dart'); - var b = _p('/test/lib/b.dart'); - var c = _p('/test/lib/c.dart'); - provider.newFile(a, r''' + var a = convertPath('/test/lib/a.dart'); + var b = convertPath('/test/lib/b.dart'); + var c = convertPath('/test/lib/c.dart'); + newFile(a, content: r''' library a; import 'b.dart'; part 'c.dart'; class A {} var c = new C(); '''); - provider.newFile(b, 'class B {}'); - provider.newFile(c, r''' + newFile(b, content: 'class B {}'); + newFile(c, content: r''' part of a; class C {} var a = new A(); @@ -2744,15 +2777,15 @@ // b.dart will be analyzed after a.dart is analyzed. // So, A and B references are resolved. - AnalysisResult result = await driver.getResult(c); + ResolvedUnitResult result = await driver.getResult(c); expect(result.errors, isEmpty); expect(_getTopLevelVarType(result.unit, 'a'), 'A'); expect(_getTopLevelVarType(result.unit, 'b'), 'B'); } test_part_getResult_noLibrary() async { - var c = _p('/test/lib/c.dart'); - provider.newFile(c, r''' + var c = convertPath('/test/lib/c.dart'); + newFile(c, content: r''' part of a; class C {} var a = new A(); @@ -2763,24 +2796,24 @@ // There is no library which c.dart is a part of, so it has unresolved // A and B references. - AnalysisResult result = await driver.getResult(c); + ResolvedUnitResult result = await driver.getResult(c); expect(result.errors, isNotEmpty); expect(result.unit, isNotNull); } test_part_getUnitElement_afterLibrary() async { - var a = _p('/test/lib/a.dart'); - var b = _p('/test/lib/b.dart'); - var c = _p('/test/lib/c.dart'); - provider.newFile(a, r''' + var a = convertPath('/test/lib/a.dart'); + var b = convertPath('/test/lib/b.dart'); + var c = convertPath('/test/lib/c.dart'); + newFile(a, content: r''' library a; import 'b.dart'; part 'c.dart'; class A {} var c = new C(); '''); - provider.newFile(b, 'class B {}'); - provider.newFile(c, r''' + newFile(b, content: 'class B {}'); + newFile(c, content: r''' part of a; class C {} var a = new A(); @@ -2808,18 +2841,18 @@ } test_part_getUnitElement_beforeLibrary() async { - var a = _p('/test/lib/a.dart'); - var b = _p('/test/lib/b.dart'); - var c = _p('/test/lib/c.dart'); - provider.newFile(a, r''' + var a = convertPath('/test/lib/a.dart'); + var b = convertPath('/test/lib/b.dart'); + var c = convertPath('/test/lib/c.dart'); + newFile(a, content: r''' library a; import 'b.dart'; part 'c.dart'; class A {} var c = new C(); '''); - provider.newFile(b, 'class B {}'); - provider.newFile(c, r''' + newFile(b, content: 'class B {}'); + newFile(c, content: r''' part of a; class C {} var a = new A(); @@ -2844,8 +2877,8 @@ } test_part_getUnitElement_noLibrary() async { - var c = _p('/test/lib/c.dart'); - provider.newFile(c, r''' + var c = convertPath('/test/lib/c.dart'); + newFile(c, content: r''' part of a; var a = new A(); var b = new B(); @@ -2868,18 +2901,18 @@ } test_part_getUnitElementSignature() async { - var a = _p('/test/lib/a.dart'); - var b = _p('/test/lib/b.dart'); - var c = _p('/test/lib/c.dart'); - provider.newFile(a, r''' + var a = convertPath('/test/lib/a.dart'); + var b = convertPath('/test/lib/b.dart'); + var c = convertPath('/test/lib/c.dart'); + newFile(a, content: r''' library a; import 'b.dart'; part 'c.dart'; class A {} var c = new C(); '''); - provider.newFile(b, 'class B {}'); - provider.newFile(c, r''' + newFile(b, content: 'class B {}'); + newFile(c, content: r''' part of a; class C {} var a = new A(); @@ -2902,18 +2935,18 @@ } test_part_results_afterLibrary() async { - var a = _p('/test/lib/a.dart'); - var b = _p('/test/lib/b.dart'); - var c = _p('/test/lib/c.dart'); - provider.newFile(a, r''' + var a = convertPath('/test/lib/a.dart'); + var b = convertPath('/test/lib/b.dart'); + var c = convertPath('/test/lib/c.dart'); + newFile(a, content: r''' library a; import 'b.dart'; part 'c.dart'; class A {} var c = new C(); '''); - provider.newFile(b, 'class B {}'); - provider.newFile(c, r''' + newFile(b, content: 'class B {}'); + newFile(c, content: r''' part of a; class C {} var a = new A(); @@ -2930,38 +2963,38 @@ // c.dart was added after a.dart, so it is analyzed after a.dart, // so we know that a.dart is the library of c.dart, so no errors. - AnalysisResult result = allResults.lastWhere((r) => r.path == c); + ResolvedUnitResult result = allResults.lastWhere((r) => r.path == c); expect(result.errors, isEmpty); expect(result.unit, isNull); } // Update a.dart so that c.dart is not a part. { - provider.updateFile(a, '// does not use c.dart anymore'); + modifyFile(a, '// does not use c.dart anymore'); driver.changeFile(a); await waitForIdleWithoutExceptions(); // Now c.dart does not have a library context, so A and B cannot be // resolved, so there are errors. - AnalysisResult result = allResults.lastWhere((r) => r.path == c); + ResolvedUnitResult result = allResults.lastWhere((r) => r.path == c); expect(result.errors, isNotEmpty); expect(result.unit, isNull); } } test_part_results_beforeLibrary() async { - var a = _p('/test/lib/a.dart'); - var b = _p('/test/lib/b.dart'); - var c = _p('/test/lib/c.dart'); - provider.newFile(a, r''' + var a = convertPath('/test/lib/a.dart'); + var b = convertPath('/test/lib/b.dart'); + var c = convertPath('/test/lib/c.dart'); + newFile(a, content: r''' library a; import 'b.dart'; part 'c.dart'; class A {} var c = new C(); '''); - provider.newFile(b, 'class B {}'); - provider.newFile(c, r''' + newFile(b, content: 'class B {}'); + newFile(c, content: r''' part of a; class C {} var a = new A(); @@ -2979,14 +3012,14 @@ // a.dart, but we cannot find the library for it, so we delay analysis // until all other files are analyzed, including a.dart, after which we // analyze the delayed parts. - AnalysisResult result = allResults.lastWhere((r) => r.path == c); + ResolvedUnitResult result = allResults.lastWhere((r) => r.path == c); expect(result.errors, isEmpty); expect(result.unit, isNull); } test_part_results_noLibrary() async { - var c = _p('/test/lib/c.dart'); - provider.newFile(c, r''' + var c = convertPath('/test/lib/c.dart'); + newFile(c, content: r''' part of a; class C {} var a = new A(); @@ -2999,24 +3032,24 @@ // There is no library which c.dart is a part of, so it has unresolved // A and B references. - AnalysisResult result = allResults.lastWhere((r) => r.path == c); + ResolvedUnitResult result = allResults.lastWhere((r) => r.path == c); expect(result.errors, isNotEmpty); expect(result.unit, isNull); } test_part_results_priority_beforeLibrary() async { - var a = _p('/test/lib/a.dart'); - var b = _p('/test/lib/b.dart'); - var c = _p('/test/lib/c.dart'); - provider.newFile(a, r''' + var a = convertPath('/test/lib/a.dart'); + var b = convertPath('/test/lib/b.dart'); + var c = convertPath('/test/lib/c.dart'); + newFile(a, content: r''' library a; import 'b.dart'; part 'c.dart'; class A {} var c = new C(); '''); - provider.newFile(b, 'class B {}'); - provider.newFile(c, r''' + newFile(b, content: 'class B {}'); + newFile(c, content: r''' part of a; class C {} var a = new A(); @@ -3035,19 +3068,19 @@ // a.dart, but we cannot find the library for it, so we delay analysis // until all other files are analyzed, including a.dart, after which we // analyze the delayed parts. - AnalysisResult result = allResults.lastWhere((r) => r.path == c); + ResolvedUnitResult result = allResults.lastWhere((r) => r.path == c); expect(result.errors, isEmpty); expect(result.unit, isNotNull); } test_removeFile_changeFile_implicitlyAnalyzed() async { - var a = _p('/test/lib/a.dart'); - var b = _p('/test/lib/b.dart'); - provider.newFile(a, r''' + var a = convertPath('/test/lib/a.dart'); + var b = convertPath('/test/lib/b.dart'); + newFile(a, content: r''' import 'b.dart'; var A = B; '''); - provider.newFile(b, 'var B = 1;'); + newFile(b, content: 'var B = 1;'); driver.priorityFiles = [a, b]; driver.addFile(a); @@ -3057,17 +3090,17 @@ await waitForIdleWithoutExceptions(); expect(allResults, hasLength(2)); { - AnalysisResult ar = allResults.firstWhere((r) => r.path == a); + ResolvedUnitResult ar = allResults.firstWhere((r) => r.path == a); expect(_getTopLevelVarType(ar.unit, 'A'), 'int'); } { - AnalysisResult br = allResults.firstWhere((r) => r.path == b); + ResolvedUnitResult br = allResults.firstWhere((r) => r.path == b); expect(_getTopLevelVarType(br.unit, 'B'), 'int'); } allResults.clear(); // Remove "b" and send the change notification. - provider.updateFile(b, 'var B = 1.2;'); + modifyFile(b, 'var B = 1.2;'); driver.removeFile(b); driver.changeFile(b); @@ -3077,7 +3110,7 @@ await waitForIdleWithoutExceptions(); expect(allResults, hasLength(1)); { - AnalysisResult ar = allResults.firstWhere((r) => r.path == a); + ResolvedUnitResult ar = allResults.firstWhere((r) => r.path == a); expect(_getTopLevelVarType(ar.unit, 'A'), 'double'); } } @@ -3102,11 +3135,11 @@ } test_removeFile_invalidate_importers() async { - var a = _p('/test/lib/a.dart'); - var b = _p('/test/lib/b.dart'); + var a = convertPath('/test/lib/a.dart'); + var b = convertPath('/test/lib/b.dart'); - provider.newFile(a, 'class A {}'); - provider.newFile(b, "import 'a.dart'; var a = new A();"); + newFile(a, content: 'class A {}'); + newFile(b, content: "import 'a.dart'; var a = new A();"); driver.addFile(a); driver.addFile(b); @@ -3117,7 +3150,7 @@ allResults.clear(); // Remove a.dart, now b.dart should be reanalyzed and has an error. - provider.deleteFile(a); + deleteFile(a); driver.removeFile(a); await waitForIdleWithoutExceptions(); expect(allResults.singleWhere((r) => r.path == b).errors, hasLength(2)); @@ -3132,26 +3165,26 @@ } test_results_order() async { - var a = _p('/test/lib/a.dart'); - var b = _p('/test/lib/b.dart'); - var c = _p('/test/lib/c.dart'); - var d = _p('/test/lib/d.dart'); - var e = _p('/test/lib/e.dart'); - var f = _p('/test/lib/f.dart'); - provider.newFile(a, r''' + var a = convertPath('/test/lib/a.dart'); + var b = convertPath('/test/lib/b.dart'); + var c = convertPath('/test/lib/c.dart'); + var d = convertPath('/test/lib/d.dart'); + var e = convertPath('/test/lib/e.dart'); + var f = convertPath('/test/lib/f.dart'); + newFile(a, content: r''' import 'd.dart'; '''); - provider.newFile(b, ''); - provider.newFile(c, r''' + newFile(b); + newFile(c, content: r''' import 'd.dart'; '''); - provider.newFile(d, r''' + newFile(d, content: r''' import 'b.dart'; '''); - provider.newFile(e, r''' + newFile(e, content: r''' export 'b.dart'; '''); - provider.newFile(f, r''' + newFile(f, content: r''' import 'e.dart'; class F extends X {} '''); @@ -3171,7 +3204,7 @@ allResults.clear(); // Update a.dart with changing its API signature. - provider.updateFile(b, 'class A {}'); + modifyFile(b, 'class A {}'); driver.changeFile(b); await waitForIdleWithoutExceptions(); @@ -3188,16 +3221,16 @@ } test_results_order_allChangedFirst_thenImports() async { - var a = _p('/test/lib/a.dart'); - var b = _p('/test/lib/b.dart'); - var c = _p('/test/lib/c.dart'); - var d = _p('/test/lib/d.dart'); - var e = _p('/test/lib/e.dart'); - provider.newFile(a, 'class A {}'); - provider.newFile(b, 'class B {}'); - provider.newFile(c, ''); - provider.newFile(d, "import 'a.dart';"); - provider.newFile(e, "import 'b.dart';"); + var a = convertPath('/test/lib/a.dart'); + var b = convertPath('/test/lib/b.dart'); + var c = convertPath('/test/lib/c.dart'); + var d = convertPath('/test/lib/d.dart'); + var e = convertPath('/test/lib/e.dart'); + newFile(a, content: 'class A {}'); + newFile(b, content: 'class B {}'); + newFile(c); + newFile(d, content: "import 'a.dart';"); + newFile(e, content: "import 'b.dart';"); driver.addFile(a); driver.addFile(b); @@ -3211,8 +3244,8 @@ // Change b.dart and then a.dart files. // So, a.dart and b.dart should be analyzed first. // Then d.dart and e.dart because they import a.dart and b.dart files. - provider.updateFile(a, 'class A2 {}'); - provider.updateFile(b, 'class B2 {}'); + modifyFile(a, 'class A2 {}'); + modifyFile(b, 'class B2 {}'); driver.changeFile(b); driver.changeFile(a); await waitForIdleWithoutExceptions(); @@ -3235,7 +3268,7 @@ await waitForIdleWithoutExceptions(); expect(allResults, hasLength(1)); - AnalysisResult result = allResults.single; + ResolvedUnitResult result = allResults.single; expect(result.path, testFile); expect(result.uri.toString(), 'package:test/test.dart'); expect(result.content, content); @@ -3248,12 +3281,12 @@ } test_results_priorityFirst() async { - var a = _p('/test/lib/a.dart'); - var b = _p('/test/lib/b.dart'); - var c = _p('/test/lib/c.dart'); - provider.newFile(a, 'class A {}'); - provider.newFile(b, 'class B {}'); - provider.newFile(c, 'class C {}'); + var a = convertPath('/test/lib/a.dart'); + var b = convertPath('/test/lib/b.dart'); + var c = convertPath('/test/lib/c.dart'); + newFile(a, content: 'class A {}'); + newFile(b, content: 'class B {}'); + newFile(c, content: 'class C {}'); driver.addFile(a); driver.addFile(b); @@ -3262,7 +3295,7 @@ await waitForIdleWithoutExceptions(); expect(allResults, hasLength(3)); - AnalysisResult result = allResults[0]; + ResolvedUnitResult result = allResults[0]; expect(result.path, b); expect(result.unit, isNotNull); expect(result.errors, hasLength(0)); @@ -3274,7 +3307,7 @@ await waitForIdleWithoutExceptions(); expect(allResults, hasLength(1)); - AnalysisResult result = allResults.single; + ResolvedUnitResult result = allResults.single; expect(result.path, testFile); expect(result.uri.toString(), 'package:test/test.dart'); expect(result.content, isNull); @@ -3283,10 +3316,10 @@ } test_results_skipNotAffected() async { - var a = _p('/test/lib/a.dart'); - var b = _p('/test/lib/b.dart'); - provider.newFile(a, 'class A {}'); - provider.newFile(b, 'class B {}'); + var a = convertPath('/test/lib/a.dart'); + var b = convertPath('/test/lib/b.dart'); + newFile(a, content: 'class A {}'); + newFile(b, content: 'class B {}'); driver.addFile(a); driver.addFile(b); @@ -3296,7 +3329,7 @@ allResults.clear(); // Update a.dart and notify. - provider.updateFile(a, 'class A2 {}'); + modifyFile(a, 'class A2 {}'); driver.changeFile(a); // Only result for a.dart should be produced, b.dart is not affected. @@ -3451,11 +3484,6 @@ .type .toString(); } - - /** - * Return the [provider] specific path for the given Posix [path]. - */ - String _p(String path) => provider.convertPath(path); } @reflectiveTest @@ -3463,31 +3491,31 @@ bool get disableChangesAndCacheAllResults => true; test_addFile() async { - var a = _p('/test/lib/a.dart'); - var b = _p('/test/lib/b.dart'); + var a = convertPath('/test/lib/a.dart'); + var b = convertPath('/test/lib/b.dart'); driver.addFile(a); driver.addFile(b); } test_changeFile() async { - var path = _p('/test.dart'); + var path = convertPath('/test.dart'); expect(() { driver.changeFile(path); }, throwsStateError); } test_getResult_libraryUnits() async { - var lib = _p('/lib.dart'); - var part1 = _p('/part1.dart'); - var part2 = _p('/part2.dart'); + var lib = convertPath('/lib.dart'); + var part1 = convertPath('/part1.dart'); + var part2 = convertPath('/part2.dart'); - provider.newFile(lib, r''' + newFile(lib, content: r''' library test; part 'part1.dart'; part 'part2.dart'; '''); - provider.newFile(part1, 'part of test; class A {}'); - provider.newFile(part2, 'part of test; class B {}'); + newFile(part1, content: 'part of test; class A {}'); + newFile(part2, content: 'part of test; class B {}'); driver.addFile(lib); driver.addFile(part1); @@ -3496,9 +3524,9 @@ // No analyzed libraries initially. expect(driver.test.numOfAnalyzedLibraries, 0); - AnalysisResult libResult = await driver.getResult(lib); - AnalysisResult partResult1 = await driver.getResult(part1); - AnalysisResult partResult2 = await driver.getResult(part2); + ResolvedUnitResult libResult = await driver.getResult(lib); + ResolvedUnitResult partResult1 = await driver.getResult(part1); + ResolvedUnitResult partResult2 = await driver.getResult(part2); // Just one library was analyzed, results for parts are cached. expect(driver.test.numOfAnalyzedLibraries, 1); @@ -3520,11 +3548,11 @@ } test_getResult_singleFile() async { - var path = _p('/test.dart'); - provider.newFile(path, 'main() {}'); + var path = convertPath('/test.dart'); + newFile(path, content: 'main() {}'); driver.addFile(path); - AnalysisResult result1 = await driver.getResult(path); + ResolvedUnitResult result1 = await driver.getResult(path); expect(driver.test.numOfAnalyzedLibraries, 1); var unit1 = result1.unit; var unitElement1 = unit1.declaredElement; @@ -3532,7 +3560,7 @@ expect(unit1, isNotNull); expect(unitElement1, isNotNull); - AnalysisResult result2 = await driver.getResult(path); + ResolvedUnitResult result2 = await driver.getResult(path); expect(driver.test.numOfAnalyzedLibraries, 1); expect(result2.path, path); expect(result2.unit, same(unit1)); @@ -3540,13 +3568,11 @@ } test_removeFile() async { - var path = _p('/test.dart'); + var path = convertPath('/test.dart'); expect(() { driver.removeFile(path); }, throwsStateError); } - - String _p(String path) => provider.convertPath(path); } class _SourceMock implements Source {
diff --git a/pkg/analyzer/test/src/dart/analysis/file_state_test.dart b/pkg/analyzer/test/src/dart/analysis/file_state_test.dart index aeb0e75..119f2b3 100644 --- a/pkg/analyzer/test/src/dart/analysis/file_state_test.dart +++ b/pkg/analyzer/test/src/dart/analysis/file_state_test.dart
@@ -6,9 +6,9 @@ import 'dart:typed_data'; import 'package:analyzer/file_system/file_system.dart'; -import 'package:analyzer/file_system/memory_file_system.dart'; import 'package:analyzer/src/dart/analysis/byte_store.dart'; import 'package:analyzer/src/dart/analysis/file_state.dart'; +import 'package:analyzer/src/dart/analysis/library_graph.dart'; import 'package:analyzer/src/dart/analysis/performance_logger.dart'; import 'package:analyzer/src/dart/analysis/top_level_declaration.dart'; import 'package:analyzer/src/file_system/file_system.dart'; @@ -16,13 +16,13 @@ show AnalysisOptions, AnalysisOptionsImpl; import 'package:analyzer/src/generated/source.dart'; import 'package:analyzer/src/source/package_map_resolver.dart'; +import 'package:analyzer/src/test_utilities/mock_sdk.dart'; +import 'package:analyzer/src/test_utilities/resource_provider_mixin.dart'; import 'package:convert/convert.dart'; import 'package:crypto/crypto.dart'; import 'package:test/test.dart'; import 'package:test_reflective_loader/test_reflective_loader.dart'; -import '../../context/mock_sdk.dart'; - main() { defineReflectiveSuite(() { defineReflectiveTests(FileSystemStateTest); @@ -30,8 +30,7 @@ } @reflectiveTest -class FileSystemStateTest { - final MemoryResourceProvider provider = new MemoryResourceProvider(); +class FileSystemStateTest with ResourceProviderMixin { MockSdk sdk; final ByteStore byteStore = new MemoryByteStore(); @@ -47,22 +46,22 @@ void setUp() { logger = new PerformanceLog(logBuffer); - sdk = new MockSdk(resourceProvider: provider); + sdk = new MockSdk(resourceProvider: resourceProvider); sourceFactory = new SourceFactory([ new DartUriResolver(sdk), generatedUriResolver, - new PackageMapUriResolver(provider, <String, List<Folder>>{ - 'aaa': [provider.getFolder(_p('/aaa/lib'))], - 'bbb': [provider.getFolder(_p('/bbb/lib'))], + new PackageMapUriResolver(resourceProvider, <String, List<Folder>>{ + 'aaa': [getFolder('/aaa/lib')], + 'bbb': [getFolder('/bbb/lib')], }), - new ResourceUriResolver(provider) - ], null, provider); + new ResourceUriResolver(resourceProvider) + ], null, resourceProvider); AnalysisOptions analysisOptions = new AnalysisOptionsImpl(); fileSystemState = new FileSystemState( logger, byteStore, contentOverlay, - provider, + resourceProvider, sourceFactory, analysisOptions, new Uint32List(0), @@ -70,8 +69,8 @@ } test_definedClassMemberNames() { - String path = _p('/aaa/lib/a.dart'); - provider.newFile(path, r''' + String path = convertPath('/aaa/lib/a.dart'); + newFile(path, content: r''' class A { int a, b; A(); @@ -90,8 +89,8 @@ } test_definedTopLevelNames() { - String path = _p('/aaa/lib/a.dart'); - provider.newFile(path, r''' + String path = convertPath('/aaa/lib/a.dart'); + newFile(path, content: r''' class A {} class B = Object with A; typedef C(); @@ -106,18 +105,18 @@ } test_exportedTopLevelDeclarations_cycle() { - String a = _p('/aaa/lib/a.dart'); - String b = _p('/aaa/lib/b.dart'); - String c = _p('/aaa/lib/c.dart'); - provider.newFile(a, r''' + String a = convertPath('/aaa/lib/a.dart'); + String b = convertPath('/aaa/lib/b.dart'); + String c = convertPath('/aaa/lib/c.dart'); + newFile(a, content: r''' export 'b.dart'; class A {} '''); - provider.newFile(b, r''' + newFile(b, content: r''' export 'c.dart'; class B {} '''); - provider.newFile(c, r''' + newFile(c, content: r''' export 'a.dart'; class C {} '''); @@ -130,24 +129,24 @@ } test_exportedTopLevelDeclarations_cycle_anotherOutsideCycle() { - String a = _p('/aaa/lib/a.dart'); - String b = _p('/aaa/lib/b.dart'); - String c = _p('/aaa/lib/c.dart'); - String d = _p('/aaa/lib/d.dart'); - provider.newFile(a, r''' + String a = convertPath('/aaa/lib/a.dart'); + String b = convertPath('/aaa/lib/b.dart'); + String c = convertPath('/aaa/lib/c.dart'); + String d = convertPath('/aaa/lib/d.dart'); + newFile(a, content: r''' export 'b.dart'; class A {} '''); - provider.newFile(b, r''' + newFile(b, content: r''' export 'c.dart'; class B {} '''); - provider.newFile(c, r''' + newFile(c, content: r''' export 'b.dart'; export 'd.dart'; class C {} '''); - provider.newFile(d, r''' + newFile(d, content: r''' class D {} '''); _assertExportedTopLevelDeclarations(a, ['A', 'B', 'C', 'D']); @@ -159,28 +158,28 @@ } test_exportedTopLevelDeclarations_cycle_onSequence() { - String a = _p('/aaa/lib/a.dart'); - String b = _p('/aaa/lib/b.dart'); - String c = _p('/aaa/lib/c.dart'); - String d = _p('/aaa/lib/d.dart'); - String e = _p('/aaa/lib/e.dart'); - provider.newFile(a, r''' + String a = convertPath('/aaa/lib/a.dart'); + String b = convertPath('/aaa/lib/b.dart'); + String c = convertPath('/aaa/lib/c.dart'); + String d = convertPath('/aaa/lib/d.dart'); + String e = convertPath('/aaa/lib/e.dart'); + newFile(a, content: r''' export 'b.dart'; class A {} '''); - provider.newFile(b, r''' + newFile(b, content: r''' export 'c.dart'; class B {} '''); - provider.newFile(c, r''' + newFile(c, content: r''' export 'd.dart'; class C {} '''); - provider.newFile(d, r''' + newFile(d, content: r''' export 'e.dart'; class D {} '''); - provider.newFile(e, r''' + newFile(e, content: r''' export 'c.dart'; class E {} '''); @@ -197,12 +196,12 @@ } test_exportedTopLevelDeclarations_export() { - String a = _p('/aaa/lib/a.dart'); - String b = _p('/aaa/lib/b.dart'); - provider.newFile(a, r''' + String a = convertPath('/aaa/lib/a.dart'); + String b = convertPath('/aaa/lib/b.dart'); + newFile(a, content: r''' class A {} '''); - provider.newFile(b, r''' + newFile(b, content: r''' export 'a.dart'; class B {} '''); @@ -211,20 +210,20 @@ } test_exportedTopLevelDeclarations_export2_show() { - String a = _p('/aaa/lib/a.dart'); - String b = _p('/aaa/lib/b.dart'); - String c = _p('/aaa/lib/c.dart'); - provider.newFile(a, r''' + String a = convertPath('/aaa/lib/a.dart'); + String b = convertPath('/aaa/lib/b.dart'); + String c = convertPath('/aaa/lib/c.dart'); + newFile(a, content: r''' class A1 {} class A2 {} class A3 {} '''); - provider.newFile(b, r''' + newFile(b, content: r''' export 'a.dart' show A1, A2; class B1 {} class B2 {} '''); - provider.newFile(c, r''' + newFile(c, content: r''' export 'b.dart' show A2, A3, B1; class C {} '''); @@ -233,12 +232,12 @@ } test_exportedTopLevelDeclarations_export_flushOnChange() { - String a = _p('/aaa/lib/a.dart'); - String b = _p('/aaa/lib/b.dart'); - provider.newFile(a, r''' + String a = convertPath('/aaa/lib/a.dart'); + String b = convertPath('/aaa/lib/b.dart'); + newFile(a, content: r''' class A {} '''); - provider.newFile(b, r''' + newFile(b, content: r''' export 'a.dart'; class B {} '''); @@ -247,20 +246,20 @@ _assertExportedTopLevelDeclarations(b, ['A', 'B']); // Update a.dart, so a.dart and b.dart exported declarations are flushed. - provider.newFile(a, 'class A {} class A2 {}'); + newFile(a, content: 'class A {} class A2 {}'); fileSystemState.getFileForPath(a).refresh(); _assertExportedTopLevelDeclarations(b, ['A', 'A2', 'B']); } test_exportedTopLevelDeclarations_export_hide() { - String a = _p('/aaa/lib/a.dart'); - String b = _p('/aaa/lib/b.dart'); - provider.newFile(a, r''' + String a = convertPath('/aaa/lib/a.dart'); + String b = convertPath('/aaa/lib/b.dart'); + newFile(a, content: r''' class A1 {} class A2 {} class A3 {} '''); - provider.newFile(b, r''' + newFile(b, content: r''' export 'a.dart' hide A2; class B {} '''); @@ -268,12 +267,12 @@ } test_exportedTopLevelDeclarations_export_preferLocal() { - String a = _p('/aaa/lib/a.dart'); - String b = _p('/aaa/lib/b.dart'); - provider.newFile(a, r''' + String a = convertPath('/aaa/lib/a.dart'); + String b = convertPath('/aaa/lib/b.dart'); + newFile(a, content: r''' class V {} '''); - provider.newFile(b, r''' + newFile(b, content: r''' export 'a.dart'; int V; '''); @@ -285,13 +284,13 @@ } test_exportedTopLevelDeclarations_export_show() { - String a = _p('/aaa/lib/a.dart'); - String b = _p('/aaa/lib/b.dart'); - provider.newFile(a, r''' + String a = convertPath('/aaa/lib/a.dart'); + String b = convertPath('/aaa/lib/b.dart'); + newFile(a, content: r''' class A1 {} class A2 {} '''); - provider.newFile(b, r''' + newFile(b, content: r''' export 'a.dart' show A2; class B {} '''); @@ -299,21 +298,21 @@ } test_exportedTopLevelDeclarations_export_show2() { - String a = _p('/aaa/lib/a.dart'); - String b = _p('/aaa/lib/b.dart'); - String c = _p('/aaa/lib/c.dart'); - String d = _p('/aaa/lib/d.dart'); - provider.newFile(a, r''' + String a = convertPath('/aaa/lib/a.dart'); + String b = convertPath('/aaa/lib/b.dart'); + String c = convertPath('/aaa/lib/c.dart'); + String d = convertPath('/aaa/lib/d.dart'); + newFile(a, content: r''' export 'b.dart' show Foo; export 'c.dart' show Bar; '''); - provider.newFile(b, r''' + newFile(b, content: r''' export 'd.dart'; '''); - provider.newFile(c, r''' + newFile(c, content: r''' export 'd.dart'; '''); - provider.newFile(d, r''' + newFile(d, content: r''' class Foo {} class Bar {} '''); @@ -321,12 +320,12 @@ } test_exportedTopLevelDeclarations_import() { - String a = _p('/aaa/lib/a.dart'); - String b = _p('/aaa/lib/b.dart'); - provider.newFile(a, r''' + String a = convertPath('/aaa/lib/a.dart'); + String b = convertPath('/aaa/lib/b.dart'); + newFile(a, content: r''' class A {} '''); - provider.newFile(b, r''' + newFile(b, content: r''' import 'a.dart'; class B {} '''); @@ -334,14 +333,14 @@ } test_exportedTopLevelDeclarations_parts() { - String a = _p('/aaa/lib/a.dart'); - String a2 = _p('/aaa/lib/a2.dart'); - provider.newFile(a, r''' + String a = convertPath('/aaa/lib/a.dart'); + String a2 = convertPath('/aaa/lib/a2.dart'); + newFile(a, content: r''' library lib; part 'a2.dart'; class A1 {} '''); - provider.newFile(a2, r''' + newFile(a2, content: r''' part of lib; class A2 {} '''); @@ -349,7 +348,7 @@ } test_getFileForPath_doesNotExist() { - String path = _p('/aaa/lib/a.dart'); + String path = convertPath('/aaa/lib/a.dart'); FileState file = fileSystemState.getFileForPath(path); expect(file.path, path); expect(file.uri, Uri.parse('package:aaa/a.dart')); @@ -367,8 +366,8 @@ } test_getFileForPath_emptyUri() { - String path = _p('/test.dart'); - provider.newFile(path, r''' + String path = convertPath('/test.dart'); + newFile(path, content: r''' import ''; export ''; part ''; @@ -381,8 +380,8 @@ } test_getFileForPath_hasLibraryDirective_hasPartOfDirective() { - String a = _p('/test/lib/a.dart'); - provider.newFile(a, r''' + String a = convertPath('/test/lib/a.dart'); + newFile(a, content: r''' library L; part of L; '''); @@ -391,10 +390,10 @@ } test_getFileForPath_invalidUri() { - String a = _p('/aaa/lib/a.dart'); - String a1 = _p('/aaa/lib/a1.dart'); - String a2 = _p('/aaa/lib/a2.dart'); - String a3 = _p('/aaa/lib/a3.dart'); + String a = convertPath('/aaa/lib/a.dart'); + String a1 = convertPath('/aaa/lib/a1.dart'); + String a2 = convertPath('/aaa/lib/a2.dart'); + String a3 = convertPath('/aaa/lib/a3.dart'); String content_a1 = r''' import 'package:aaa/a1.dart'; import ':[invalid uri]'; @@ -405,7 +404,7 @@ part 'a3.dart'; part ':[invalid uri]'; '''; - provider.newFile(a, content_a1); + newFile(a, content: content_a1); FileState file = fileSystemState.getFileForPath(a); @@ -429,12 +428,12 @@ } test_getFileForPath_library() { - String a1 = _p('/aaa/lib/a1.dart'); - String a2 = _p('/aaa/lib/a2.dart'); - String a3 = _p('/aaa/lib/a3.dart'); - String a4 = _p('/aaa/lib/a4.dart'); - String b1 = _p('/bbb/lib/b1.dart'); - String b2 = _p('/bbb/lib/b2.dart'); + String a1 = convertPath('/aaa/lib/a1.dart'); + String a2 = convertPath('/aaa/lib/a2.dart'); + String a3 = convertPath('/aaa/lib/a3.dart'); + String a4 = convertPath('/aaa/lib/a4.dart'); + String b1 = convertPath('/bbb/lib/b1.dart'); + String b2 = convertPath('/bbb/lib/b2.dart'); String content_a1 = r''' import 'package:aaa/a2.dart'; import 'package:bbb/b1.dart'; @@ -444,7 +443,7 @@ class A1 {} '''; - provider.newFile(a1, content_a1); + newFile(a1, content: content_a1); FileState file = fileSystemState.getFileForPath(a1); expect(file.path, a1); @@ -485,12 +484,12 @@ } test_getFileForPath_onlyDartFiles() { - String not_dart = _p('/test/lib/not_dart.txt'); - String a = _p('/test/lib/a.dart'); - String b = _p('/test/lib/b.dart'); - String c = _p('/test/lib/c.dart'); - String d = _p('/test/lib/d.dart'); - provider.newFile(a, r''' + String not_dart = convertPath('/test/lib/not_dart.txt'); + String a = convertPath('/test/lib/a.dart'); + String b = convertPath('/test/lib/b.dart'); + String c = convertPath('/test/lib/c.dart'); + String d = convertPath('/test/lib/d.dart'); + newFile(a, content: r''' library lib; import 'dart:math'; import 'b.dart'; @@ -511,13 +510,13 @@ } test_getFileForPath_part() { - String a1 = _p('/aaa/lib/a1.dart'); - String a2 = _p('/aaa/lib/a2.dart'); - provider.newFile(a1, r''' + String a1 = convertPath('/aaa/lib/a1.dart'); + String a2 = convertPath('/aaa/lib/a2.dart'); + newFile(a1, content: r''' library a1; part 'a2.dart'; '''); - provider.newFile(a2, r''' + newFile(a2, content: r''' part of a1; class A2 {} '''); @@ -552,7 +551,7 @@ // Now update the library, and refresh its file. // The 'a2.dart' is not referenced anymore. // So the part file does not have the library anymore. - provider.newFile(a1, r''' + newFile(a1, content: r''' library a1; part 'not-a2.dart'; '''); @@ -561,7 +560,7 @@ } test_getFileForPath_samePath() { - String path = _p('/aaa/lib/a.dart'); + String path = convertPath('/aaa/lib/a.dart'); FileState file1 = fileSystemState.getFileForPath(path); FileState file2 = fileSystemState.getFileForPath(path); expect(file2, same(file1)); @@ -577,9 +576,9 @@ } test_getFileForUri_packageVsFileUri() { - String path = _p('/aaa/lib/a.dart'); + String path = convertPath('/aaa/lib/a.dart'); var packageUri = Uri.parse('package:aaa/a.dart'); - var fileUri = provider.pathContext.toUri(path); + var fileUri = toUri(path); // The files with `package:` and `file:` URIs are different. FileState filePackageUri = fileSystemState.getFileForUri(packageUri); @@ -598,14 +597,14 @@ } test_getFilesSubtypingName() { - String a = _p('/a.dart'); - String b = _p('/b.dart'); + String a = convertPath('/a.dart'); + String b = convertPath('/b.dart'); - provider.newFile(a, r''' + newFile(a, content: r''' class A {} class B extends A {} '''); - provider.newFile(b, r''' + newFile(b, content: r''' class A {} class D implements A {} '''); @@ -619,7 +618,7 @@ ); // Change b.dart so that it does not subtype A. - provider.newFile(b, r''' + newFile(b, content: r''' class C {} class D implements C {} '''); @@ -636,8 +635,8 @@ test_hasUri() { Uri uri = Uri.parse('package:aaa/foo.dart'); - String templatePath = _p('/aaa/lib/foo.dart'); - String generatedPath = _p('/generated/aaa/lib/foo.dart'); + String templatePath = convertPath('/aaa/lib/foo.dart'); + String generatedPath = convertPath('/generated/aaa/lib/foo.dart'); Source generatedSource = new _SourceMock(generatedPath, uri); @@ -648,9 +647,87 @@ expect(fileSystemState.hasUri(generatedPath), isTrue); } + test_libraryCycle() { + String pa = convertPath('/aaa/lib/a.dart'); + String pb = convertPath('/aaa/lib/b.dart'); + String pc = convertPath('/aaa/lib/c.dart'); + String pd = convertPath('/aaa/lib/d.dart'); + + FileState fa = fileSystemState.getFileForPath(pa); + FileState fb = fileSystemState.getFileForPath(pb); + FileState fc = fileSystemState.getFileForPath(pc); + FileState fd = fileSystemState.getFileForPath(pd); + + // Compute library cycles for all files. + fa.libraryCycle; + fb.libraryCycle; + fc.libraryCycle; + fd.libraryCycle; + _assertFilesWithoutLibraryCycle([]); + + // No imports, so just a single file. + newFile(pa); + _assertLibraryCycle(fa, [fa], []); + + // Import b.dart into a.dart, two files now. + newFile(pa, content: "import 'b.dart';"); + fa.refresh(); + _assertFilesWithoutLibraryCycle([fa]); + _assertLibraryCycle(fa, [fa], [fb.libraryCycle]); + + // Update b.dart so that it imports c.dart now. + newFile(pb, content: "import 'c.dart';"); + fb.refresh(); + _assertFilesWithoutLibraryCycle([fa, fb]); + _assertLibraryCycle(fa, [fa], [fb.libraryCycle]); + _assertLibraryCycle(fb, [fb], [fc.libraryCycle]); + _assertFilesWithoutLibraryCycle([]); + + // Update b.dart so that it exports d.dart instead. + newFile(pb, content: "export 'd.dart';"); + fb.refresh(); + _assertFilesWithoutLibraryCycle([fa, fb]); + _assertLibraryCycle(fa, [fa], [fb.libraryCycle]); + _assertLibraryCycle(fb, [fb], [fd.libraryCycle]); + _assertFilesWithoutLibraryCycle([]); + + // Update a.dart so that it does not import b.dart anymore. + newFile(pa); + fa.refresh(); + _assertFilesWithoutLibraryCycle([fa]); + _assertLibraryCycle(fa, [fa], []); + } + + test_libraryCycle_cycle() { + String pa = convertPath('/aaa/lib/a.dart'); + String pb = convertPath('/aaa/lib/b.dart'); + + newFile(pa, content: "import 'b.dart';"); + newFile(pb, content: "import 'a.dart';"); + + FileState fa = fileSystemState.getFileForPath(pa); + FileState fb = fileSystemState.getFileForPath(pb); + + // Compute library cycles for all files. + fa.libraryCycle; + fb.libraryCycle; + _assertFilesWithoutLibraryCycle([]); + + // It's a cycle. + _assertLibraryCycle(fa, [fa, fb], []); + _assertLibraryCycle(fb, [fa, fb], []); + + // Update a.dart so that it does not import b.dart anymore. + newFile(pa); + fa.refresh(); + _assertFilesWithoutLibraryCycle([fa, fb]); + _assertLibraryCycle(fa, [fa], []); + _assertLibraryCycle(fb, [fb], [fa.libraryCycle]); + } + test_referencedNames() { - String path = _p('/aaa/lib/a.dart'); - provider.newFile(path, r''' + String path = convertPath('/aaa/lib/a.dart'); + newFile(path, content: r''' A foo(B p) { foo(null); C c = new C(p); @@ -662,8 +739,8 @@ } test_refresh_differentApiSignature() { - String path = _p('/aaa/lib/a.dart'); - provider.newFile(path, r''' + String path = convertPath('/aaa/lib/a.dart'); + newFile(path, content: r''' class A {} '''); FileState file = fileSystemState.getFileForPath(path); @@ -671,7 +748,7 @@ List<int> signature = file.apiSignature; // Update the resource and refresh the file state. - provider.newFile(path, r''' + newFile(path, content: r''' class B {} '''); bool apiSignatureChanged = file.refresh(); @@ -682,8 +759,8 @@ } test_refresh_sameApiSignature() { - String path = _p('/aaa/lib/a.dart'); - provider.newFile(path, r''' + String path = convertPath('/aaa/lib/a.dart'); + newFile(path, content: r''' class C { foo() { print(111); @@ -694,7 +771,7 @@ List<int> signature = file.apiSignature; // Update the resource and refresh the file state. - provider.newFile(path, r''' + newFile(path, content: r''' class C { foo() { print(222); @@ -708,8 +785,8 @@ } test_store_zeroLengthUnlinked() { - String path = _p('/test.dart'); - provider.newFile(path, 'class A {}'); + String path = convertPath('/test.dart'); + newFile(path, content: 'class A {}'); // Get the file, prepare unlinked. FileState file = fileSystemState.getFileForPath(path); @@ -724,8 +801,8 @@ } test_subtypedNames() { - String path = _p('/test.dart'); - provider.newFile(path, r''' + String path = convertPath('/test.dart'); + newFile(path, content: r''' class X extends A {} class Y extends A with B {} class Z implements C, D {} @@ -735,8 +812,8 @@ } test_topLevelDeclarations() { - String path = _p('/aaa/lib/a.dart'); - provider.newFile(path, r''' + String path = convertPath('/aaa/lib/a.dart'); + newFile(path, content: r''' class C {} typedef F(); enum E {E1, E2} @@ -775,95 +852,16 @@ assertHas('V4', TopLevelDeclarationKind.variable); } - test_transitiveFiles() { - String pa = _p('/aaa/lib/a.dart'); - String pb = _p('/aaa/lib/b.dart'); - String pc = _p('/aaa/lib/c.dart'); - String pd = _p('/aaa/lib/d.dart'); - - FileState fa = fileSystemState.getFileForPath(pa); - FileState fb = fileSystemState.getFileForPath(pb); - FileState fc = fileSystemState.getFileForPath(pc); - FileState fd = fileSystemState.getFileForPath(pd); - - // Compute transitive closures for all files. - fa.transitiveFiles; - fb.transitiveFiles; - fc.transitiveFiles; - fd.transitiveFiles; - expect( - _excludeSdk(fileSystemState.test.filesWithoutTransitiveFiles), isEmpty); - - // No imports, so just a single file. - provider.newFile(pa, ""); - _assertTransitiveFiles(fa, [fa]); - - // Import b.dart into a.dart, two files now. - provider.newFile(pa, "import 'b.dart';"); - fa.refresh(); - _assertFilesWithoutTransitiveFiles([fa]); - _assertTransitiveFiles(fa, [fa, fb]); - - // Update b.dart so that it imports c.dart now. - provider.newFile(pb, "import 'c.dart';"); - fb.refresh(); - _assertFilesWithoutTransitiveFiles([fa, fb]); - _assertTransitiveFiles(fa, [fa, fb, fc]); - _assertTransitiveFiles(fb, [fb, fc]); - _assertFilesWithoutTransitiveFiles([]); - - // Update b.dart so that it exports d.dart instead. - provider.newFile(pb, "export 'd.dart';"); - fb.refresh(); - _assertFilesWithoutTransitiveFiles([fa, fb]); - _assertTransitiveFiles(fa, [fa, fb, fd]); - _assertTransitiveFiles(fb, [fb, fd]); - _assertFilesWithoutTransitiveFiles([]); - - // Update a.dart so that it does not import b.dart anymore. - provider.newFile(pa, ""); - fa.refresh(); - _assertFilesWithoutTransitiveFiles([fa]); - _assertTransitiveFiles(fa, [fa]); - } - - test_transitiveFiles_cycle() { - String pa = _p('/aaa/lib/a.dart'); - String pb = _p('/aaa/lib/b.dart'); - - provider.newFile(pa, "import 'b.dart';"); - provider.newFile(pb, "import 'a.dart';"); - - FileState fa = fileSystemState.getFileForPath(pa); - FileState fb = fileSystemState.getFileForPath(pb); - - // Compute transitive closures for all files. - fa.transitiveFiles; - fb.transitiveFiles; - _assertFilesWithoutTransitiveFiles([]); - - // It's a cycle. - _assertTransitiveFiles(fa, [fa, fb]); - _assertTransitiveFiles(fb, [fa, fb]); - - // Update a.dart so that it does not import b.dart anymore. - provider.newFile(pa, ""); - fa.refresh(); - _assertFilesWithoutTransitiveFiles([fa, fb]); - _assertTransitiveFiles(fa, [fa]); - _assertTransitiveFiles(fb, [fa, fb]); - } - test_transitiveSignature() { - String pa = _p('/aaa/lib/a.dart'); - String pb = _p('/aaa/lib/b.dart'); - String pc = _p('/aaa/lib/c.dart'); - String pd = _p('/aaa/lib/d.dart'); + String pa = convertPath('/aaa/lib/a.dart'); + String pb = convertPath('/aaa/lib/b.dart'); + String pc = convertPath('/aaa/lib/c.dart'); + String pd = convertPath('/aaa/lib/d.dart'); - provider.newFile(pa, "class A {}"); - provider.newFile(pb, "import 'a.dart';"); - provider.newFile(pc, "import 'b.dart';"); - provider.newFile(pd, "class D {}"); + newFile(pa, content: "class A {}"); + newFile(pb, content: "import 'a.dart';"); + newFile(pc, content: "import 'b.dart';"); + newFile(pd, content: "class D {}"); FileState fa = fileSystemState.getFileForPath(pa); FileState fb = fileSystemState.getFileForPath(pb); @@ -871,25 +869,24 @@ FileState fd = fileSystemState.getFileForPath(pd); // Compute transitive closures for all files. + // This implicitly computes library cycles. expect(fa.transitiveSignature, isNotNull); expect(fb.transitiveSignature, isNotNull); expect(fc.transitiveSignature, isNotNull); expect(fd.transitiveSignature, isNotNull); - expect( - _excludeSdk(fileSystemState.test.filesWithoutTransitiveFiles), isEmpty); + _assertFilesWithoutLibraryCycle([]); // Make an update to a.dart that does not change its API signature. - // All transitive signatures are still valid. - provider.newFile(pa, "class A {} // the same API signature"); + // All library cycles are still valid. + newFile(pa, content: "class A {} // the same API signature"); fa.refresh(); - expect( - _excludeSdk(fileSystemState.test.filesWithoutTransitiveFiles), isEmpty); + _assertFilesWithoutLibraryCycle([]); - // Change a.dart API signature, also flush signatures of b.dart and c.dart, - // but d.dart is still OK. - provider.newFile(pa, "class A2 {}"); + // Change a.dart API signature. + // This flushes signatures of b.dart and c.dart, but d.dart is still OK. + newFile(pa, content: "class A2 {}"); fa.refresh(); - _assertFilesWithoutTransitiveSignatures([fa, fb, fc]); + _assertFilesWithoutLibraryCycle([fa, fb, fc]); } void _assertExportedTopLevelDeclarations(String path, List<String> expected) { @@ -899,13 +896,8 @@ expect(declarations.keys, unorderedEquals(expected)); } - void _assertFilesWithoutTransitiveFiles(List<FileState> expected) { - var actual = fileSystemState.test.filesWithoutTransitiveFiles; - expect(_excludeSdk(actual), unorderedEquals(expected)); - } - - void _assertFilesWithoutTransitiveSignatures(List<FileState> expected) { - var actual = fileSystemState.test.filesWithoutTransitiveSignature; + void _assertFilesWithoutLibraryCycle(List<FileState> expected) { + var actual = fileSystemState.test.filesWithoutLibraryCycle; expect(_excludeSdk(actual), unorderedEquals(expected)); } @@ -921,22 +913,30 @@ expect(file.source, isNull); } - void _assertTransitiveFiles(FileState file, List<FileState> expected) { - expect(_excludeSdk(file.transitiveFiles), unorderedEquals(expected)); + void _assertLibraryCycle( + FileState file, + List<FileState> expectedLibraries, + List<LibraryCycle> expectedDirectDependencies, + ) { + expect(file.libraryCycle.libraries, unorderedEquals(expectedLibraries)); + expect( + _excludeSdk(file.libraryCycle.directDependencies), + unorderedEquals(expectedDirectDependencies), + ); } List<T> _excludeSdk<T>(Iterable<T> files) { return files.where((Object file) { - if (file is FileState) { + if (file is LibraryCycle) { + return !file.libraries.any((file) => file.uri.isScheme('dart')); + } else if (file is FileState) { return file.uri?.scheme != 'dart'; } else { - return !(file as String).startsWith(_p('/sdk')); + return !(file as String).startsWith(convertPath('/sdk')); } }).toList(); } - String _p(String path) => provider.convertPath(path); - static String _md5(String content) { return hex.encode(md5.convert(utf8.encode(content)).bytes); }
diff --git a/pkg/analyzer/test/src/dart/analysis/index_test.dart b/pkg/analyzer/test/src/dart/analysis/index_test.dart index e3106d1..94fbd94 100644 --- a/pkg/analyzer/test/src/dart/analysis/index_test.dart +++ b/pkg/analyzer/test/src/dart/analysis/index_test.dart
@@ -5,9 +5,9 @@ import 'dart:async'; import 'dart:convert'; +import 'package:analyzer/dart/analysis/results.dart'; import 'package:analyzer/dart/ast/ast.dart'; import 'package:analyzer/dart/element/element.dart'; -import 'package:analyzer/src/dart/analysis/driver.dart'; import 'package:analyzer/src/dart/analysis/index.dart'; import 'package:analyzer/src/summary/format.dart'; import 'package:analyzer/src/summary/idl.dart'; @@ -134,7 +134,7 @@ } test_isExtendedBy_ClassDeclaration_isQualified() async { - provider.newFile(_p('$testProject/lib.dart'), ''' + newFile('$testProject/lib.dart', content: ''' class A {} '''); await _indexTestUnit(''' @@ -167,7 +167,7 @@ } test_isExtendedBy_ClassTypeAlias_isQualified() async { - provider.newFile(_p('$testProject/lib.dart'), ''' + newFile('$testProject/lib.dart', content: ''' class A {} '''); await _indexTestUnit(''' @@ -193,7 +193,7 @@ } test_isImplementedBy_ClassDeclaration_isQualified() async { - provider.newFile(_p('$testProject/lib.dart'), ''' + newFile('$testProject/lib.dart', content: ''' class A {} '''); await _indexTestUnit(''' @@ -256,7 +256,7 @@ } test_isInvokedBy_FunctionElement() async { - provider.newFile(_p('$testProject/lib.dart'), ''' + newFile('$testProject/lib.dart', content: ''' library lib; foo() {} '''); @@ -393,7 +393,7 @@ } test_isMixedInBy_ClassDeclaration_isQualified() async { - provider.newFile(_p('$testProject/lib.dart'), ''' + newFile('$testProject/lib.dart', content: ''' class A {} '''); await _indexTestUnit(''' @@ -465,7 +465,7 @@ } test_isReferencedBy_ClassElement_invocation_isQualified() async { - provider.newFile(_p('$testProject/lib.dart'), ''' + newFile('$testProject/lib.dart', content: ''' class A {} '''); await _indexTestUnit(''' @@ -504,7 +504,7 @@ } test_isReferencedBy_CompilationUnitElement_export() async { - provider.newFile(_p('$testProject/lib.dart'), ''' + newFile('$testProject/lib.dart', content: ''' library lib; '''); await _indexTestUnit(''' @@ -515,7 +515,7 @@ } test_isReferencedBy_CompilationUnitElement_import() async { - provider.newFile(_p('$testProject/lib.dart'), ''' + newFile('$testProject/lib.dart', content: ''' library lib; '''); await _indexTestUnit(''' @@ -526,7 +526,7 @@ } test_isReferencedBy_CompilationUnitElement_part() async { - provider.newFile(_p('$testProject/my_unit.dart'), 'part of my_lib;'); + newFile('$testProject/my_unit.dart', content: 'part of my_lib;'); await _indexTestUnit(''' library my_lib; part 'my_unit.dart'; @@ -536,8 +536,8 @@ } test_isReferencedBy_CompilationUnitElement_part_inPart() async { - provider.newFile(_p('$testProject/a.dart'), 'part of lib;'); - provider.newFile(_p('$testProject/b.dart'), ''' + newFile('$testProject/a.dart', content: 'part of lib;'); + newFile('$testProject/b.dart', content: ''' library lib; part 'a.dart'; '''); @@ -803,7 +803,7 @@ } test_isReferencedBy_FunctionElement_with_LibraryElement() async { - provider.newFile(_p('$testProject/foo.dart'), r''' + newFile('$testProject/foo.dart', content: r''' bar() {} '''); await _indexTestUnit(''' @@ -863,8 +863,8 @@ } test_isReferencedBy_MultiplyDefinedElement() async { - provider.newFile(_p('$testProject/a1.dart'), 'class A {}'); - provider.newFile(_p('$testProject/a2.dart'), 'class A {}'); + newFile('$testProject/a1.dart', content: 'class A {}'); + newFile('$testProject/a2.dart', content: 'class A {}'); await _indexTestUnit(''' import 'a1.dart'; import 'a2.dart'; @@ -911,7 +911,7 @@ } test_isReferencedBy_TopLevelVariableElement() async { - provider.newFile(_p('$testProject/lib.dart'), ''' + newFile('$testProject/lib.dart', content: ''' library lib; var V; '''); @@ -935,7 +935,7 @@ } test_isReferencedBy_TopLevelVariableElement_synthetic_hasGetterSetter() async { - provider.newFile(_p('$testProject/lib.dart'), ''' + newFile('$testProject/lib.dart', content: ''' int get V => 0; void set V(_) {} '''); @@ -947,7 +947,7 @@ } test_isReferencedBy_TopLevelVariableElement_synthetic_hasSetter() async { - provider.newFile(_p('$testProject/lib.dart'), ''' + newFile('$testProject/lib.dart', content: ''' void set V(_) {} '''); await _indexTestUnit(''' @@ -982,7 +982,7 @@ test_subtypes_classDeclaration() async { String libP = 'package:test/lib.dart;package:test/lib.dart'; - provider.newFile(_p('$testProject/lib.dart'), ''' + newFile('$testProject/lib.dart', content: ''' class A {} class B {} class C {} @@ -1032,7 +1032,7 @@ test_subtypes_classTypeAlias() async { String libP = 'package:test/lib.dart;package:test/lib.dart'; - provider.newFile(_p('$testProject/lib.dart'), ''' + newFile('$testProject/lib.dart', content: ''' class A {} class B {} class C {} @@ -1070,7 +1070,7 @@ test_subtypes_mixinDeclaration() async { String libP = 'package:test/lib.dart;package:test/lib.dart'; - provider.newFile(_p('$testProject/lib.dart'), ''' + newFile('$testProject/lib.dart', content: ''' class A {} class B {} class C {} @@ -1339,7 +1339,7 @@ Future<Null> _indexTestUnit(String code) async { addTestFile(code); - AnalysisResult result = await driver.getResult(testFile); + ResolvedUnitResult result = await driver.getResult(testFile); testUnit = result.unit; testUnitElement = testUnit.declaredElement; testLibraryElement = testUnitElement.library; @@ -1348,8 +1348,6 @@ List<int> indexBytes = indexBuilder.toBuffer(); index = new AnalysisDriverUnitIndex.fromBuffer(indexBytes); } - - String _p(String path) => provider.convertPath(path); } class _ElementIndexAssert {
diff --git a/pkg/analyzer/test/src/dart/analysis/search_test.dart b/pkg/analyzer/test/src/dart/analysis/search_test.dart index ad2bc6e..2d67389 100644 --- a/pkg/analyzer/test/src/dart/analysis/search_test.dart +++ b/pkg/analyzer/test/src/dart/analysis/search_test.dart
@@ -5,10 +5,10 @@ import 'dart:async'; import 'dart:collection'; +import 'package:analyzer/dart/analysis/results.dart'; import 'package:analyzer/dart/ast/ast.dart' hide Declaration; import 'package:analyzer/dart/ast/standard_resolution_map.dart'; import 'package:analyzer/dart/element/element.dart'; -import 'package:analyzer/src/dart/analysis/driver.dart'; import 'package:analyzer/src/dart/analysis/search.dart'; import 'package:analyzer/src/dart/ast/utilities.dart'; import 'package:analyzer/src/dart/element/member.dart'; @@ -149,15 +149,15 @@ } test_declarations_discover() async { - var t = _p('/test/lib/t.dart'); - var a = _p('/aaa/lib/a.dart'); - var b = _p('/bbb/lib/b.dart'); - var c = _p('/ccc/lib/c.dart'); + var t = convertPath('/test/lib/t.dart'); + var a = convertPath('/aaa/lib/a.dart'); + var b = convertPath('/bbb/lib/b.dart'); + var c = convertPath('/ccc/lib/c.dart'); - provider.newFile(t, 'class T {}'); - provider.newFile(a, 'class A {}'); - provider.newFile(b, 'class B {}'); - provider.newFile(c, 'class C {}'); + newFile(t, content: 'class T {}'); + newFile(a, content: 'class A {}'); + newFile(b, content: 'class B {}'); + newFile(c, content: 'class C {}'); driver.addFile(t); @@ -170,11 +170,11 @@ } test_declarations_duplicateFile() async { - var a = _p('/test/lib/a.dart'); - var b = _p('/test/lib/b.dart'); + var a = convertPath('/test/lib/a.dart'); + var b = convertPath('/test/lib/b.dart'); - provider.newFile(a, 'class A {}'); - provider.newFile(b, 'class B {}'); + newFile(a, content: 'class A {}'); + newFile(b, content: 'class B {}'); driver.addFile(a); driver.addFile(b); @@ -243,10 +243,10 @@ } test_declarations_onlyForFile() async { - var a = _p('/test/lib/a.dart'); - var b = _p('/test/lib/b.dart'); - provider.newFile(a, 'class A {}'); - provider.newFile(b, 'class B {}'); + var a = convertPath('/test/lib/a.dart'); + var b = convertPath('/test/lib/b.dart'); + newFile(a, content: 'class A {}'); + newFile(b, content: 'class B {}'); driver.addFile(a); driver.addFile(b); @@ -423,15 +423,15 @@ } test_references_discover() async { - var t = _p('/test/lib/t.dart'); - var a = _p('/aaa/lib/a.dart'); - var b = _p('/bbb/lib/b.dart'); - var c = _p('/ccc/lib/c.dart'); + var t = convertPath('/test/lib/t.dart'); + var a = convertPath('/aaa/lib/a.dart'); + var b = convertPath('/bbb/lib/b.dart'); + var c = convertPath('/ccc/lib/c.dart'); - provider.newFile(t, 'List t;'); - provider.newFile(a, 'List a;'); - provider.newFile(b, 'List b;'); - provider.newFile(c, 'List c;'); + newFile(t, content: 'List t;'); + newFile(a, content: 'List a;'); + newFile(b, content: 'List b;'); + newFile(c, content: 'List c;'); driver.addFile(t); @@ -456,13 +456,13 @@ } test_references_discover_onlyOwned() async { - var t = _p('/test/lib/t.dart'); - var a = _p('/aaa/lib/a.dart'); - var b = _p('/bbb/lib/b.dart'); + var t = convertPath('/test/lib/t.dart'); + var a = convertPath('/aaa/lib/a.dart'); + var b = convertPath('/bbb/lib/b.dart'); - provider.newFile(t, 'List t;'); - provider.newFile(a, 'List a;'); - provider.newFile(b, 'List b;'); + newFile(t, content: 'List t;'); + newFile(a, content: 'List a;'); + newFile(b, content: 'List b;'); driver.addFile(t); driver.addFile(a); @@ -492,11 +492,11 @@ } test_references_discover_onlyOwned_samePath() async { - var p = _p('/test/lib/t.dart'); - provider.newFile(p, 'int t;'); + var p = convertPath('/test/lib/t.dart'); + newFile(p, content: 'int t;'); var driver1 = createAnalysisDriver(packageMap: { - 'test': [provider.newFolder(_p('/test/lib'))] + 'test': [newFolder('/test/lib')] }); var driver2 = createAnalysisDriver(packageMap: {}); @@ -512,17 +512,17 @@ } test_references_discover_onlyOwned_sameUri() async { - var a = _p('/aaa/lib/t.dart'); - var b = _p('/bbb/lib/t.dart'); + var a = convertPath('/aaa/lib/t.dart'); + var b = convertPath('/bbb/lib/t.dart'); - provider.newFile(a, 'int t;'); - provider.newFile(b, 'double t;'); + newFile(a, content: 'int t;'); + newFile(b, content: 'double t;'); var driver1 = createAnalysisDriver(packageMap: { - 'ttt': [provider.newFolder(_p('/aaa/lib'))] + 'ttt': [newFolder('/aaa/lib')] }); var driver2 = createAnalysisDriver(packageMap: { - 'ttt': [provider.newFolder(_p('/bbb/lib'))] + 'ttt': [newFolder('/bbb/lib')] }); // driver1 owns `/aaa/lib/t.dart` with `package:ttt/t.dart`. @@ -620,7 +620,7 @@ ClassElement randomElement; { String randomPath = sdk.mapDartUri('dart:math').fullName; - AnalysisResult result = await driver.getResult(randomPath); + ResolvedUnitResult result = await driver.getResult(randomPath); randomElement = result.unit.declaredElement.getType('Random'); } @@ -680,7 +680,7 @@ } test_searchReferences_ClassElement_definedOutside() async { - provider.newFile(_p('$testProject/lib.dart'), r''' + newFile('$testProject/lib.dart', content: r''' class A {}; '''); await _resolveTestUnit(''' @@ -713,7 +713,7 @@ } test_searchReferences_CompilationUnitElement() async { - provider.newFile(_p('$testProject/foo.dart'), ''); + newFile('$testProject/foo.dart'); await _resolveTestUnit(''' import 'foo.dart'; // import export 'foo.dart'; // export @@ -750,14 +750,14 @@ } test_searchReferences_ConstructorElement_default_otherFile() async { - String other = _p('$testProject/other.dart'); + String other = convertPath('$testProject/other.dart'); String otherCode = ''' import 'test.dart'; main() { new A(); // in other } '''; - provider.newFile(other, otherCode); + newFile(other, content: otherCode); driver.addFile(other); await _resolveTestUnit(''' @@ -962,7 +962,7 @@ } test_searchReferences_ImportElement_noPrefix_inPackage() async { - testFile = _p('/aaa/lib/a.dart'); + testFile = convertPath('/aaa/lib/a.dart'); await _resolveTestUnit(''' import 'dart:math' show max, PI, Random hide min; export 'dart:math' show max, PI, Random hide min; @@ -1063,8 +1063,8 @@ test_searchReferences_LibraryElement() async { var codeA = 'part of lib; // A'; var codeB = 'part of lib; // B'; - provider.newFile(_p('$testProject/unitA.dart'), codeA); - provider.newFile(_p('$testProject/unitB.dart'), codeB); + newFile('$testProject/unitA.dart', content: codeA); + newFile('$testProject/unitB.dart', content: codeB); await _resolveTestUnit(''' library lib; part 'unitA.dart'; @@ -1083,14 +1083,14 @@ } test_searchReferences_LibraryElement_inPackage() async { - testFile = _p('/aaa/lib/a.dart'); - var partPathA = _p('/aaa/lib/unitA.dart'); - var partPathB = _p('/aaa/lib/unitB.dart'); + testFile = convertPath('/aaa/lib/a.dart'); + var partPathA = convertPath('/aaa/lib/unitA.dart'); + var partPathB = convertPath('/aaa/lib/unitB.dart'); var codeA = 'part of lib; // A'; var codeB = 'part of lib; // B'; - provider.newFile(partPathA, codeA); - provider.newFile(partPathB, codeB); + newFile(partPathA, content: codeA); + newFile(partPathB, content: codeB); await _resolveTestUnit(''' library lib; part 'unitA.dart'; @@ -1152,7 +1152,7 @@ } test_searchReferences_LocalVariableElement_inPackage() async { - testFile = _p('/aaa/lib/a.dart'); + testFile = convertPath('/aaa/lib/a.dart'); await _resolveTestUnit(''' main() { @@ -1370,7 +1370,7 @@ part of my_lib; ppp.Future c; '''; - provider.newFile(_p('$testProject/my_part.dart'), partCode); + newFile('$testProject/my_part.dart', content: partCode); await _resolveTestUnit(''' library my_lib; import 'dart:async' as ppp; @@ -1393,14 +1393,14 @@ } test_searchReferences_PrefixElement_inPackage() async { - testFile = _p('/aaa/lib/a.dart'); - var partPath = _p('/aaa/lib/my_part.dart'); + testFile = convertPath('/aaa/lib/a.dart'); + var partPath = convertPath('/aaa/lib/my_part.dart'); String partCode = r''' part of my_lib; ppp.Future c; '''; - provider.newFile(partPath, partCode); + newFile(partPath, content: partCode); await _resolveTestUnit(''' library my_lib; import 'dart:async' as ppp; @@ -1423,14 +1423,14 @@ } test_searchReferences_private_declaredInDefiningUnit() async { - String p1 = _p('$testProject/part1.dart'); - String p2 = _p('$testProject/part2.dart'); - String p3 = _p('$testProject/part3.dart'); + String p1 = convertPath('$testProject/part1.dart'); + String p2 = convertPath('$testProject/part2.dart'); + String p3 = convertPath('$testProject/part3.dart'); String code1 = 'part of lib; _C v1;'; String code2 = 'part of lib; _C v2;'; - provider.newFile(p1, code1); - provider.newFile(p2, code2); - provider.newFile(p3, 'part of lib; int v3;'); + newFile(p1, content: code1); + newFile(p2, content: code2); + newFile(p3, content: 'part of lib; int v3;'); driver.addFile(p1); driver.addFile(p2); @@ -1459,9 +1459,9 @@ } test_searchReferences_private_declaredInPart() async { - String p = _p('$testProject/lib.dart'); - String p1 = _p('$testProject/part1.dart'); - String p2 = _p('$testProject/part2.dart'); + String p = convertPath('$testProject/lib.dart'); + String p1 = convertPath('$testProject/part1.dart'); + String p2 = convertPath('$testProject/part2.dart'); var code = ''' library lib; @@ -1476,15 +1476,15 @@ '''; String code2 = 'part of lib; _C v2;'; - provider.newFile(p, code); - provider.newFile(p1, code1); - provider.newFile(p2, code2); + newFile(p, content: code); + newFile(p1, content: code1); + newFile(p2, content: code2); driver.addFile(p); driver.addFile(p1); driver.addFile(p2); - AnalysisResult result = await driver.getResult(p); + ResolvedUnitResult result = await driver.getResult(p); testUnit = result.unit; testUnitElement = testUnit.declaredElement; testLibraryElement = testUnitElement.library; @@ -1505,15 +1505,15 @@ } test_searchReferences_private_inPackage() async { - testFile = _p('/aaa/lib/a.dart'); - var p1 = _p('/aaa/lib/part1.dart'); - var p2 = _p('/aaa/lib/part2.dart'); + testFile = convertPath('/aaa/lib/a.dart'); + var p1 = convertPath('/aaa/lib/part1.dart'); + var p2 = convertPath('/aaa/lib/part2.dart'); String code1 = 'part of lib; _C v1;'; String code2 = 'part of lib; _C v2;'; - provider.newFile(p1, code1); - provider.newFile(p2, code2); + newFile(p1, content: code1); + newFile(p2, content: code2); await _resolveTestUnit(''' library lib; @@ -1581,7 +1581,7 @@ } test_searchReferences_TopLevelVariableElement() async { - provider.newFile(_p('$testProject/lib.dart'), ''' + newFile('$testProject/lib.dart', content: ''' library lib; var V; '''); @@ -1768,15 +1768,15 @@ } test_subtypes_discover() async { - var pathT = _p('/test/lib/t.dart'); - var pathA = _p('/aaa/lib/a.dart'); - var pathB = _p('/bbb/lib/b.dart'); + var pathT = convertPath('/test/lib/t.dart'); + var pathA = convertPath('/aaa/lib/a.dart'); + var pathB = convertPath('/bbb/lib/b.dart'); var tUri = 'package:test/t.dart'; var aUri = 'package:aaa/a.dart'; var bUri = 'package:bbb/b.dart'; - provider.newFile(pathT, r''' + newFile(pathT, content: r''' import 'package:aaa/a.dart'; class T1 extends A { @@ -1788,7 +1788,7 @@ } '''); - provider.newFile(pathB, r''' + newFile(pathB, content: r''' import 'package:aaa/a.dart'; class B extends A { @@ -1796,7 +1796,7 @@ } '''); - provider.newFile(pathA, r''' + newFile(pathA, content: r''' class A { void method1() {} void method2() {} @@ -1830,15 +1830,15 @@ } test_subTypes_discover() async { - var t = _p('/test/lib/t.dart'); - var a = _p('/aaa/lib/a.dart'); - var b = _p('/bbb/lib/b.dart'); - var c = _p('/ccc/lib/c.dart'); + var t = convertPath('/test/lib/t.dart'); + var a = convertPath('/aaa/lib/a.dart'); + var b = convertPath('/bbb/lib/b.dart'); + var c = convertPath('/ccc/lib/c.dart'); - provider.newFile(t, 'class T implements List {}'); - provider.newFile(a, 'class A implements List {}'); - provider.newFile(b, 'class B implements List {}'); - provider.newFile(c, 'class C implements List {}'); + newFile(t, content: 'class T implements List {}'); + newFile(a, content: 'class A implements List {}'); + newFile(b, content: 'class B implements List {}'); + newFile(c, content: 'class C implements List {}'); driver.addFile(t); @@ -1863,13 +1863,13 @@ } test_subtypes_files() async { - String pathB = _p('$testProject/b.dart'); - String pathC = _p('$testProject/c.dart'); - provider.newFile(pathB, r''' + String pathB = convertPath('$testProject/b.dart'); + String pathC = convertPath('$testProject/c.dart'); + newFile(pathB, content: r''' import 'test.dart'; class B extends A {} '''); - provider.newFile(pathC, r''' + newFile(pathC, content: r''' import 'test.dart'; class C extends A {} class D {} @@ -2016,17 +2016,15 @@ return ElementLocator.locate(node); } - String _p(String path) => provider.convertPath(path); - Future<Null> _resolveTestUnit(String code, {bool addToDriver: true}) async { if (addToDriver) { addTestFile(code); } else { testCode = code; - provider.newFile(testFile, testCode); + newFile(testFile, content: testCode); } if (testUnit == null) { - AnalysisResult result = await driver.getResult(testFile); + ResolvedUnitResult result = await driver.getResult(testFile); testUnit = result.unit; testUnitElement = testUnit.declaredElement; testLibraryElement = testUnitElement.library;
diff --git a/pkg/analyzer/test/src/dart/analysis/session_helper_test.dart b/pkg/analyzer/test/src/dart/analysis/session_helper_test.dart index 81e7cbb..f815fbc 100644 --- a/pkg/analyzer/test/src/dart/analysis/session_helper_test.dart +++ b/pkg/analyzer/test/src/dart/analysis/session_helper_test.dart
@@ -2,12 +2,13 @@ // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. +import 'package:analyzer/dart/ast/ast.dart'; import 'package:analyzer/dart/element/element.dart'; import 'package:analyzer/src/dart/analysis/session_helper.dart'; import 'package:test/test.dart'; import 'package:test_reflective_loader/test_reflective_loader.dart'; -import 'base.dart'; +import '../resolution/driver_resolution.dart'; main() { defineReflectiveSuite(() { @@ -16,163 +17,408 @@ } @reflectiveTest -class AnalysisSessionHelperTest extends BaseAnalysisDriverTest { - AnalysisSessionHelper sessionHelper; +class AnalysisSessionHelperTest extends DriverResolutionTest { + AnalysisSessionHelper helper; @override void setUp() { super.setUp(); - sessionHelper = new AnalysisSessionHelper(driver.currentSession); + helper = new AnalysisSessionHelper(driver.currentSession); } test_getClass_defined() async { - var path = _p('/c.dart'); - var file = provider.newFile(path, r''' + var file = newFile('/test/lib/c.dart', content: r''' class C {} int v = 0; '''); String uri = file.toUri().toString(); - var element = await sessionHelper.getClass(uri, 'C'); + var element = await helper.getClass(uri, 'C'); expect(element, isNotNull); expect(element.displayName, 'C'); } test_getClass_defined_notClass() async { - var path = _p('/c.dart'); - var file = provider.newFile(path, r''' + var file = newFile('/test/lib/c.dart', content: r''' int v = 0; '''); String uri = file.toUri().toString(); - var element = await sessionHelper.getClass(uri, 'v'); + var element = await helper.getClass(uri, 'v'); expect(element, isNull); } test_getClass_exported() async { - var a = _p('/a.dart'); - var b = _p('/b.dart'); - provider.newFile(a, r''' + newFile('/test/lib/a.dart', content: r''' class A {} '''); - var bFile = provider.newFile(b, r''' + var bFile = newFile('/test/lib/b.dart', content: r''' export 'a.dart'; '''); String bUri = bFile.toUri().toString(); - var element = await sessionHelper.getClass(bUri, 'A'); + var element = await helper.getClass(bUri, 'A'); expect(element, isNotNull); expect(element.displayName, 'A'); } test_getClass_imported() async { - var a = _p('/a.dart'); - var b = _p('/b.dart'); - provider.newFile(a, r''' + newFile('/test/lib/a.dart', content: r''' class A {} '''); - var bFile = provider.newFile(b, r''' + var bFile = newFile('/test/lib/b.dart', content: r''' import 'a.dart'; '''); String bUri = bFile.toUri().toString(); - var element = await sessionHelper.getClass(bUri, 'A'); + var element = await helper.getClass(bUri, 'A'); expect(element, isNull); } + test_getElementDeclaration_class() async { + newFile('/test/lib/test.dart', content: r''' +class A {} +'''); + await resolveTestFile(); + + var element = findNode.classDeclaration('A').declaredElement; + var result = await helper.getElementDeclaration(element); + ClassDeclaration node = result.node; + expect(node.name.name, 'A'); + } + + test_getElementDeclaration_class_duplicate() async { + newFile('/test/lib/test.dart', content: r''' +class A {} // 1 +class A {} // 2 +'''); + await resolveTestFile(); + + { + var element = findNode.classDeclaration('A {} // 1').declaredElement; + var result = await helper.getElementDeclaration(element); + ClassDeclaration node = result.node; + expect(node.name.name, 'A'); + expect( + node.name.offset, + this.result.content.indexOf('A {} // 1'), + ); + } + + { + var element = findNode.classDeclaration('A {} // 2').declaredElement; + var result = await helper.getElementDeclaration(element); + ClassDeclaration node = result.node; + expect(node.name.name, 'A'); + expect( + node.name.offset, + this.result.content.indexOf('A {} // 2'), + ); + } + } + + test_getElementDeclaration_class_inPart() async { + newFile('/test/lib/a.dart', content: r''' +part of 'test.dart'; +class A {} +'''); + newFile('/test/lib/test.dart', content: r''' +part 'a.dart'; +'''); + await resolveTestFile(); + + var library = this.result.unit.declaredElement.library; + var element = library.getType('A'); + var result = await helper.getElementDeclaration(element); + ClassDeclaration node = result.node; + expect(node.name.name, 'A'); + } + + test_getElementDeclaration_constructor() async { + newFile('/test/lib/test.dart', content: r''' +class A { + A(); + A.named(); +} +'''); + await resolveTestFile(); + + { + var unnamed = findNode.constructor('A();').declaredElement; + var result = await helper.getElementDeclaration(unnamed); + ConstructorDeclaration node = result.node; + expect(node.name, isNull); + } + + { + var named = findNode.constructor('A.named();').declaredElement; + var result = await helper.getElementDeclaration(named); + ConstructorDeclaration node = result.node; + expect(node.name.name, 'named'); + } + } + + test_getElementDeclaration_constructor_duplicate_named() async { + newFile('/test/lib/test.dart', content: r''' +class A { + A.named(); // 1 + A.named(); // 2 +} +'''); + await resolveTestFile(); + + { + var element = findNode.constructor('A.named(); // 1').declaredElement; + var result = await helper.getElementDeclaration(element); + ConstructorDeclaration node = result.node; + expect(node.name.name, 'named'); + expect( + node.name.offset, + this.result.content.indexOf('named(); // 1'), + ); + } + + { + var element = findNode.constructor('A.named(); // 2').declaredElement; + var result = await helper.getElementDeclaration(element); + ConstructorDeclaration node = result.node; + expect(node.name.name, 'named'); + expect( + node.name.offset, + this.result.content.indexOf('named(); // 2'), + ); + } + } + + test_getElementDeclaration_constructor_duplicate_unnamed() async { + newFile('/test/lib/test.dart', content: r''' +class A { + A(); // 1 + A(); // 2 +} +'''); + await resolveTestFile(); + + { + var element = findNode.constructor('A(); // 1').declaredElement; + var result = await helper.getElementDeclaration(element); + ConstructorDeclaration node = result.node; + expect(node.name, isNull); + expect( + node.returnType.offset, + this.result.content.indexOf('A(); // 1'), + ); + } + + { + var element = findNode.constructor('A(); // 2').declaredElement; + var result = await helper.getElementDeclaration(element); + ConstructorDeclaration node = result.node; + expect(node.name, isNull); + expect( + node.returnType.offset, + this.result.content.indexOf('A(); // 2'), + ); + } + } + + test_getElementDeclaration_constructor_synthetic() async { + newFile('/test/lib/test.dart', content: r''' +class A {} +'''); + await resolveTestFile(); + + var element = findElement.class_('A').unnamedConstructor; + expect(element.isSynthetic, isTrue); + + var result = await helper.getElementDeclaration(element); + expect(result, isNull); + } + + test_getElementDeclaration_field() async { + newFile('/test/lib/test.dart', content: r''' +class C { + int foo; +} +'''); + await resolveTestFile(); + + var element = findElement.field('foo'); + var result = await helper.getElementDeclaration(element); + VariableDeclaration node = result.node; + expect(node.name.name, 'foo'); + } + + test_getElementDeclaration_functionDeclaration_local() async { + newFile('/test/lib/test.dart', content: r''' +main() { + void foo() {} +} +'''); + await resolveTestFile(); + + var element = findElement.localFunction('foo'); + var result = await helper.getElementDeclaration(element); + FunctionDeclaration node = result.node; + expect(node.name.name, 'foo'); + } + + test_getElementDeclaration_functionDeclaration_top() async { + newFile('/test/lib/test.dart', content: r''' +void foo() {} +'''); + await resolveTestFile(); + + var element = findElement.topFunction('foo'); + var result = await helper.getElementDeclaration(element); + FunctionDeclaration node = result.node; + expect(node.name.name, 'foo'); + } + + test_getElementDeclaration_localVariable() async { + newFile('/test/lib/test.dart', content: r''' +main() { + int foo; +} +'''); + await resolveTestFile(); + + var element = findElement.localVar('foo'); + var result = await helper.getElementDeclaration(element); + VariableDeclaration node = result.node; + expect(node.name.name, 'foo'); + } + + test_getElementDeclaration_method() async { + newFile('/test/lib/test.dart', content: r''' +class C { + void foo() {} +} +'''); + await resolveTestFile(); + + var element = findElement.method('foo'); + var result = await helper.getElementDeclaration(element); + MethodDeclaration node = result.node; + expect(node.name.name, 'foo'); + } + + test_getElementDeclaration_topLevelVariable() async { + newFile('/test/lib/test.dart', content: r''' +int foo; +'''); + await resolveTestFile(); + + var element = findElement.topVar('foo'); + var result = await helper.getElementDeclaration(element); + VariableDeclaration node = result.node; + expect(node.name.name, 'foo'); + } + + test_getElementDeclaration_topLevelVariable_synthetic() async { + newFile('/test/lib/test.dart', content: r''' +int get foo => 0; +'''); + await resolveTestFile(); + + var element = findElement.topVar('foo'); + var result = await helper.getElementDeclaration(element); + expect(result, isNull); + } + + test_getResolvedUnitByElement() async { + newFile('/test/lib/test.dart', content: r''' +class A {} +class B {} +'''); + await resolveTestFile(); + + var element = findNode.classDeclaration('A').declaredElement; + var resolvedUnit = await helper.getResolvedUnitByElement(element); + expect(resolvedUnit.unit.declarations, hasLength(2)); + } + test_getTopLevelPropertyAccessor_defined_getter() async { - var path = _p('/test.dart'); - var file = provider.newFile(path, r''' + var file = newFile('/test/lib/test.dart', content: r''' int get a => 0; '''); String uri = file.toUri().toString(); - var element = await sessionHelper.getTopLevelPropertyAccessor(uri, 'a'); + var element = await helper.getTopLevelPropertyAccessor(uri, 'a'); expect(element, isNotNull); expect(element.kind, ElementKind.GETTER); expect(element.displayName, 'a'); } test_getTopLevelPropertyAccessor_defined_setter() async { - var path = _p('/test.dart'); - var file = provider.newFile(path, r''' + var file = newFile('/test/lib/test.dart', content: r''' set a(_) {} '''); String uri = file.toUri().toString(); - var element = await sessionHelper.getTopLevelPropertyAccessor(uri, 'a='); + var element = await helper.getTopLevelPropertyAccessor(uri, 'a='); expect(element, isNotNull); expect(element.kind, ElementKind.SETTER); expect(element.displayName, 'a'); } test_getTopLevelPropertyAccessor_defined_variable() async { - var path = _p('/test.dart'); - var file = provider.newFile(path, r''' + var file = newFile('/test/lib/test.dart', content: r''' int a; '''); String uri = file.toUri().toString(); - var element = await sessionHelper.getTopLevelPropertyAccessor(uri, 'a'); + var element = await helper.getTopLevelPropertyAccessor(uri, 'a'); expect(element, isNotNull); expect(element.kind, ElementKind.GETTER); expect(element.displayName, 'a'); } test_getTopLevelPropertyAccessor_exported() async { - var a = _p('/a.dart'); - var b = _p('/b.dart'); - provider.newFile(a, r''' + newFile('/test/lib/a.dart', content: r''' int a; '''); - var bFile = provider.newFile(b, r''' + var bFile = newFile('/test/lib/b.dart', content: r''' export 'a.dart'; '''); String bUri = bFile.toUri().toString(); - var element = await sessionHelper.getTopLevelPropertyAccessor(bUri, 'a'); + var element = await helper.getTopLevelPropertyAccessor(bUri, 'a'); expect(element, isNotNull); expect(element.kind, ElementKind.GETTER); expect(element.displayName, 'a'); } test_getTopLevelPropertyAccessor_imported() async { - var a = _p('/a.dart'); - var b = _p('/b.dart'); - provider.newFile(a, r''' + newFile('/test/lib/a.dart', content: r''' int a; '''); - var bFile = provider.newFile(b, r''' + var bFile = newFile('/test/lib/b.dart', content: r''' import 'a.dart'; '''); String bUri = bFile.toUri().toString(); - var element = await sessionHelper.getTopLevelPropertyAccessor(bUri, 'a'); + var element = await helper.getTopLevelPropertyAccessor(bUri, 'a'); expect(element, isNull); } test_getTopLevelPropertyAccessor_notDefined() async { - var path = _p('/test.dart'); - var file = provider.newFile(path, r''' + var file = newFile('/test/lib/test.dart', content: r''' int a; '''); String uri = file.toUri().toString(); - var element = await sessionHelper.getTopLevelPropertyAccessor(uri, 'b'); + var element = await helper.getTopLevelPropertyAccessor(uri, 'b'); expect(element, isNull); } test_getTopLevelPropertyAccessor_notPropertyAccessor() async { - var path = _p('/test.dart'); - var file = provider.newFile(path, r''' + var file = newFile('/test/lib/test.dart', content: r''' int a() {} '''); String uri = file.toUri().toString(); - var element = await sessionHelper.getTopLevelPropertyAccessor(uri, 'a'); + var element = await helper.getTopLevelPropertyAccessor(uri, 'a'); expect(element, isNull); } - - /// Return the [provider] specific path for the given Posix [path]. - String _p(String path) => provider.convertPath(path); }
diff --git a/pkg/analyzer/test/src/dart/analysis/session_test.dart b/pkg/analyzer/test/src/dart/analysis/session_test.dart index a5b9b87..555c2ec 100644 --- a/pkg/analyzer/test/src/dart/analysis/session_test.dart +++ b/pkg/analyzer/test/src/dart/analysis/session_test.dart
@@ -8,12 +8,11 @@ import 'package:analyzer/src/dart/analysis/analysis_context_collection.dart'; import 'package:analyzer/src/dart/analysis/session.dart'; import 'package:analyzer/src/generated/source.dart'; +import 'package:analyzer/src/test_utilities/mock_sdk.dart'; import 'package:analyzer/src/test_utilities/resource_provider_mixin.dart'; import 'package:test/test.dart'; import 'package:test_reflective_loader/test_reflective_loader.dart'; -import '../../context/mock_sdk.dart'; - main() { defineReflectiveSuite(() { defineReflectiveTests(AnalysisSessionImplTest); @@ -74,32 +73,207 @@ expect(library.getType('C'), isNull); } - test_getParsedAstSync() async { + test_getParsedLibrary() async { newFile(testPath, content: r''' class A {} class B {} '''); - var unitResult = session.getParsedAstSync(testPath); - expect(unitResult.session, session); - expect(unitResult.path, testPath); - expect(unitResult.uri, Uri.parse('package:test/test.dart')); - expect(unitResult.unit.declarations, hasLength(2)); + var parsedLibrary = session.getParsedLibrary(testPath); + expect(parsedLibrary.session, session); + expect(parsedLibrary.path, testPath); + expect(parsedLibrary.uri, Uri.parse('package:test/test.dart')); + + expect(parsedLibrary.units, hasLength(1)); + { + var parsedUnit = parsedLibrary.units[0]; + expect(parsedUnit.session, session); + expect(parsedUnit.path, testPath); + expect(parsedUnit.uri, Uri.parse('package:test/test.dart')); + expect(parsedUnit.unit.declarations, hasLength(2)); + } } - test_getResolvedAst() async { + test_getParsedLibrary_getElementDeclaration_class() async { newFile(testPath, content: r''' class A {} class B {} '''); - var unitResult = await session.getResolvedAst(testPath); + var library = await session.getLibraryByUri('package:test/test.dart'); + var parsedLibrary = session.getParsedLibrary(testPath); + + var element = library.getType('A'); + var declaration = parsedLibrary.getElementDeclaration(element); + ClassDeclaration node = declaration.node; + expect(node.name.name, 'A'); + expect(node.offset, 0); + expect(node.length, 10); + } + + test_getParsedLibrary_getElementDeclaration_notThisLibrary() async { + newFile(testPath, content: ''); + + var parsedLibrary = await session.getParsedLibrary(testPath); + + var typeProvider = await session.typeProvider; + var intClass = typeProvider.intType.element; + + expect(() { + parsedLibrary.getElementDeclaration(intClass); + }, throwsArgumentError); + } + + test_getParsedLibrary_getElementDeclaration_synthetic() async { + newFile(testPath, content: r''' +int foo = 0; +'''); + + var parsedLibrary = session.getParsedLibrary(testPath); + + var unitElement = (await session.getUnitElement(testPath)).element; + var fooElement = unitElement.topLevelVariables[0]; + expect(fooElement.name, 'foo'); + + // We can get the variable element declaration. + var fooDeclaration = parsedLibrary.getElementDeclaration(fooElement); + VariableDeclaration fooNode = fooDeclaration.node; + expect(fooNode.name.name, 'foo'); + expect(fooNode.offset, 4); + expect(fooNode.length, 7); + expect(fooNode.name.staticElement, isNull); + + // Synthetic elements don't have nodes. + expect(parsedLibrary.getElementDeclaration(fooElement.getter), isNull); + expect(parsedLibrary.getElementDeclaration(fooElement.setter), isNull); + } + + test_getParsedLibrary_invalidPartUri() async { + newFile(testPath, content: r''' +part 'a.dart'; +part ':[invalid uri].dart'; +part 'c.dart'; +'''); + + var parsedLibrary = session.getParsedLibrary(testPath); + + expect(parsedLibrary.units, hasLength(3)); + expect( + parsedLibrary.units[0].path, + convertPath('/home/test/lib/test.dart'), + ); + expect( + parsedLibrary.units[1].path, + convertPath('/home/test/lib/a.dart'), + ); + expect( + parsedLibrary.units[2].path, + convertPath('/home/test/lib/c.dart'), + ); + } + + test_getParsedLibrary_notLibrary() async { + newFile(testPath, content: 'part of "a.dart";'); + + expect(() { + session.getParsedLibrary(testPath); + }, throwsArgumentError); + } + + test_getParsedLibrary_parts() async { + var a = convertPath('/home/test/lib/a.dart'); + var b = convertPath('/home/test/lib/b.dart'); + var c = convertPath('/home/test/lib/c.dart'); + + var aContent = r''' +part 'b.dart'; +part 'c.dart'; + +class A {} +'''; + + var bContent = r''' +part of 'a.dart'; + +class B1 {} +class B2 {} +'''; + + var cContent = r''' +part of 'a.dart'; + +class C1 {} +class C2 {} +class C3 {} +'''; + + newFile(a, content: aContent); + newFile(b, content: bContent); + newFile(c, content: cContent); + + var parsedLibrary = session.getParsedLibrary(a); + expect(parsedLibrary.path, a); + expect(parsedLibrary.uri, Uri.parse('package:test/a.dart')); + expect(parsedLibrary.units, hasLength(3)); + + { + var aUnit = parsedLibrary.units[0]; + expect(aUnit.path, a); + expect(aUnit.uri, Uri.parse('package:test/a.dart')); + expect(aUnit.unit.declarations, hasLength(1)); + } + + { + var bUnit = parsedLibrary.units[1]; + expect(bUnit.path, b); + expect(bUnit.uri, Uri.parse('package:test/b.dart')); + expect(bUnit.unit.declarations, hasLength(2)); + } + + { + var cUnit = parsedLibrary.units[2]; + expect(cUnit.path, c); + expect(cUnit.uri, Uri.parse('package:test/c.dart')); + expect(cUnit.unit.declarations, hasLength(3)); + } + } + + test_getParsedLibraryByElement() async { + newFile(testPath, content: ''); + + var element = await session.getLibraryByUri('package:test/test.dart'); + + var parsedLibrary = session.getParsedLibraryByElement(element); + expect(parsedLibrary.session, session); + expect(parsedLibrary.path, testPath); + expect(parsedLibrary.uri, Uri.parse('package:test/test.dart')); + expect(parsedLibrary.units, hasLength(1)); + } + + test_getParsedLibraryByElement_differentSession() async { + newFile(testPath, content: ''); + + var element = await session.getLibraryByUri('package:test/test.dart'); + + var aaaSession = + contextCollection.contextFor(aaaContextPath).currentSession; + + expect(() { + aaaSession.getParsedLibraryByElement(element); + }, throwsArgumentError); + } + + test_getParsedUnit() async { + newFile(testPath, content: r''' +class A {} +class B {} +'''); + + var unitResult = session.getParsedUnit(testPath); expect(unitResult.session, session); expect(unitResult.path, testPath); expect(unitResult.uri, Uri.parse('package:test/test.dart')); expect(unitResult.unit.declarations, hasLength(2)); - expect(unitResult.typeProvider, isNotNull); - expect(unitResult.libraryElement, isNotNull); } test_getResolvedLibrary() async { @@ -251,6 +425,34 @@ expect(resolvedLibrary.units[0].unit.declaredElement, isNotNull); } + test_getResolvedLibraryByElement_differentSession() async { + newFile(testPath, content: ''); + + var element = await session.getLibraryByUri('package:test/test.dart'); + + var aaaSession = + contextCollection.contextFor(aaaContextPath).currentSession; + + expect(() async { + await aaaSession.getResolvedLibraryByElement(element); + }, throwsArgumentError); + } + + test_getResolvedUnit() async { + newFile(testPath, content: r''' +class A {} +class B {} +'''); + + var unitResult = await session.getResolvedUnit(testPath); + expect(unitResult.session, session); + expect(unitResult.path, testPath); + expect(unitResult.uri, Uri.parse('package:test/test.dart')); + expect(unitResult.unit.declarations, hasLength(2)); + expect(unitResult.typeProvider, isNotNull); + expect(unitResult.libraryElement, isNotNull); + } + test_getSourceKind() async { newFile(testPath, content: 'class C {}');
diff --git a/pkg/analyzer/test/src/dart/analysis/uri_converter_test.dart b/pkg/analyzer/test/src/dart/analysis/uri_converter_test.dart index f400cee..c7e291e 100644 --- a/pkg/analyzer/test/src/dart/analysis/uri_converter_test.dart +++ b/pkg/analyzer/test/src/dart/analysis/uri_converter_test.dart
@@ -3,18 +3,16 @@ // BSD-style license that can be found in the LICENSE file. import 'package:analyzer/file_system/file_system.dart'; -import 'package:analyzer/file_system/memory_file_system.dart'; import 'package:analyzer/src/context/context_root.dart'; import 'package:analyzer/src/dart/analysis/driver.dart'; import 'package:analyzer/src/dart/analysis/uri_converter.dart'; import 'package:analyzer/src/generated/source.dart'; import 'package:analyzer/src/source/package_map_resolver.dart'; +import 'package:analyzer/src/test_utilities/mock_sdk.dart'; import 'package:analyzer/src/test_utilities/resource_provider_mixin.dart'; import 'package:test/test.dart'; import 'package:test_reflective_loader/test_reflective_loader.dart'; -import '../../context/mock_sdk.dart'; - main() { defineReflectiveSuite(() { defineReflectiveTests(DriverBasedUriConverterTest); @@ -22,12 +20,10 @@ } @reflectiveTest -class DriverBasedUriConverterTest extends Object with ResourceProviderMixin { +class DriverBasedUriConverterTest with ResourceProviderMixin { DriverBasedUriConverter uriConverter; void setUp() { - resourceProvider = new MemoryResourceProvider(); - Folder barFolder = newFolder('/packages/bar/lib'); Folder fooFolder = newFolder('/packages/foo/lib');
diff --git a/pkg/analyzer/test/src/dart/ast/ast_test.dart b/pkg/analyzer/test/src/dart/ast/ast_test.dart index 1bbecda..f0a6265 100644 --- a/pkg/analyzer/test/src/dart/ast/ast_test.dart +++ b/pkg/analyzer/test/src/dart/ast/ast_test.dart
@@ -1,4 +1,4 @@ -// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file +// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. @@ -6,7 +6,6 @@ import 'package:analyzer/src/dart/ast/ast.dart'; import 'package:analyzer/src/dart/ast/utilities.dart'; -import 'package:analyzer/src/generated/engine.dart'; import 'package:test/test.dart'; import 'package:test_reflective_loader/test_reflective_loader.dart'; @@ -472,102 +471,24 @@ bool get enableNewAnalysisDriver => true; - void assertCanBeConst(String snippet, bool expectedResult) { - int index = testSource.indexOf(snippet); - expect(index >= 0, isTrue); - NodeLocator visitor = new NodeLocator(index); - AstNodeImpl node = visitor.searchWithin(testUnit); - node = node.getAncestor((node) => node is InstanceCreationExpressionImpl); - expect(node, isNotNull); - expect((node as InstanceCreationExpressionImpl).canBeConst(), - expectedResult ? isTrue : isFalse); - } - void assertIsConst(String snippet, bool expectedResult) { int index = testSource.indexOf(snippet); expect(index >= 0, isTrue); NodeLocator visitor = new NodeLocator(index); AstNodeImpl node = visitor.searchWithin(testUnit); - node = node.getAncestor((node) => node is InstanceCreationExpressionImpl); + node = node.thisOrAncestorOfType<InstanceCreationExpressionImpl>(); expect(node, isNotNull); expect((node as InstanceCreationExpressionImpl).isConst, expectedResult ? isTrue : isFalse); } - void enablePreviewDart2() { - resetWith(options: new AnalysisOptionsImpl()..previewDart2 = true); - } - Future<void> resolve(String source) async { testSource = source; testUnit = await resolveSource2('/test.dart', source); } - void test_canBeConst_false_argument_invocation() async { - enablePreviewDart2(); - await resolve(''' -class A {} -class B { - const B(A a); -} -A f() => A(); -B g() => B(f()); -'''); - assertCanBeConst("B(f", false); - } - - void test_canBeConst_false_argument_invocationInList() async { - enablePreviewDart2(); - await resolve(''' -class A {} -class B { - const B(a); -} -A f() => A(); -B g() => B([f()]); -'''); - assertCanBeConst("B([", false); - } - - void test_canBeConst_false_argument_nonConstConstructor() async { - enablePreviewDart2(); - await resolve(''' -class A {} -class B { - const B(A a); -} -B f() => B(A()); -'''); - assertCanBeConst("B(A(", false); - } - - void test_canBeConst_false_nonConstConstructor() async { - enablePreviewDart2(); - await resolve(''' -class A {} -A f() => A(); -'''); - assertCanBeConst("A(", false); - } - - @failingTest - void test_canBeConst_true_argument_constConstructor() async { - enablePreviewDart2(); - await resolve(''' -class A { - const A(); -} -class B { - const B(A a); -} -B f() => B(A()); -'''); - assertCanBeConst("B(A(", true); - } - void test_isConst_notInContext_constructor_const_constParam_identifier() async { - enablePreviewDart2(); await resolve(''' var v = C(C.a); class C { @@ -580,7 +501,6 @@ } void test_isConst_notInContext_constructor_const_constParam_named() async { - enablePreviewDart2(); await resolve(''' var v = C(c: C()); class C { @@ -592,7 +512,6 @@ void test_isConst_notInContext_constructor_const_constParam_named_parens() async { - enablePreviewDart2(); await resolve(''' var v = C(c: (C())); class C { @@ -603,7 +522,6 @@ } void test_isConst_notInContext_constructor_const_constParam_parens() async { - enablePreviewDart2(); await resolve(''' var v = C( (C.c()) ); class C { @@ -615,7 +533,6 @@ } void test_isConst_notInContext_constructor_const_generic_named() async { - enablePreviewDart2(); await resolve(''' f() => <Object>[C<int>.n()]; class C<E> { @@ -627,7 +544,6 @@ void test_isConst_notInContext_constructor_const_generic_named_prefixed() async { - enablePreviewDart2(); addNamedSource('/c.dart', ''' class C<E> { const C.n(); @@ -641,7 +557,6 @@ } void test_isConst_notInContext_constructor_const_generic_unnamed() async { - enablePreviewDart2(); await resolve(''' f() => <Object>[C<int>()]; class C<E> { @@ -653,7 +568,6 @@ void test_isConst_notInContext_constructor_const_generic_unnamed_prefixed() async { - enablePreviewDart2(); addNamedSource('/c.dart', ''' class C<E> { const C(); @@ -668,7 +582,6 @@ void test_isConst_notInContext_constructor_const_nonConstParam_constructor() async { - enablePreviewDart2(); await resolve(''' f() { return A(B()); @@ -687,7 +600,6 @@ void test_isConst_notInContext_constructor_const_nonConstParam_variable() async { - enablePreviewDart2(); await resolve(''' f(int i) => <Object>[C(i)]; class C { @@ -699,7 +611,6 @@ } void test_isConst_notInContext_constructor_const_nonGeneric_named() async { - enablePreviewDart2(); await resolve(''' f() => <Object>[C.n()]; class C<E> { @@ -711,7 +622,6 @@ void test_isConst_notInContext_constructor_const_nonGeneric_named_prefixed() async { - enablePreviewDart2(); addNamedSource('/c.dart', ''' class C { const C.n(); @@ -725,7 +635,6 @@ } void test_isConst_notInContext_constructor_const_nonGeneric_unnamed() async { - enablePreviewDart2(); await resolve(''' f() => <Object>[C()]; class C { @@ -737,7 +646,6 @@ void test_isConst_notInContext_constructor_const_nonGeneric_unnamed_prefixed() async { - enablePreviewDart2(); addNamedSource('/c.dart', ''' class C { const C(); @@ -751,7 +659,6 @@ } void test_isConst_notInContext_constructor_nonConst() async { - enablePreviewDart2(); await resolve(''' f() => <Object>[C()]; class C {
diff --git a/pkg/analyzer/test/src/dart/ast/utilities_test.dart b/pkg/analyzer/test/src/dart/ast/utilities_test.dart index de28384..795c3da 100644 --- a/pkg/analyzer/test/src/dart/ast/utilities_test.dart +++ b/pkg/analyzer/test/src/dart/ast/utilities_test.dart
@@ -805,7 +805,7 @@ void test_visitPartDirective() { PartDirective fromNode = AstTestFactory.partDirective2("part.dart"); LibraryElement element = new LibraryElementImpl.forNode( - null, AstTestFactory.libraryIdentifier2(["lib"])); + null, null, AstTestFactory.libraryIdentifier2(["lib"])); fromNode.element = element; PartDirective toNode = AstTestFactory.partDirective2("part.dart"); ResolutionCopier.copyResolutionData(fromNode, toNode); @@ -816,7 +816,7 @@ PartOfDirective fromNode = AstTestFactory.partOfDirective( AstTestFactory.libraryIdentifier2(["lib"])); LibraryElement element = new LibraryElementImpl.forNode( - null, AstTestFactory.libraryIdentifier2(["lib"])); + null, null, AstTestFactory.libraryIdentifier2(["lib"])); fromNode.element = element; PartOfDirective toNode = AstTestFactory.partOfDirective( AstTestFactory.libraryIdentifier2(["lib"]));
diff --git a/pkg/analyzer/test/src/dart/constant/evaluation_test.dart b/pkg/analyzer/test/src/dart/constant/evaluation_test.dart index 0a08cae..5fce676 100644 --- a/pkg/analyzer/test/src/dart/constant/evaluation_test.dart +++ b/pkg/analyzer/test/src/dart/constant/evaluation_test.dart
@@ -1,4 +1,4 @@ -// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file +// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. @@ -6,9 +6,12 @@ import 'package:analyzer/dart/ast/ast.dart'; import 'package:analyzer/dart/ast/standard_resolution_map.dart'; import 'package:analyzer/dart/ast/token.dart'; +import 'package:analyzer/error/error.dart'; import 'package:analyzer/error/listener.dart'; +import 'package:analyzer/src/dart/analysis/experiments.dart'; import 'package:analyzer/src/error/codes.dart'; import 'package:analyzer/src/generated/constant.dart'; +import 'package:analyzer/src/generated/engine.dart'; import 'package:analyzer/src/generated/resolver.dart'; import 'package:analyzer/src/generated/source.dart'; import 'package:analyzer/src/generated/source_io.dart'; @@ -29,7 +32,139 @@ @reflectiveTest class ConstantVisitorTest extends ResolverTestCase { - test_visitBinaryExpression_questionQuestion_notNull_notNull() async { + test_visitAsExpression_instanceOfSameClass() async { + CompilationUnit compilationUnit = await resolveSource(''' +const a = const A(); +const b = a as A; +class A { + const A(); +} +'''); + DartObjectImpl resultA = _evaluateConstant(compilationUnit, 'a', + experiments: [Experiments.constantUpdate2018Name]); + DartObjectImpl resultB = _evaluateConstant(compilationUnit, 'b', + experiments: [Experiments.constantUpdate2018Name]); + expect(resultB, resultA); + } + + test_visitAsExpression_instanceOfSubclass() async { + CompilationUnit compilationUnit = await resolveSource(''' +const a = const B(); +const b = a as A; +class A { + const A(); +} +class B extends A { + const B(); +} +'''); + DartObjectImpl resultA = _evaluateConstant(compilationUnit, 'a', + experiments: [Experiments.constantUpdate2018Name]); + DartObjectImpl resultB = _evaluateConstant(compilationUnit, 'b', + experiments: [Experiments.constantUpdate2018Name]); + expect(resultB, resultA); + } + + test_visitAsExpression_instanceOfSuperclass() async { + CompilationUnit compilationUnit = await resolveSource(''' +const a = const A(); +const b = a as B; +class A { + const A(); +} +class B extends A { + const B(); +} +'''); + DartObjectImpl result = _evaluateConstant(compilationUnit, 'b', + errorCodes: [CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION], + experiments: [Experiments.constantUpdate2018Name]); + expect(result, isNull); + } + + test_visitAsExpression_instanceOfUnrelatedClass() async { + CompilationUnit compilationUnit = await resolveSource(''' +const a = const A(); +const b = a as B; +class A { + const A(); +} +class B { + const B(); +} +'''); + DartObjectImpl result = _evaluateConstant(compilationUnit, 'b', + errorCodes: [CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION], + experiments: [Experiments.constantUpdate2018Name]); + expect(result, isNull); + } + + test_visitAsExpression_null() async { + CompilationUnit compilationUnit = await resolveSource(''' +const a = null; +const b = a as A; +class A {} +'''); + DartObjectImpl result = _evaluateConstant(compilationUnit, 'b', + experiments: [Experiments.constantUpdate2018Name]); + expect(result.type, typeProvider.nullType); + } + + test_visitBinaryExpression_and_bool() async { + CompilationUnit compilationUnit = await resolveSource(''' +const c = false & true; +'''); + DartObjectImpl result = _evaluateConstant(compilationUnit, 'c', + experiments: [Experiments.constantUpdate2018Name]); + expect(result.type, typeProvider.boolType); + } + + test_visitBinaryExpression_and_int() async { + CompilationUnit compilationUnit = await resolveSource(''' +const c = 3 & 5; +'''); + DartObjectImpl result = _evaluateConstant(compilationUnit, 'c', + experiments: [Experiments.constantUpdate2018Name]); + expect(result.type, typeProvider.intType); + } + + test_visitBinaryExpression_and_mixed() async { + CompilationUnit compilationUnit = await resolveSource(''' +const c = 3 & false; +'''); + _evaluateConstant(compilationUnit, 'c', + errorCodes: [CompileTimeErrorCode.CONST_EVAL_TYPE_BOOL_INT], + experiments: [Experiments.constantUpdate2018Name]); + } + + test_visitBinaryExpression_or_bool() async { + CompilationUnit compilationUnit = await resolveSource(''' +const c = false | true; +'''); + DartObjectImpl result = _evaluateConstant(compilationUnit, 'c', + experiments: [Experiments.constantUpdate2018Name]); + expect(result.type, typeProvider.boolType); + } + + test_visitBinaryExpression_or_int() async { + CompilationUnit compilationUnit = await resolveSource(''' +const c = 3 | 5; +'''); + DartObjectImpl result = _evaluateConstant(compilationUnit, 'c', + experiments: [Experiments.constantUpdate2018Name]); + expect(result.type, typeProvider.intType); + } + + test_visitBinaryExpression_or_mixed() async { + CompilationUnit compilationUnit = await resolveSource(''' +const c = 3 | false; +'''); + _evaluateConstant(compilationUnit, 'c', + errorCodes: [CompileTimeErrorCode.CONST_EVAL_TYPE_BOOL_INT], + experiments: [Experiments.constantUpdate2018Name]); + } + + test_visitBinaryExpression_questionQuestion_eager_notNull_notNull() async { Expression left = AstTestFactory.string2('a'); Expression right = AstTestFactory.string2('b'); Expression expression = AstTestFactory.binaryExpression( @@ -45,7 +180,7 @@ errorListener.assertNoErrors(); } - test_visitBinaryExpression_questionQuestion_null_notNull() async { + test_visitBinaryExpression_questionQuestion_eager_null_notNull() async { Expression left = AstTestFactory.nullLiteral(); Expression right = AstTestFactory.string2('b'); Expression expression = AstTestFactory.binaryExpression( @@ -61,7 +196,7 @@ errorListener.assertNoErrors(); } - test_visitBinaryExpression_questionQuestion_null_null() async { + test_visitBinaryExpression_questionQuestion_eager_null_null() async { Expression left = AstTestFactory.nullLiteral(); Expression right = AstTestFactory.nullLiteral(); Expression expression = AstTestFactory.binaryExpression( @@ -76,7 +211,84 @@ errorListener.assertNoErrors(); } - test_visitConditionalExpression_false() async { + test_visitBinaryExpression_questionQuestion_lazy_notNull_invalid() async { + CompilationUnit compilationUnit = await resolveSource(''' +const c = 'a' ?? new C(); +class C {} +'''); + DartObjectImpl result = _evaluateConstant(compilationUnit, 'c', + experiments: [Experiments.constantUpdate2018Name]); + expect(result.type, typeProvider.stringType); + expect(result.toStringValue(), 'a'); + } + + test_visitBinaryExpression_questionQuestion_lazy_notNull_notNull() async { + CompilationUnit compilationUnit = await resolveSource(''' +const c = 'a' ?? 'b'; +'''); + DartObjectImpl result = _evaluateConstant(compilationUnit, 'c', + experiments: [Experiments.constantUpdate2018Name]); + expect(result.type, typeProvider.stringType); + expect(result.toStringValue(), 'a'); + } + + test_visitBinaryExpression_questionQuestion_lazy_null_invalid() async { + CompilationUnit compilationUnit = await resolveSource(''' +const c = null ?? new C(); +class C {} +'''); + _evaluateConstant(compilationUnit, 'c', + errorCodes: [CompileTimeErrorCode.INVALID_CONSTANT], + experiments: [Experiments.constantUpdate2018Name]); + } + + test_visitBinaryExpression_questionQuestion_lazy_null_notNull() async { + CompilationUnit compilationUnit = await resolveSource(''' +const c = null ?? 'b'; +'''); + DartObjectImpl result = _evaluateConstant(compilationUnit, 'c', + experiments: [Experiments.constantUpdate2018Name]); + expect(result.type, typeProvider.stringType); + expect(result.toStringValue(), 'b'); + } + + test_visitBinaryExpression_questionQuestion_lazy_null_null() async { + CompilationUnit compilationUnit = await resolveSource(''' +const c = null ?? null; +'''); + DartObjectImpl result = _evaluateConstant(compilationUnit, 'c', + experiments: [Experiments.constantUpdate2018Name]); + expect(result.isNull, isTrue); + } + + test_visitBinaryExpression_xor_bool() async { + CompilationUnit compilationUnit = await resolveSource(''' +const c = false ^ true; +'''); + DartObjectImpl result = _evaluateConstant(compilationUnit, 'c', + experiments: [Experiments.constantUpdate2018Name]); + expect(result.type, typeProvider.boolType); + } + + test_visitBinaryExpression_xor_int() async { + CompilationUnit compilationUnit = await resolveSource(''' +const c = 3 ^ 5; +'''); + DartObjectImpl result = _evaluateConstant(compilationUnit, 'c', + experiments: [Experiments.constantUpdate2018Name]); + expect(result.type, typeProvider.intType); + } + + test_visitBinaryExpression_xor_mixed() async { + CompilationUnit compilationUnit = await resolveSource(''' +const c = 3 ^ false; +'''); + _evaluateConstant(compilationUnit, 'c', + errorCodes: [CompileTimeErrorCode.CONST_EVAL_TYPE_BOOL_INT], + experiments: [Experiments.constantUpdate2018Name]); + } + + test_visitConditionalExpression_eager_false_int_int() async { Expression thenExpression = AstTestFactory.integer(1); Expression elseExpression = AstTestFactory.integer(0); ConditionalExpression expression = AstTestFactory.conditionalExpression( @@ -88,7 +300,7 @@ errorListener.assertNoErrors(); } - test_visitConditionalExpression_nonBooleanCondition() async { + test_visitConditionalExpression_eager_invalid_int_int() async { Expression thenExpression = AstTestFactory.integer(1); Expression elseExpression = AstTestFactory.integer(0); NullLiteral conditionExpression = AstTestFactory.nullLiteral(); @@ -103,7 +315,19 @@ .assertErrorsWithCodes([CompileTimeErrorCode.CONST_EVAL_TYPE_BOOL]); } - test_visitConditionalExpression_nonConstantElse() async { + test_visitConditionalExpression_eager_true_int_int() async { + Expression thenExpression = AstTestFactory.integer(1); + Expression elseExpression = AstTestFactory.integer(0); + ConditionalExpression expression = AstTestFactory.conditionalExpression( + AstTestFactory.booleanLiteral(true), thenExpression, elseExpression); + GatheringErrorListener errorListener = new GatheringErrorListener(); + ErrorReporter errorReporter = + new ErrorReporter(errorListener, _dummySource()); + _assertValue(1, _evaluate(expression, errorReporter)); + errorListener.assertNoErrors(); + } + + test_visitConditionalExpression_eager_true_int_invalid() async { Expression thenExpression = AstTestFactory.integer(1); Expression elseExpression = AstTestFactory.identifier3("x"); ConditionalExpression expression = AstTestFactory.conditionalExpression( @@ -117,7 +341,7 @@ .assertErrorsWithCodes([CompileTimeErrorCode.INVALID_CONSTANT]); } - test_visitConditionalExpression_nonConstantThen() async { + test_visitConditionalExpression_eager_true_invalid_int() async { Expression thenExpression = AstTestFactory.identifier3("x"); Expression elseExpression = AstTestFactory.integer(0); ConditionalExpression expression = AstTestFactory.conditionalExpression( @@ -131,16 +355,263 @@ .assertErrorsWithCodes([CompileTimeErrorCode.INVALID_CONSTANT]); } - test_visitConditionalExpression_true() async { - Expression thenExpression = AstTestFactory.integer(1); - Expression elseExpression = AstTestFactory.integer(0); - ConditionalExpression expression = AstTestFactory.conditionalExpression( - AstTestFactory.booleanLiteral(true), thenExpression, elseExpression); - GatheringErrorListener errorListener = new GatheringErrorListener(); - ErrorReporter errorReporter = - new ErrorReporter(errorListener, _dummySource()); - _assertValue(1, _evaluate(expression, errorReporter)); - errorListener.assertNoErrors(); + test_visitConditionalExpression_lazy_false_int_int() async { + CompilationUnit compilationUnit = await resolveSource(''' +const c = false ? 1 : 0; +'''); + DartObjectImpl result = _evaluateConstant(compilationUnit, 'c', + experiments: [Experiments.constantUpdate2018Name]); + expect(result.type, typeProvider.intType); + expect(result.toIntValue(), 0); + } + + test_visitConditionalExpression_lazy_false_int_invalid() async { + CompilationUnit compilationUnit = await resolveSource(''' +const c = false ? 1 : new C(); +'''); + DartObjectImpl result = _evaluateConstant(compilationUnit, 'c', + errorCodes: [CompileTimeErrorCode.INVALID_CONSTANT], + experiments: [Experiments.constantUpdate2018Name]); + } + + test_visitConditionalExpression_lazy_false_invalid_int() async { + CompilationUnit compilationUnit = await resolveSource(''' +const c = false ? new C() : 0; +class C {} +'''); + DartObjectImpl result = _evaluateConstant(compilationUnit, 'c', + experiments: [Experiments.constantUpdate2018Name]); + expect(result.type, typeProvider.intType); + expect(result.toIntValue(), 0); + } + + test_visitConditionalExpression_lazy_invalid_int_int() async { + CompilationUnit compilationUnit = await resolveSource(''' +const c = 3 ? 1 : 0; +'''); + _evaluateConstant(compilationUnit, 'c', + errorCodes: [CompileTimeErrorCode.CONST_EVAL_TYPE_BOOL], + experiments: [Experiments.constantUpdate2018Name]); + } + + test_visitConditionalExpression_lazy_true_int_int() async { + CompilationUnit compilationUnit = await resolveSource(''' +const c = true ? 1 : 0; +'''); + DartObjectImpl result = _evaluateConstant(compilationUnit, 'c', + experiments: [Experiments.constantUpdate2018Name]); + expect(result.type, typeProvider.intType); + expect(result.toIntValue(), 1); + } + + test_visitConditionalExpression_lazy_true_int_invalid() async { + CompilationUnit compilationUnit = await resolveSource(''' +const c = true ? 1 : new C(); +'''); + DartObjectImpl result = _evaluateConstant(compilationUnit, 'c', + experiments: [Experiments.constantUpdate2018Name]); + expect(result.type, typeProvider.intType); + expect(result.toIntValue(), 1); + } + + test_visitConditionalExpression_lazy_true_invalid_int() async { + CompilationUnit compilationUnit = await resolveSource(''' +const c = true ? new C() : 0; +class C {} +'''); + _evaluateConstant(compilationUnit, 'c', + errorCodes: [CompileTimeErrorCode.INVALID_CONSTANT], + experiments: [Experiments.constantUpdate2018Name]); + } + + test_visitIsExpression_is_instanceOfSameClass() async { + CompilationUnit compilationUnit = await resolveSource(''' +const a = const A(); +const b = a is A; +class A { + const A(); +} +'''); + DartObjectImpl result = _evaluateConstant(compilationUnit, 'b', + experiments: [Experiments.constantUpdate2018Name]); + expect(result.type, typeProvider.boolType); + expect(result.toBoolValue(), true); + } + + test_visitIsExpression_is_instanceOfSubclass() async { + CompilationUnit compilationUnit = await resolveSource(''' +const a = const B(); +const b = a is A; +class A { + const A(); +} +class B extends A { + const B(); +} +'''); + DartObjectImpl result = _evaluateConstant(compilationUnit, 'b', + experiments: [Experiments.constantUpdate2018Name]); + expect(result.type, typeProvider.boolType); + expect(result.toBoolValue(), true); + } + + test_visitIsExpression_is_instanceOfSuperclass() async { + CompilationUnit compilationUnit = await resolveSource(''' +const a = const A(); +const b = a is B; +class A { + const A(); +} +class B extends A { + const B(); +} +'''); + DartObjectImpl result = _evaluateConstant(compilationUnit, 'b', + experiments: [Experiments.constantUpdate2018Name]); + expect(result.type, typeProvider.boolType); + expect(result.toBoolValue(), false); + } + + test_visitIsExpression_is_instanceOfUnrelatedClass() async { + CompilationUnit compilationUnit = await resolveSource(''' +const a = const A(); +const b = a is B; +class A { + const A(); +} +class B { + const B(); +} +'''); + DartObjectImpl result = _evaluateConstant(compilationUnit, 'b', + experiments: [Experiments.constantUpdate2018Name]); + expect(result.type, typeProvider.boolType); + expect(result.toBoolValue(), false); + } + + test_visitIsExpression_is_null() async { + CompilationUnit compilationUnit = await resolveSource(''' +const a = null; +const b = a is A; +class A {} +'''); + DartObjectImpl result = _evaluateConstant(compilationUnit, 'b', + experiments: [Experiments.constantUpdate2018Name]); + expect(result.type, typeProvider.boolType); + expect(result.toBoolValue(), false); + } + + test_visitIsExpression_is_null_dynamic() async { + CompilationUnit compilationUnit = await resolveSource(''' +const a = null; +const b = a is dynamic; +class A {} +'''); + DartObjectImpl result = _evaluateConstant(compilationUnit, 'b', + experiments: [Experiments.constantUpdate2018Name]); + expect(result.type, typeProvider.boolType); + expect(result.toBoolValue(), true); + } + + test_visitIsExpression_is_null_null() async { + CompilationUnit compilationUnit = await resolveSource(''' +const a = null; +const b = a is Null; +class A {} +'''); + DartObjectImpl result = _evaluateConstant(compilationUnit, 'b', + experiments: [Experiments.constantUpdate2018Name]); + expect(result.type, typeProvider.boolType); + expect(result.toBoolValue(), true); + } + + test_visitIsExpression_is_null_object() async { + CompilationUnit compilationUnit = await resolveSource(''' +const a = null; +const b = a is Object; +class A {} +'''); + DartObjectImpl result = _evaluateConstant(compilationUnit, 'b', + experiments: [Experiments.constantUpdate2018Name]); + expect(result.type, typeProvider.boolType); + expect(result.toBoolValue(), true); + } + + test_visitIsExpression_isNot_instanceOfSameClass() async { + CompilationUnit compilationUnit = await resolveSource(''' +const a = const A(); +const b = a is! A; +class A { + const A(); +} +'''); + DartObjectImpl result = _evaluateConstant(compilationUnit, 'b', + experiments: [Experiments.constantUpdate2018Name]); + expect(result.type, typeProvider.boolType); + expect(result.toBoolValue(), false); + } + + test_visitIsExpression_isNot_instanceOfSubclass() async { + CompilationUnit compilationUnit = await resolveSource(''' +const a = const B(); +const b = a is! A; +class A { + const A(); +} +class B extends A { + const B(); +} +'''); + DartObjectImpl result = _evaluateConstant(compilationUnit, 'b', + experiments: [Experiments.constantUpdate2018Name]); + expect(result.type, typeProvider.boolType); + expect(result.toBoolValue(), false); + } + + test_visitIsExpression_isNot_instanceOfSuperclass() async { + CompilationUnit compilationUnit = await resolveSource(''' +const a = const A(); +const b = a is! B; +class A { + const A(); +} +class B extends A { + const B(); +} +'''); + DartObjectImpl result = _evaluateConstant(compilationUnit, 'b', + experiments: [Experiments.constantUpdate2018Name]); + expect(result.type, typeProvider.boolType); + expect(result.toBoolValue(), true); + } + + test_visitIsExpression_isNot_instanceOfUnrelatedClass() async { + CompilationUnit compilationUnit = await resolveSource(''' +const a = const A(); +const b = a is! B; +class A { + const A(); +} +class B { + const B(); +} +'''); + DartObjectImpl result = _evaluateConstant(compilationUnit, 'b', + experiments: [Experiments.constantUpdate2018Name]); + expect(result.type, typeProvider.boolType); + expect(result.toBoolValue(), true); + } + + test_visitIsExpression_isNot_null() async { + CompilationUnit compilationUnit = await resolveSource(''' +const a = null; +const b = a is! A; +class A {} +'''); + DartObjectImpl result = _evaluateConstant(compilationUnit, 'b', + experiments: [Experiments.constantUpdate2018Name]); + expect(result.type, typeProvider.boolType); + expect(result.toBoolValue(), true); } test_visitSimpleIdentifier_className() async { @@ -148,7 +619,7 @@ const a = C; class C {} '''); - DartObjectImpl result = _evaluateConstant(compilationUnit, 'a', null); + DartObjectImpl result = _evaluateConstant(compilationUnit, 'a'); expect(result.type, typeProvider.typeType); expect(result.toTypeValue().name, 'C'); } @@ -157,7 +628,7 @@ CompilationUnit compilationUnit = await resolveSource(''' const a = dynamic; '''); - DartObjectImpl result = _evaluateConstant(compilationUnit, 'a', null); + DartObjectImpl result = _evaluateConstant(compilationUnit, 'a'); expect(result.type, typeProvider.typeType); expect(result.toTypeValue(), typeProvider.dynamicType); } @@ -170,7 +641,10 @@ DartObjectImpl six = new DartObjectImpl(typeProvider.intType, new IntState(6)); environment["b"] = six; - _assertValue(6, _evaluateConstant(compilationUnit, "a", environment)); + _assertValue( + 6, + _evaluateConstant(compilationUnit, "a", + lexicalEnvironment: environment)); } test_visitSimpleIdentifier_notInEnvironment() async { @@ -181,14 +655,17 @@ DartObjectImpl six = new DartObjectImpl(typeProvider.intType, new IntState(6)); environment["c"] = six; - _assertValue(3, _evaluateConstant(compilationUnit, "a", environment)); + _assertValue( + 3, + _evaluateConstant(compilationUnit, "a", + lexicalEnvironment: environment)); } test_visitSimpleIdentifier_withoutEnvironment() async { CompilationUnit compilationUnit = await resolveSource(r''' const a = b; const b = 3;'''); - _assertValue(3, _evaluateConstant(compilationUnit, "a", null)); + _assertValue(3, _evaluateConstant(compilationUnit, "a")); } void _assertValue(int expectedValue, DartObjectImpl result) { @@ -211,19 +688,32 @@ } DartObjectImpl _evaluateConstant(CompilationUnit compilationUnit, String name, - Map<String, DartObjectImpl> lexicalEnvironment) { + {List<ErrorCode> errorCodes, + List<String> experiments, + Map<String, DartObjectImpl> lexicalEnvironment}) { Source source = resolutionMap.elementDeclaredByCompilationUnit(compilationUnit).source; Expression expression = findTopLevelConstantExpression(compilationUnit, name); + + AnalysisOptionsImpl options = new AnalysisOptionsImpl(); + if (experiments != null) { + options..enabledExperiments = experiments; + } + GatheringErrorListener errorListener = new GatheringErrorListener(); ErrorReporter errorReporter = new ErrorReporter(errorListener, source); + DartObjectImpl result = expression.accept(new ConstantVisitor( new ConstantEvaluationEngine(typeProvider, new DeclaredVariables(), - typeSystem: typeSystem), + experiments: new Experiments(options), typeSystem: typeSystem), errorReporter, lexicalEnvironment: lexicalEnvironment)); - errorListener.assertNoErrors(); + if (errorCodes == null) { + errorListener.assertNoErrors(); + } else { + errorListener.assertErrorsWithCodes(errorCodes); + } return result; } }
diff --git a/pkg/analyzer/test/src/dart/constant/value_test.dart b/pkg/analyzer/test/src/dart/constant/value_test.dart index 1883704..6825e19 100644 --- a/pkg/analyzer/test/src/dart/constant/value_test.dart +++ b/pkg/analyzer/test/src/dart/constant/value_test.dart
@@ -94,27 +94,27 @@ } void test_bitAnd_knownInt_knownInt() { - _assertBitAnd(_intValue(2), _intValue(6), _intValue(3)); + _assertEagerAnd(_intValue(2), _intValue(6), _intValue(3)); } void test_bitAnd_knownInt_knownString() { - _assertBitAnd(null, _intValue(6), _stringValue("3")); + _assertEagerAnd(null, _intValue(6), _stringValue("3")); } void test_bitAnd_knownInt_unknownInt() { - _assertBitAnd(_intValue(null), _intValue(6), _intValue(null)); + _assertEagerAnd(_intValue(null), _intValue(6), _intValue(null)); } void test_bitAnd_knownString_knownInt() { - _assertBitAnd(null, _stringValue("6"), _intValue(3)); + _assertEagerAnd(null, _stringValue("6"), _intValue(3)); } void test_bitAnd_unknownInt_knownInt() { - _assertBitAnd(_intValue(null), _intValue(null), _intValue(3)); + _assertEagerAnd(_intValue(null), _intValue(null), _intValue(3)); } void test_bitAnd_unknownInt_unknownInt() { - _assertBitAnd(_intValue(null), _intValue(null), _intValue(null)); + _assertEagerAnd(_intValue(null), _intValue(null), _intValue(null)); } void test_bitNot_knownInt() { @@ -130,51 +130,51 @@ } void test_bitOr_knownInt_knownInt() { - _assertBitOr(_intValue(7), _intValue(6), _intValue(3)); + _assertEagerOr(_intValue(7), _intValue(6), _intValue(3)); } void test_bitOr_knownInt_knownString() { - _assertBitOr(null, _intValue(6), _stringValue("3")); + _assertEagerOr(null, _intValue(6), _stringValue("3")); } void test_bitOr_knownInt_unknownInt() { - _assertBitOr(_intValue(null), _intValue(6), _intValue(null)); + _assertEagerOr(_intValue(null), _intValue(6), _intValue(null)); } void test_bitOr_knownString_knownInt() { - _assertBitOr(null, _stringValue("6"), _intValue(3)); + _assertEagerOr(null, _stringValue("6"), _intValue(3)); } void test_bitOr_unknownInt_knownInt() { - _assertBitOr(_intValue(null), _intValue(null), _intValue(3)); + _assertEagerOr(_intValue(null), _intValue(null), _intValue(3)); } void test_bitOr_unknownInt_unknownInt() { - _assertBitOr(_intValue(null), _intValue(null), _intValue(null)); + _assertEagerOr(_intValue(null), _intValue(null), _intValue(null)); } void test_bitXor_knownInt_knownInt() { - _assertBitXor(_intValue(5), _intValue(6), _intValue(3)); + _assertEagerXor(_intValue(5), _intValue(6), _intValue(3)); } void test_bitXor_knownInt_knownString() { - _assertBitXor(null, _intValue(6), _stringValue("3")); + _assertEagerXor(null, _intValue(6), _stringValue("3")); } void test_bitXor_knownInt_unknownInt() { - _assertBitXor(_intValue(null), _intValue(6), _intValue(null)); + _assertEagerXor(_intValue(null), _intValue(6), _intValue(null)); } void test_bitXor_knownString_knownInt() { - _assertBitXor(null, _stringValue("6"), _intValue(3)); + _assertEagerXor(null, _stringValue("6"), _intValue(3)); } void test_bitXor_unknownInt_knownInt() { - _assertBitXor(_intValue(null), _intValue(null), _intValue(3)); + _assertEagerXor(_intValue(null), _intValue(null), _intValue(3)); } void test_bitXor_unknownInt_unknownInt() { - _assertBitXor(_intValue(null), _intValue(null), _intValue(null)); + _assertEagerXor(_intValue(null), _intValue(null), _intValue(null)); } void test_concatenate_knownInt_knownString() { @@ -418,6 +418,20 @@ expect(_nullValue().isNull, isTrue); } + void test_getValue_set_empty() { + Object result = _setValue().toSetValue(); + _assertInstanceOfObjectArray(result); + Set<Object> set = result as Set<Object>; + expect(set, hasLength(0)); + } + + void test_getValue_set_valid() { + Object result = _setValue(new Set.from([_intValue(23)])).toSetValue(); + _assertInstanceOfObjectArray(result); + Set<Object> set = result as Set<Object>; + expect(set, hasLength(1)); + } + void test_getValue_string_known() { String value = "twenty-three"; expect(_stringValue(value).toStringValue(), value); @@ -958,65 +972,63 @@ } void test_logicalAnd_false_false() { - _assertLogicalAnd(_boolValue(false), _boolValue(false), _boolValue(false)); + _assertLazyAnd(_boolValue(false), _boolValue(false), _boolValue(false)); } void test_logicalAnd_false_null() { - _assertLogicalAnd(_boolValue(false), _boolValue(false), _nullValue()); + _assertLazyAnd(_boolValue(false), _boolValue(false), _nullValue()); } void test_logicalAnd_false_string() { - _assertLogicalAnd( - _boolValue(false), _boolValue(false), _stringValue("false")); + _assertLazyAnd(_boolValue(false), _boolValue(false), _stringValue("false")); } void test_logicalAnd_false_true() { - _assertLogicalAnd(_boolValue(false), _boolValue(false), _boolValue(true)); + _assertLazyAnd(_boolValue(false), _boolValue(false), _boolValue(true)); } void test_logicalAnd_null_false() { expect(() { - _assertLogicalAnd(_boolValue(false), _nullValue(), _boolValue(false)); + _assertLazyAnd(_boolValue(false), _nullValue(), _boolValue(false)); }, throwsEvaluationException); } void test_logicalAnd_null_true() { expect(() { - _assertLogicalAnd(_boolValue(false), _nullValue(), _boolValue(true)); + _assertLazyAnd(_boolValue(false), _nullValue(), _boolValue(true)); }, throwsEvaluationException); } void test_logicalAnd_string_false() { expect(() { - _assertLogicalAnd( + _assertLazyAnd( _boolValue(false), _stringValue("true"), _boolValue(false)); }, throwsEvaluationException); } void test_logicalAnd_string_true() { expect(() { - _assertLogicalAnd( + _assertLazyAnd( _boolValue(false), _stringValue("false"), _boolValue(true)); }, throwsEvaluationException); } void test_logicalAnd_true_false() { - _assertLogicalAnd(_boolValue(false), _boolValue(true), _boolValue(false)); + _assertLazyAnd(_boolValue(false), _boolValue(true), _boolValue(false)); } void test_logicalAnd_true_null() { - _assertLogicalAnd(null, _boolValue(true), _nullValue()); + _assertLazyAnd(null, _boolValue(true), _nullValue()); } void test_logicalAnd_true_string() { expect(() { - _assertLogicalAnd( - _boolValue(false), _boolValue(true), _stringValue("true")); + _assertLazyAnd(_boolValue(false), _boolValue(true), _stringValue("true")); }, throwsEvaluationException); } void test_logicalAnd_true_true() { - _assertLogicalAnd(_boolValue(true), _boolValue(true), _boolValue(true)); + _assertLazyAnd(_boolValue(true), _boolValue(true), _boolValue(true)); } void test_logicalNot_false() { @@ -1042,64 +1054,62 @@ } void test_logicalOr_false_false() { - _assertLogicalOr(_boolValue(false), _boolValue(false), _boolValue(false)); + _assertLazyOr(_boolValue(false), _boolValue(false), _boolValue(false)); } void test_logicalOr_false_null() { - _assertLogicalOr(null, _boolValue(false), _nullValue()); + _assertLazyOr(null, _boolValue(false), _nullValue()); } void test_logicalOr_false_string() { expect(() { - _assertLogicalOr( + _assertLazyOr( _boolValue(false), _boolValue(false), _stringValue("false")); }, throwsEvaluationException); } void test_logicalOr_false_true() { - _assertLogicalOr(_boolValue(true), _boolValue(false), _boolValue(true)); + _assertLazyOr(_boolValue(true), _boolValue(false), _boolValue(true)); } void test_logicalOr_null_false() { expect(() { - _assertLogicalOr(_boolValue(false), _nullValue(), _boolValue(false)); + _assertLazyOr(_boolValue(false), _nullValue(), _boolValue(false)); }, throwsEvaluationException); } void test_logicalOr_null_true() { expect(() { - _assertLogicalOr(_boolValue(true), _nullValue(), _boolValue(true)); + _assertLazyOr(_boolValue(true), _nullValue(), _boolValue(true)); }, throwsEvaluationException); } void test_logicalOr_string_false() { expect(() { - _assertLogicalOr( - _boolValue(false), _stringValue("true"), _boolValue(false)); + _assertLazyOr(_boolValue(false), _stringValue("true"), _boolValue(false)); }, throwsEvaluationException); } void test_logicalOr_string_true() { expect(() { - _assertLogicalOr( - _boolValue(true), _stringValue("false"), _boolValue(true)); + _assertLazyOr(_boolValue(true), _stringValue("false"), _boolValue(true)); }, throwsEvaluationException); } void test_logicalOr_true_false() { - _assertLogicalOr(_boolValue(true), _boolValue(true), _boolValue(false)); + _assertLazyOr(_boolValue(true), _boolValue(true), _boolValue(false)); } void test_logicalOr_true_null() { - _assertLogicalOr(_boolValue(true), _boolValue(true), _nullValue()); + _assertLazyOr(_boolValue(true), _boolValue(true), _nullValue()); } void test_logicalOr_true_string() { - _assertLogicalOr(_boolValue(true), _boolValue(true), _stringValue("true")); + _assertLazyOr(_boolValue(true), _boolValue(true), _stringValue("true")); } void test_logicalOr_true_true() { - _assertLogicalOr(_boolValue(true), _boolValue(true), _boolValue(true)); + _assertLazyOr(_boolValue(true), _boolValue(true), _boolValue(true)); } void test_minus_knownDouble_knownDouble() { @@ -1480,24 +1490,6 @@ } /** - * Assert that the result of bit-anding the [left] and [right] operands is the - * [expected] value, or that the operation throws an exception if the expected - * value is `null`. - */ - void _assertBitAnd( - DartObjectImpl expected, DartObjectImpl left, DartObjectImpl right) { - if (expected == null) { - expect(() { - left.bitAnd(_typeProvider, right); - }, throwsEvaluationException); - } else { - DartObjectImpl result = left.bitAnd(_typeProvider, right); - expect(result, isNotNull); - expect(result, expected); - } - } - - /** * Assert that the bit-not of the [operand] is the [expected] value, or that * the operation throws an exception if the expected value is `null`. */ @@ -1514,42 +1506,6 @@ } /** - * Assert that the result of bit-oring the [left] and [right] operands is the - * [expected] value, or that the operation throws an exception if the expected - * value is `null`. - */ - void _assertBitOr( - DartObjectImpl expected, DartObjectImpl left, DartObjectImpl right) { - if (expected == null) { - expect(() { - left.bitOr(_typeProvider, right); - }, throwsEvaluationException); - } else { - DartObjectImpl result = left.bitOr(_typeProvider, right); - expect(result, isNotNull); - expect(result, expected); - } - } - - /** - * Assert that the result of bit-xoring the [left] and [right] operands is the - * [expected] value, or that the operation throws an exception if the expected - * value is `null`. - */ - void _assertBitXor( - DartObjectImpl expected, DartObjectImpl left, DartObjectImpl right) { - if (expected == null) { - expect(() { - left.bitXor(_typeProvider, right); - }, throwsEvaluationException); - } else { - DartObjectImpl result = left.bitXor(_typeProvider, right); - expect(result, isNotNull); - expect(result, expected); - } - } - - /** * Assert that the result of concatenating the [left] and [right] operands is * the [expected] value, or that the operation throws an exception if the * expected value is `null`. @@ -1586,6 +1542,60 @@ } /** + * Assert that the result of bit-anding the [left] and [right] operands is the + * [expected] value, or that the operation throws an exception if the expected + * value is `null`. + */ + void _assertEagerAnd( + DartObjectImpl expected, DartObjectImpl left, DartObjectImpl right) { + if (expected == null) { + expect(() { + left.eagerAnd(_typeProvider, right, false); + }, throwsEvaluationException); + } else { + DartObjectImpl result = left.eagerAnd(_typeProvider, right, false); + expect(result, isNotNull); + expect(result, expected); + } + } + + /** + * Assert that the result of bit-oring the [left] and [right] operands is the + * [expected] value, or that the operation throws an exception if the expected + * value is `null`. + */ + void _assertEagerOr( + DartObjectImpl expected, DartObjectImpl left, DartObjectImpl right) { + if (expected == null) { + expect(() { + left.eagerOr(_typeProvider, right, false); + }, throwsEvaluationException); + } else { + DartObjectImpl result = left.eagerOr(_typeProvider, right, false); + expect(result, isNotNull); + expect(result, expected); + } + } + + /** + * Assert that the result of bit-xoring the [left] and [right] operands is the + * [expected] value, or that the operation throws an exception if the expected + * value is `null`. + */ + void _assertEagerXor( + DartObjectImpl expected, DartObjectImpl left, DartObjectImpl right) { + if (expected == null) { + expect(() { + left.eagerXor(_typeProvider, right, false); + }, throwsEvaluationException); + } else { + DartObjectImpl result = left.eagerXor(_typeProvider, right, false); + expect(result, isNotNull); + expect(result, expected); + } + } + + /** * Assert that the result of comparing the [left] and [right] operands for * equality is the [expected] value, or that the operation throws an exception * if the expected value is `null`. @@ -1673,6 +1683,42 @@ } /** + * Assert that the result of logical-anding the [left] and [right] operands is + * the [expected] value, or that the operation throws an exception if the + * expected value is `null`. + */ + void _assertLazyAnd( + DartObjectImpl expected, DartObjectImpl left, DartObjectImpl right) { + if (expected == null) { + expect(() { + left.lazyAnd(_typeProvider, () => right); + }, throwsEvaluationException); + } else { + DartObjectImpl result = left.lazyAnd(_typeProvider, () => right); + expect(result, isNotNull); + expect(result, expected); + } + } + + /** + * Assert that the result of logical-oring the [left] and [right] operands is + * the [expected] value, or that the operation throws an exception if the + * expected value is `null`. + */ + void _assertLazyOr( + DartObjectImpl expected, DartObjectImpl left, DartObjectImpl right) { + if (expected == null) { + expect(() { + left.lazyOr(_typeProvider, () => right); + }, throwsEvaluationException); + } else { + DartObjectImpl result = left.lazyOr(_typeProvider, () => right); + expect(result, isNotNull); + expect(result, expected); + } + } + + /** * Assert that the result of comparing the [left] and [right] operands is the * [expected] value, or that the operation throws an exception if the expected * value is `null`. @@ -1709,24 +1755,6 @@ } /** - * Assert that the result of logical-anding the [left] and [right] operands is - * the [expected] value, or that the operation throws an exception if the - * expected value is `null`. - */ - void _assertLogicalAnd( - DartObjectImpl expected, DartObjectImpl left, DartObjectImpl right) { - if (expected == null) { - expect(() { - left.logicalAnd(_typeProvider, () => right); - }, throwsEvaluationException); - } else { - DartObjectImpl result = left.logicalAnd(_typeProvider, () => right); - expect(result, isNotNull); - expect(result, expected); - } - } - - /** * Assert that the logical-not of the [operand] is the [expected] value, or * that the operation throws an exception if the expected value is `null`. */ @@ -1743,24 +1771,6 @@ } /** - * Assert that the result of logical-oring the [left] and [right] operands is - * the [expected] value, or that the operation throws an exception if the - * expected value is `null`. - */ - void _assertLogicalOr( - DartObjectImpl expected, DartObjectImpl left, DartObjectImpl right) { - if (expected == null) { - expect(() { - left.logicalOr(_typeProvider, () => right); - }, throwsEvaluationException); - } else { - DartObjectImpl result = left.logicalOr(_typeProvider, () => right); - expect(result, isNotNull); - expect(result, expected); - } - } - - /** * Assert that the result of subtracting the [left] and [right] operands is * the [expected] value, or that the operation throws an exception if the * expected value is `null`. @@ -1975,6 +1985,11 @@ return new DartObjectImpl(_typeProvider.nullType, NumState.UNKNOWN_VALUE); } + DartObjectImpl _setValue([Set<DartObjectImpl> elements]) { + return new DartObjectImpl(_typeProvider.setType, + new SetState(elements ?? new Set<DartObjectImpl>())); + } + DartObjectImpl _stringValue(String value) { if (value == null) { return new DartObjectImpl(
diff --git a/pkg/analyzer/test/src/dart/element/element_test.dart b/pkg/analyzer/test/src/dart/element/element_test.dart index 3a0bc36..dbebb31 100644 --- a/pkg/analyzer/test/src/dart/element/element_test.dart +++ b/pkg/analyzer/test/src/dart/element/element_test.dart
@@ -47,6 +47,7 @@ @reflectiveTest class ClassElementImplTest extends EngineTestCase { + @deprecated void test_computeNode_ClassDeclaration() { AnalysisContextHelper contextHelper = new AnalysisContextHelper(); AnalysisContext context = contextHelper.context; @@ -100,6 +101,7 @@ } } + @deprecated void test_computeNode_ClassTypeAlias() { AnalysisContextHelper contextHelper = new AnalysisContextHelper(); AnalysisContext context = contextHelper.context; @@ -130,8 +132,8 @@ new TestElementResynthesizer(context, {location: classA}); ClassElementHandle classAHandle = new ClassElementHandle(resynthesizer, location); - ClassElementImpl classB = - ElementFactory.classElement("B", new InterfaceTypeImpl(classAHandle)); + ClassElementImpl classB = new ClassElementImpl('B', 0) + ..supertype = new InterfaceTypeImpl(classAHandle); classB.mixinApplication = true; expect(classB.constructors, hasLength(1)); @@ -1194,6 +1196,7 @@ @reflectiveTest class FieldElementImplTest extends EngineTestCase { + @deprecated void test_computeNode() { AnalysisContextHelper contextHelper = new AnalysisContextHelper(); AnalysisContext context = contextHelper.context; @@ -3692,8 +3695,8 @@ class LibraryElementImplTest extends EngineTestCase { void test_creation() { expect( - new LibraryElementImpl.forNode( - createAnalysisContext(), AstTestFactory.libraryIdentifier2(["l"])), + new LibraryElementImpl.forNode(createAnalysisContext(), null, + AstTestFactory.libraryIdentifier2(["l"])), isNotNull); } @@ -3780,7 +3783,7 @@ void test_setImports() { AnalysisContext context = createAnalysisContext(); LibraryElementImpl library = new LibraryElementImpl.forNode( - context, AstTestFactory.libraryIdentifier2(["l1"])); + context, null, AstTestFactory.libraryIdentifier2(["l1"])); List<ImportElementImpl> expectedImports = [ ElementFactory.importFor(ElementFactory.library(context, "l2"), null), ElementFactory.importFor(ElementFactory.library(context, "l3"), null) @@ -3799,6 +3802,7 @@ @reflectiveTest class MethodElementImplTest extends EngineTestCase { + @deprecated void test_computeNode() { AnalysisContextHelper contextHelper = new AnalysisContextHelper(); AnalysisContext context = contextHelper.context; @@ -3829,6 +3833,7 @@ } } + @deprecated void test_computeNode_withoutFunctionBody() { AnalysisOptionsImpl options = new AnalysisOptionsImpl(); options.analyzeFunctionBodies = false; @@ -3908,6 +3913,7 @@ @reflectiveTest class ParameterElementImplTest extends EngineTestCase { + @deprecated void test_computeNode_DefaultFormalParameter() { AnalysisContextHelper contextHelper = new AnalysisContextHelper(); AnalysisContext context = contextHelper.context; @@ -3927,6 +3933,7 @@ } } + @deprecated void test_computeNode_FieldFormalParameter() { AnalysisContextHelper contextHelper = new AnalysisContextHelper(); AnalysisContext context = contextHelper.context; @@ -3951,6 +3958,7 @@ } } + @deprecated void test_computeNode_FunctionTypedFormalParameter() { AnalysisContextHelper contextHelper = new AnalysisContextHelper(); AnalysisContext context = contextHelper.context; @@ -3970,6 +3978,7 @@ } } + @deprecated void test_computeNode_SimpleFormalParameter() { AnalysisContextHelper contextHelper = new AnalysisContextHelper(); AnalysisContext context = contextHelper.context; @@ -4027,7 +4036,7 @@ Map<ElementLocation, Element> locationMap; TestElementResynthesizer(AnalysisContext context, this.locationMap) - : super(context); + : super(context, null); @override Element getElement(ElementLocation location) {
diff --git a/pkg/analyzer/test/src/dart/element/function_type_test.dart b/pkg/analyzer/test/src/dart/element/function_type_test.dart index 16b9189..975952b 100644 --- a/pkg/analyzer/test/src/dart/element/function_type_test.dart +++ b/pkg/analyzer/test/src/dart/element/function_type_test.dart
@@ -1,13 +1,13 @@ -// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. -import 'package:analyzer/analyzer.dart'; import 'package:analyzer/dart/element/element.dart'; import 'package:analyzer/dart/element/type.dart'; import 'package:analyzer/src/dart/element/element.dart'; import 'package:analyzer/src/dart/element/member.dart'; import 'package:analyzer/src/dart/element/type.dart'; +import 'package:analyzer/src/generated/utilities_dart.dart'; import 'package:test/test.dart'; import 'package:test_reflective_loader/test_reflective_loader.dart';
diff --git a/pkg/analyzer/test/src/dart/resolution/assignment_test.dart b/pkg/analyzer/test/src/dart/resolution/assignment_test.dart index c07703f..ba409b4 100644 --- a/pkg/analyzer/test/src/dart/resolution/assignment_test.dart +++ b/pkg/analyzer/test/src/dart/resolution/assignment_test.dart
@@ -22,7 +22,7 @@ class AssignmentDriverResolutionTest extends DriverResolutionTest with AssignmentResolutionMixin {} -abstract class AssignmentResolutionMixin implements ResolutionTest { +mixin AssignmentResolutionMixin implements ResolutionTest { test_compound_indexExpression() async { addTestFile(r''' main() {
diff --git a/pkg/analyzer/test/src/dart/resolution/class_alias_test.dart b/pkg/analyzer/test/src/dart/resolution/class_alias_test.dart index aea7e0f..6a6388a 100644 --- a/pkg/analyzer/test/src/dart/resolution/class_alias_test.dart +++ b/pkg/analyzer/test/src/dart/resolution/class_alias_test.dart
@@ -19,7 +19,7 @@ class ClassAliasDriverResolutionTest extends DriverResolutionTest with ClassAliasResolutionMixin {} -abstract class ClassAliasResolutionMixin implements ResolutionTest { +mixin ClassAliasResolutionMixin implements ResolutionTest { test_defaultConstructor() async { addTestFile(r''' class A {}
diff --git a/pkg/analyzer/test/src/dart/resolution/class_test.dart b/pkg/analyzer/test/src/dart/resolution/class_test.dart index f825033..0fecf73 100644 --- a/pkg/analyzer/test/src/dart/resolution/class_test.dart +++ b/pkg/analyzer/test/src/dart/resolution/class_test.dart
@@ -21,7 +21,7 @@ class ClassDriverResolutionTest extends DriverResolutionTest with ClassResolutionMixin {} -abstract class ClassResolutionMixin implements ResolutionTest { +mixin ClassResolutionMixin implements ResolutionTest { test_abstractSuperMemberReference_getter() async { addTestFile(r''' abstract class A { @@ -55,28 +55,7 @@ assertTestErrors([CompileTimeErrorCode.ABSTRACT_SUPER_MEMBER_REFERENCE]); assertElement( findNode.simple('foo; // ref'), - findElement.getter('foo', className: 'Foo'), - ); - } - - test_abstractSuperMemberReference_method_invocation() async { - addTestFile(r''' -abstract class A { - foo(); -} -abstract class B extends A { - bar() { - super.foo(); // ref - } - - foo() {} // does not matter -} -'''); - await resolveTestFile(); - assertTestErrors([CompileTimeErrorCode.ABSTRACT_SUPER_MEMBER_REFERENCE]); - assertElement( - findNode.simple('foo(); // ref'), - findElement.method('foo', of: 'A'), + findElement.getter('foo', of: 'Foo'), ); } @@ -96,31 +75,6 @@ assertElement(findNode.simple('foo; // ref'), findElement.method('foo')); } - test_abstractSuperMemberReference_OK_mixinHasConcrete2_method() async { - addTestFile(''' -class A { -} - -class M { - void foo() {} -} - -class B = A with M; - -class C extends B { - void bar() { - super.foo(); // ref - } -} -'''); - await resolveTestFile(); - assertNoTestErrors(); - assertElement( - findNode.simple('foo(); // ref'), - findElement.method('foo', of: 'M'), - ); - } - test_abstractSuperMemberReference_OK_superHasConcrete_mixinHasAbstract_method() async { addTestFile(''' class A { @@ -163,31 +117,7 @@ assertNoTestErrors(); assertElement( findNode.simple('foo; // ref'), - findElement.getter('foo', className: 'A'), - ); - } - - test_abstractSuperMemberReference_OK_superSuperHasConcrete_method() async { - addTestFile(''' -abstract class A { - void foo() {} -} - -abstract class B extends A { - void foo(); -} - -class C extends B { - void bar() { - super.foo(); // ref - } -} -'''); - await resolveTestFile(); - assertNoTestErrors(); - assertElement( - findNode.simple('foo(); // ref'), - findElement.method('foo', of: 'A'), + findElement.getter('foo', of: 'A'), ); } @@ -1371,6 +1301,32 @@ assertNoTestErrors(); } + test_error_mismatchedGetterAndSetterTypes_OK_setterParameter_0() async { + addTestFile(r''' +class C { + int get foo => 0; + set foo() {} +} +'''); + await resolveTestFile(); + assertTestErrors([ + CompileTimeErrorCode.WRONG_NUMBER_OF_PARAMETERS_FOR_SETTER, + ]); + } + + test_error_mismatchedGetterAndSetterTypes_OK_setterParameter_2() async { + addTestFile(r''' +class C { + int get foo => 0; + set foo(String p1, String p2) {} +} +'''); + await resolveTestFile(); + assertTestErrors([ + CompileTimeErrorCode.WRONG_NUMBER_OF_PARAMETERS_FOR_SETTER, + ]); + } + test_error_mismatchedGetterAndSetterTypes_superGetter() async { addTestFile(r''' class A { @@ -1483,6 +1439,22 @@ ]); } + test_issue32815() async { + addTestFile(r''' +class A<T> extends B<T> {} +class B<T> extends A<T> {} +class C<T> extends B<T> implements I<T> {} + +abstract class I<T> {} + +main() { + Iterable<I<int>> x = [new C()]; +} +'''); + await resolveTestFile(); + assertHasTestErrors(); + } + test_recursiveInterfaceInheritance_extends() async { addTestFile(r''' class A extends B {} @@ -1670,7 +1642,10 @@ } }'''); await resolveTestFile(); - assertTestErrors([StaticTypeWarningCode.UNDEFINED_SUPER_OPERATOR]); + assertTestErrors([ + StaticTypeWarningCode.UNDEFINED_SUPER_OPERATOR, + StaticTypeWarningCode.UNDEFINED_SUPER_OPERATOR, + ]); } test_undefinedSuperOperator_indexGetter() async {
diff --git a/pkg/analyzer/test/src/dart/resolution/comment_test.dart b/pkg/analyzer/test/src/dart/resolution/comment_test.dart new file mode 100644 index 0000000..8a4d787 --- /dev/null +++ b/pkg/analyzer/test/src/dart/resolution/comment_test.dart
@@ -0,0 +1,261 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:test_reflective_loader/test_reflective_loader.dart'; + +import 'driver_resolution.dart'; +import 'resolution.dart'; +import 'task_resolution.dart'; + +main() { + defineReflectiveSuite(() { + defineReflectiveTests(CommentDriverResolutionTest); + defineReflectiveTests(CommentTaskResolutionTest); + }); +} + +@reflectiveTest +class CommentDriverResolutionTest extends DriverResolutionTest + with ClassAliasResolutionMixin {} + +mixin ClassAliasResolutionMixin implements ResolutionTest { + test_error_unqualifiedReferenceToNonLocalStaticMember() async { + addTestFile(r''' +class A { + static void foo() {} +} + +/// [foo] +class B extends A {} +'''); + await resolveTestFile(); + assertNoTestErrors(); + + assertElement( + findNode.simple('foo]'), + findElement.method('foo', of: 'A'), + ); + } + + test_new() async { + addTestFile(r''' +class A { + A(); + A.named(); +} + +/// [new A] or [new A.named] +main() {} +'''); + await resolveTestFile(); + assertNoTestErrors(); + + assertElement( + findNode.simple('A]'), + findElement.unnamedConstructor('A'), + ); + assertElement( + findNode.simple('A.named]'), + findElement.class_('A'), + ); + assertElement( + findNode.simple('named]'), + findElement.constructor('named', className: 'A'), + ); + } + + test_identifier_beforeConstructor() async { + addTestFile(r''' +class A { + /// [p] + A(int p); +}'''); + await resolveTestFile(); + assertNoTestErrors(); + + assertElement( + findNode.simple('p]'), + findElement.parameter('p'), + ); + } + + test_identifier_beforeEnum() async { + addTestFile(r''' +/// This is the [Samurai] kind. +enum Samurai { + /// Use [int]. + WITH_SWORD, + /// Like [WITH_SWORD], but only without one. + WITHOUT_SWORD +}'''); + await resolveTestFile(); + assertNoTestErrors(); + + assertElement( + findNode.simple('Samurai]'), + findElement.enum_('Samurai'), + ); + assertElement( + findNode.simple('int]'), + intElement, + ); + assertElement( + findNode.simple('WITH_SWORD]'), + findElement.getter('WITH_SWORD'), + ); + } + + test_identifier_beforeFunction_blockBody() async { + addTestFile(r''' +/// [p] +foo(int p) {} +'''); + await resolveTestFile(); + assertNoTestErrors(); + + assertElement( + findNode.simple('p]'), + findElement.parameter('p'), + ); + } + + test_identifier_parameter_functionTyped() async { + addTestFile(r''' +/// [bar] +foo(int bar()) {} +'''); + await resolveTestFile(); + assertNoTestErrors(); + + assertElement( + findNode.simple('bar]'), + findElement.parameter('bar'), + ); + } + + test_identifier_beforeFunction_expressionBody() async { + addTestFile(r''' +/// [p] +foo(int p) => null; +'''); + await resolveTestFile(); + assertNoTestErrors(); + + assertElement( + findNode.simple('p]'), + findElement.parameter('p'), + ); + } + + test_identifier_beforeFunctionTypeAlias() async { + addTestFile(r''' +/// [p] +typedef Foo(int p); +'''); + await resolveTestFile(); + assertNoTestErrors(); + + assertElement( + findNode.simple('p]'), + findElement.parameter('p'), + ); + } + + test_identifier_beforeGenericTypeAlias() async { + addTestFile(r''' +/// Can resolve [T], [S], and [p]. +typedef Foo<T> = Function<S>(int p); +'''); + await resolveTestFile(); + assertNoTestErrors(); + + assertElement( + findNode.simple('T]'), + findElement.typeParameter('T'), + ); + assertElement(findNode.simple('S]'), findElement.typeParameter('S')); + assertElement( + findNode.simple('p]'), + findElement.parameter('p'), + ); + } + + test_identifier_beforeGetter() async { + addTestFile(r''' +/// [int] +get g => null; +'''); + await resolveTestFile(); + assertNoTestErrors(); + + assertElement(findNode.simple('int]'), intElement); + } + + test_identifier_beforeMethod() async { + addTestFile(r''' +abstract class A { + /// [p1] + ma(int p1); + + /// [p2] + mb(int p2); + + /// [p3] and [p4] + mc(int p3, p4()); + + /// [p5] + md(int p5, {int p6}); +} +'''); + await resolveTestFile(); + assertNoTestErrors(); + + assertElement(findNode.simple('p1]'), findElement.parameter('p1')); + assertElement(findNode.simple('p2]'), findElement.parameter('p2')); + assertElement(findNode.simple('p3]'), findElement.parameter('p3')); + assertElement(findNode.simple('p4]'), findElement.parameter('p4')); + assertElement(findNode.simple('p5]'), findElement.parameter('p5')); + } + + test_identifier_beforeClass() async { + addTestFile(r''' +/// [foo] +class A { + foo() {} +} +'''); + await resolveTestFile(); + assertNoTestErrors(); + + assertElement( + findNode.simple('foo]'), + findElement.method('foo'), + ); + } + + test_identifier_setter() async { + addTestFile(r''' +class A { + /// [x] in A + mA() {} + set x(value) {} +} + +class B extends A { + /// [x] in B + mB() {} +} +'''); + await resolveTestFile(); + assertNoTestErrors(); + + var x = findElement.setter('x', className: 'A'); + assertElement(findNode.simple('x] in A'), x); + assertElement(findNode.simple('x] in B'), x); + } +} + +@reflectiveTest +class CommentTaskResolutionTest extends TaskResolutionTest + with ClassAliasResolutionMixin {}
diff --git a/pkg/analyzer/test/src/dart/resolution/constant_test.dart b/pkg/analyzer/test/src/dart/resolution/constant_test.dart index 53a5c74..4ba17ed 100644 --- a/pkg/analyzer/test/src/dart/resolution/constant_test.dart +++ b/pkg/analyzer/test/src/dart/resolution/constant_test.dart
@@ -3,6 +3,7 @@ // BSD-style license that can be found in the LICENSE file. import 'package:analyzer/src/dart/element/element.dart'; +import 'package:analyzer/src/error/codes.dart'; import 'package:test/test.dart'; import 'package:test_reflective_loader/test_reflective_loader.dart'; @@ -20,7 +21,67 @@ @reflectiveTest class ConstantDriverTest extends DriverResolutionTest with ConstantMixin {} -abstract class ConstantMixin implements ResolutionTest { +mixin ConstantMixin implements ResolutionTest { + test_annotation_constructor_named() async { + newFile('/test/lib/a.dart', content: r''' +class A { + final int f; + const A.named(this.f); +} +'''); + + newFile('/test/lib/b.dart', content: r''' +import 'a.dart'; + +@A.named(42) +class B {} +'''); + + addTestFile(r''' +import 'b.dart'; + +B b; +'''); + await resolveTestFile(); + assertNoTestErrors(); + + var classB = findNode.typeName('B b;').name.staticElement; + var annotation = classB.metadata.single; + var value = annotation.computeConstantValue(); + expect(value, isNotNull); + expect(value.getField('f').toIntValue(), 42); + } + + test_annotation_constructor_unnamed() async { + newFile('/test/lib/a.dart', content: r''' +class A { + final int f; + const A(this.f); +} +'''); + + newFile('/test/lib/b.dart', content: r''' +import 'a.dart'; + +@A(42) +class B {} +'''); + + addTestFile(r''' +import 'b.dart'; + +B b; +'''); + await resolveTestFile(); + assertNoTestErrors(); + + var classB = findNode.typeName('B b;').name.staticElement; + var annotation = classB.metadata.single; + var value = annotation.computeConstantValue(); + expect(value, isNotNull); + expect(value.getField('f').toIntValue(), 42); + } + test_constantValue_defaultParameter_noDefaultValue() async { newFile('/test/lib/a.dart', content: r''' class A { @@ -70,6 +131,25 @@ var value = node.elementAnnotation.constantValue; expect(value.getField('(super)').getField('f').toIntValue(), 42); } + + test_constNotInitialized() async { + addTestFile(r''' +class B { + const B(_); +} + +class C extends B { + static const a; + const C() : super(a); +} +'''); + await resolveTestFile(); + assertTestErrors([ + CompileTimeErrorCode.NON_CONSTANT_VALUE_IN_INITIALIZER, + CompileTimeErrorCode.CONST_NOT_INITIALIZED, + CompileTimeErrorCode.CONST_NOT_INITIALIZED, + ]); + } } @reflectiveTest
diff --git a/pkg/analyzer/test/src/dart/resolution/driver_resolution.dart b/pkg/analyzer/test/src/dart/resolution/driver_resolution.dart index fb034da..e5315a5 100644 --- a/pkg/analyzer/test/src/dart/resolution/driver_resolution.dart +++ b/pkg/analyzer/test/src/dart/resolution/driver_resolution.dart
@@ -1,4 +1,4 @@ -// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. @@ -13,14 +13,13 @@ import 'package:analyzer/src/generated/sdk.dart'; import 'package:analyzer/src/generated/source.dart'; import 'package:analyzer/src/source/package_map_resolver.dart'; +import 'package:analyzer/src/test_utilities/mock_sdk.dart'; import 'package:analyzer/src/test_utilities/resource_provider_mixin.dart'; -import '../../context/mock_sdk.dart'; import 'resolution.dart'; /// [AnalysisDriver] based implementation of [ResolutionTest]. -class DriverResolutionTest extends Object - with ResourceProviderMixin, ResolutionTest { +class DriverResolutionTest with ResourceProviderMixin, ResolutionTest { final ByteStore byteStore = new MemoryByteStore(); final StringBuffer logBuffer = new StringBuffer(); @@ -32,7 +31,7 @@ @override Future<TestAnalysisResult> resolveFile(String path) async { - AnalysisResult result = await driver.getResult(path); + var result = await driver.getResult(path); return new TestAnalysisResult( path, result.content,
diff --git a/pkg/analyzer/test/src/dart/resolution/enum_test.dart b/pkg/analyzer/test/src/dart/resolution/enum_test.dart index 930ab7c..ff350fb 100644 --- a/pkg/analyzer/test/src/dart/resolution/enum_test.dart +++ b/pkg/analyzer/test/src/dart/resolution/enum_test.dart
@@ -21,7 +21,7 @@ class EnumDriverResolutionTest extends DriverResolutionTest with EnumResolutionMixin {} -abstract class EnumResolutionMixin implements ResolutionTest { +mixin EnumResolutionMixin implements ResolutionTest { test_error_conflictingStaticAndInstance_index() async { addTestFile(r''' enum E {
diff --git a/pkg/analyzer/test/src/dart/resolution/find_element.dart b/pkg/analyzer/test/src/dart/resolution/find_element.dart index 4eadf43..d408980 100644 --- a/pkg/analyzer/test/src/dart/resolution/find_element.dart +++ b/pkg/analyzer/test/src/dart/resolution/find_element.dart
@@ -115,9 +115,16 @@ fail('Not found generic type alias: $name'); } - PropertyAccessorElement getter(String name, {String className}) { + PropertyAccessorElement getter(String name, {String of}) { + for (var enum_ in unitElement.enums) { + for (var accessor in enum_.accessors) { + if (accessor.isGetter && accessor.displayName == name) { + return accessor; + } + } + } for (var class_ in unitElement.types) { - if (className != null && class_.name != className) { + if (of != null && class_.name != of) { continue; } for (var accessor in class_.accessors) { @@ -150,6 +157,25 @@ return class_(name).type; } + FunctionElement localFunction(String name) { + FunctionElement result; + unit.accept(new FunctionAstVisitor( + functionDeclarationStatement: (node) { + var element = node.functionDeclaration.declaredElement; + if (element is FunctionElement) { + if (result != null) { + throw new StateError('Local function name $name is not unique.'); + } + result = element; + } + }, + )); + if (result == null) { + fail('Not found local function: $name'); + } + return result; + } + LocalVariableElement localVar(String name) { LocalVariableElement result; unit.accept(new FunctionAstVisitor( @@ -318,6 +344,9 @@ for (var type in unitElement.functionTypeAliases) { type.typeParameters.forEach(consider); + if (type is GenericTypeAliasElement) { + type.function.typeParameters.forEach(consider); + } } for (var type in unitElement.types) { type.typeParameters.forEach(consider);
diff --git a/pkg/analyzer/test/src/dart/resolution/find_node.dart b/pkg/analyzer/test/src/dart/resolution/find_node.dart index 67271af..08de2f9 100644 --- a/pkg/analyzer/test/src/dart/resolution/find_node.dart +++ b/pkg/analyzer/test/src/dart/resolution/find_node.dart
@@ -1,4 +1,4 @@ -// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. @@ -28,6 +28,10 @@ return _node(search, (n) => n is CascadeExpression); } + ClassDeclaration classDeclaration(String search) { + return _node(search, (n) => n is ClassDeclaration); + } + CommentReference commentReference(String search) { return _node(search, (n) => n is CommentReference); } @@ -158,7 +162,7 @@ var node = new NodeLocator2(index).searchWithin(unit); expect(node, isNotNull); - var result = node.getAncestor(predicate); + var result = node.thisOrAncestorMatching(predicate); expect(result, isNotNull); return result; }
diff --git a/pkg/analyzer/test/src/dart/resolution/for_in_test.dart b/pkg/analyzer/test/src/dart/resolution/for_in_test.dart index fdbdd76..7ec1a40 100644 --- a/pkg/analyzer/test/src/dart/resolution/for_in_test.dart +++ b/pkg/analyzer/test/src/dart/resolution/for_in_test.dart
@@ -20,7 +20,7 @@ class ForInDriverResolutionTest extends DriverResolutionTest with ForInResolutionMixin {} -abstract class ForInResolutionMixin implements ResolutionTest { +mixin ForInResolutionMixin implements ResolutionTest { test_importPrefix_asIterable() async { // TODO(scheglov) Remove this test (already tested as import prefix). // TODO(scheglov) Move other for-in tests here.
diff --git a/pkg/analyzer/test/src/dart/resolution/function_ast_visitor.dart b/pkg/analyzer/test/src/dart/resolution/function_ast_visitor.dart index 82ae780..f3c951b 100644 --- a/pkg/analyzer/test/src/dart/resolution/function_ast_visitor.dart +++ b/pkg/analyzer/test/src/dart/resolution/function_ast_visitor.dart
@@ -7,10 +7,23 @@ /// [RecursiveAstVisitor] that delegates visit methods to functions. class FunctionAstVisitor extends RecursiveAstVisitor<void> { + final void Function(FunctionDeclarationStatement) + functionDeclarationStatement; final void Function(SimpleIdentifier) simpleIdentifier; final void Function(VariableDeclaration) variableDeclaration; - FunctionAstVisitor({this.simpleIdentifier, this.variableDeclaration}); + FunctionAstVisitor( + {this.functionDeclarationStatement, + this.simpleIdentifier, + this.variableDeclaration}); + + @override + void visitFunctionDeclarationStatement(FunctionDeclarationStatement node) { + if (functionDeclarationStatement != null) { + functionDeclarationStatement(node); + } + super.visitFunctionDeclarationStatement(node); + } @override void visitSimpleIdentifier(SimpleIdentifier node) {
diff --git a/pkg/analyzer/test/src/dart/resolution/generic_type_alias_test.dart b/pkg/analyzer/test/src/dart/resolution/generic_type_alias_test.dart index 7f24421a..2e64644 100644 --- a/pkg/analyzer/test/src/dart/resolution/generic_type_alias_test.dart +++ b/pkg/analyzer/test/src/dart/resolution/generic_type_alias_test.dart
@@ -2,6 +2,7 @@ // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. +import 'package:analyzer/src/error/codes.dart'; import 'package:test/test.dart'; import 'package:test_reflective_loader/test_reflective_loader.dart'; @@ -20,7 +21,111 @@ class GenericTypeAliasDriverResolutionTest extends DriverResolutionTest with GenericTypeAliasResolutionMixin {} -abstract class GenericTypeAliasResolutionMixin implements ResolutionTest { +mixin GenericTypeAliasResolutionMixin implements ResolutionTest { + test_genericFunctionTypeCannotBeTypeArgument_def_class() async { + addTestFile(r''' +class C<T> {} + +typedef G = Function<S>(); + +C<G> x; +'''); + await resolveTestFile(); + assertTestErrors( + [CompileTimeErrorCode.GENERIC_FUNCTION_TYPE_CANNOT_BE_TYPE_ARGUMENT], + ); + } + + test_genericFunctionTypeCannotBeTypeArgument_literal_class() async { + addTestFile(r''' +class C<T> {} + +C<Function<S>()> x; +'''); + await resolveTestFile(); + assertTestErrors( + [CompileTimeErrorCode.GENERIC_FUNCTION_TYPE_CANNOT_BE_TYPE_ARGUMENT], + ); + } + + test_genericFunctionTypeCannotBeTypeArgument_literal_function() async { + addTestFile(r''' +T f<T>(T) => null; + +main() { + f<Function<S>()>(null); +} +'''); + await resolveTestFile(); + assertTestErrors( + [CompileTimeErrorCode.GENERIC_FUNCTION_TYPE_CANNOT_BE_TYPE_ARGUMENT], + ); + } + + test_genericFunctionTypeCannotBeTypeArgument_literal_functionType() async { + addTestFile(r''' +T Function<T>(T) f; + +main() { + f<Function<S>()>(null); +} +'''); + await resolveTestFile(); + assertTestErrors( + [CompileTimeErrorCode.GENERIC_FUNCTION_TYPE_CANNOT_BE_TYPE_ARGUMENT], + ); + } + + test_genericFunctionTypeCannotBeTypeArgument_literal_method() async { + addTestFile(r''' +class C { + T f<T>(T) => null; +} + +main() { + new C().f<Function<S>()>(null); +} +'''); + await resolveTestFile(); + assertTestErrors( + [CompileTimeErrorCode.GENERIC_FUNCTION_TYPE_CANNOT_BE_TYPE_ARGUMENT], + ); + } + + test_genericFunctionTypeCannotBeTypeArgument_literal_typedef() async { + addTestFile(r''' +typedef T F<T>(T t); + +F<Function<S>()> x; +'''); + await resolveTestFile(); + assertTestErrors( + [CompileTimeErrorCode.GENERIC_FUNCTION_TYPE_CANNOT_BE_TYPE_ARGUMENT], + ); + } + + test_genericFunctionTypeCannotBeTypeArgument_OK_def_class() async { + addTestFile(r''' +class C<T> {} + +typedef G = Function(); + +C<G> x; +'''); + await resolveTestFile(); + assertNoTestErrors(); + } + + test_genericFunctionTypeCannotBeTypeArgument_OK_literal_class() async { + addTestFile(r''' +class C<T> {} + +C<Function()> x; +'''); + await resolveTestFile(); + assertNoTestErrors(); + } + test_typeParameters() async { addTestFile(r''' class A {}
diff --git a/pkg/analyzer/test/src/dart/resolution/import_prefix_test.dart b/pkg/analyzer/test/src/dart/resolution/import_prefix_test.dart index a269e79..b13db90 100644 --- a/pkg/analyzer/test/src/dart/resolution/import_prefix_test.dart +++ b/pkg/analyzer/test/src/dart/resolution/import_prefix_test.dart
@@ -21,7 +21,7 @@ class ImportPrefixDriverResolutionTest extends DriverResolutionTest with ImportPrefixResolutionMixin {} -abstract class ImportPrefixResolutionMixin implements ResolutionTest { +mixin ImportPrefixResolutionMixin implements ResolutionTest { test_asExpression_expressionStatement() async { addTestFile(r''' import 'dart:async' as p;
diff --git a/pkg/analyzer/test/src/dart/resolution/instance_creation_test.dart b/pkg/analyzer/test/src/dart/resolution/instance_creation_test.dart index 9594336..302d84b 100644 --- a/pkg/analyzer/test/src/dart/resolution/instance_creation_test.dart +++ b/pkg/analyzer/test/src/dart/resolution/instance_creation_test.dart
@@ -20,7 +20,7 @@ class InstanceCreationDriverResolutionTest extends DriverResolutionTest with InstanceCreationResolutionMixin {} -abstract class InstanceCreationResolutionMixin implements ResolutionTest { +mixin InstanceCreationResolutionMixin implements ResolutionTest { test_error_wrongNumberOfTypeArgumentsConstructor_explicitNew() async { addTestFile(r''' class Foo<X> { @@ -47,6 +47,24 @@ // ); } + test_error_newWithInvalidTypeParameters_implicitNew_inference_top() async { + addTestFile(r''' +final foo = Map<int>(); +'''); + await resolveTestFile(); + assertTestErrors([ + StaticWarningCode.NEW_WITH_INVALID_TYPE_PARAMETERS, + ]); + + var creation = findNode.instanceCreation('Map<int>'); + assertInstanceCreation( + creation, + mapElement, + 'Map<dynamic, dynamic>', + expectedConstructorMember: true, + ); + } + test_error_wrongNumberOfTypeArgumentsConstructor_explicitNew_prefix() async { newFile('/test/lib/a.dart', content: ''' class Foo<X> { @@ -137,4 +155,10 @@ @reflectiveTest class InstanceCreationTaskResolutionTest extends TaskResolutionTest - with InstanceCreationResolutionMixin {} + with InstanceCreationResolutionMixin { + @FailingTest(reason: 'Does not report the error.') + test_error_newWithInvalidTypeParameters_implicitNew_inference_top() { + return super + .test_error_newWithInvalidTypeParameters_implicitNew_inference_top(); + } +}
diff --git a/pkg/analyzer/test/src/dart/resolution/instance_member_inference_class_test.dart b/pkg/analyzer/test/src/dart/resolution/instance_member_inference_class_test.dart index 1218643..ad4b765 100644 --- a/pkg/analyzer/test/src/dart/resolution/instance_member_inference_class_test.dart +++ b/pkg/analyzer/test/src/dart/resolution/instance_member_inference_class_test.dart
@@ -19,7 +19,7 @@ class InstanceMemberInferenceClassDriverResolutionTest extends DriverResolutionTest with InstanceMemberInferenceClassMixin {} -abstract class InstanceMemberInferenceClassMixin implements ResolutionTest { +mixin InstanceMemberInferenceClassMixin implements ResolutionTest { test_invalid_inheritanceCycle() async { addTestFile(''' class A extends C {}
diff --git a/pkg/analyzer/test/src/dart/resolution/instance_member_inference_mixin_test.dart b/pkg/analyzer/test/src/dart/resolution/instance_member_inference_mixin_test.dart index 387e166..36db4b0 100644 --- a/pkg/analyzer/test/src/dart/resolution/instance_member_inference_mixin_test.dart +++ b/pkg/analyzer/test/src/dart/resolution/instance_member_inference_mixin_test.dart
@@ -19,7 +19,7 @@ class InstanceMemberInferenceMixinDriverResolutionTest extends DriverResolutionTest with InstanceMemberInferenceMixinMixin {} -abstract class InstanceMemberInferenceMixinMixin implements ResolutionTest { +mixin InstanceMemberInferenceMixinMixin implements ResolutionTest { test_invalid_inheritanceCycle() async { addTestFile(''' mixin A on C {}
diff --git a/pkg/analyzer/test/src/dart/resolution/method_invocation_test.dart b/pkg/analyzer/test/src/dart/resolution/method_invocation_test.dart new file mode 100644 index 0000000..811228a --- /dev/null +++ b/pkg/analyzer/test/src/dart/resolution/method_invocation_test.dart
@@ -0,0 +1,1720 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:analyzer/dart/ast/ast.dart'; +import 'package:analyzer/dart/element/element.dart'; +import 'package:analyzer/src/error/codes.dart'; +import 'package:test/test.dart'; +import 'package:test_reflective_loader/test_reflective_loader.dart'; + +import 'driver_resolution.dart'; + +main() { + defineReflectiveSuite(() { + defineReflectiveTests(MethodInvocationResolutionTest); + }); +} + +@reflectiveTest +class MethodInvocationResolutionTest extends DriverResolutionTest { + test_error_abstractSuperMemberReference() async { + addTestFile(r''' +abstract class A { + void foo(int _); +} +abstract class B extends A { + void bar() { + super.foo(0); + } + + void foo(int _) {} // does not matter +} +'''); + await resolveTestFile(); + assertTestErrors([CompileTimeErrorCode.ABSTRACT_SUPER_MEMBER_REFERENCE]); + + var invocation = findNode.methodInvocation('foo(0)'); + assertMethodInvocation( + invocation, + findElement.method('foo', of: 'A'), + '(int) → void', + ); + assertSuperExpression(invocation.target); + } + + test_error_abstractSuperMemberReference_mixinHasNoSuchMethod() async { + addTestFile(''' +class A { + int foo(); + noSuchMethod(im) => 42; +} + +class B extends Object with A { + foo() => super.foo(); // ref + noSuchMethod(im) => 87; +} +'''); + await resolveTestFile(); + assertTestErrors([CompileTimeErrorCode.ABSTRACT_SUPER_MEMBER_REFERENCE]); + + var invocation = findNode.methodInvocation('foo(); // ref'); + assertMethodInvocation( + invocation, + findElement.method('foo', of: 'A'), + '() → int', + ); + assertSuperExpression(invocation.target); + } + + test_error_abstractSuperMemberReference_OK_mixinHasConcrete() async { + addTestFile(''' +class A {} + +class M { + void foo(int _) {} +} + +class B = A with M; + +class C extends B { + void bar() { + super.foo(0); + } +} +'''); + await resolveTestFile(); + assertNoTestErrors(); + + var invocation = findNode.methodInvocation('foo(0)'); + assertMethodInvocation( + invocation, + findElement.method('foo', of: 'M'), + '(int) → void', + ); + assertSuperExpression(invocation.target); + } + + test_error_abstractSuperMemberReference_OK_superHasNoSuchMethod() async { + addTestFile(r''' +class A { + int foo(); + noSuchMethod(im) => 42; +} + +class B extends A { + int foo() => super.foo(); // ref + noSuchMethod(im) => 87; +} +'''); + await resolveTestFile(); + assertNoTestErrors(); + + var invocation = findNode.methodInvocation('super.foo(); // ref'); + assertMethodInvocation( + invocation, + findElement.method('foo', of: 'A'), + '() → int', + ); + assertSuperExpression(invocation.target); + } + + test_error_abstractSuperMemberReference_OK_superSuperHasConcrete() async { + addTestFile(''' +abstract class A { + void foo(int _) {} +} + +abstract class B extends A { + void foo(int _); +} + +class C extends B { + void bar() { + super.foo(0); + } +} +'''); + await resolveTestFile(); + assertNoTestErrors(); + + var invocation = findNode.methodInvocation('foo(0)'); + assertMethodInvocation( + invocation, + findElement.method('foo', of: 'A'), + '(int) → void', + ); + assertSuperExpression(invocation.target); + } + + test_error_ambiguousImport_topFunction() async { + newFile('/test/lib/a.dart', content: r''' +void foo(int _) {} +'''); + newFile('/test/lib/b.dart', content: r''' +void foo(int _) {} +'''); + + addTestFile(r''' +import 'a.dart'; +import 'b.dart'; + +main() { + foo(0); +} +'''); + await resolveTestFile(); + assertTestErrors([ + StaticWarningCode.AMBIGUOUS_IMPORT, + ]); + + var invocation = findNode.methodInvocation('foo(0)'); + assertInvokeType(invocation, '(int) → void'); + assertType(invocation, 'void'); + } + + test_error_ambiguousImport_topFunction_prefixed() async { + newFile('/test/lib/a.dart', content: r''' +void foo(int _) {} +'''); + newFile('/test/lib/b.dart', content: r''' +void foo(int _) {} +'''); + + addTestFile(r''' +import 'a.dart' as p; +import 'b.dart' as p; + +main() { + p.foo(0); +} +'''); + await resolveTestFile(); + assertTestErrors([ + StaticWarningCode.AMBIGUOUS_IMPORT, + ]); + + var invocation = findNode.methodInvocation('foo(0)'); + assertInvokeType(invocation, '(int) → void'); + assertType(invocation, 'void'); + } + + test_error_instanceAccessToStaticMember_method() async { + addTestFile(r''' +class A { + static void foo(int _) {} +} + +main(A a) { + a.foo(0); +} +'''); + await resolveTestFile(); + assertTestErrors([ + StaticTypeWarningCode.INSTANCE_ACCESS_TO_STATIC_MEMBER, + ]); + _assertInvalidInvocation( + 'a.foo(0)', + findElement.method('foo'), + expectedNameType: '(int) → void', + ); + } + + test_error_invocationOfNonFunction_interface_hasCall_field() async { + addTestFile(r''' +class C { + void Function() call; +} + +main(C c) { + c(); +} +'''); + await resolveTestFile(); + assertTestErrors([ + StaticTypeWarningCode.INVOCATION_OF_NON_FUNCTION, + ]); + _assertInvalidInvocation( + 'c()', + findElement.parameter('c'), + ); + } + + test_error_invocationOfNonFunction_localVariable() async { + addTestFile(r''' +main() { + Object foo; + foo(); +} +'''); + await resolveTestFile(); + assertTestErrors([ + StaticTypeWarningCode.INVOCATION_OF_NON_FUNCTION, + ]); + _assertInvalidInvocation( + 'foo()', + findElement.localVar('foo'), + expectedNameType: 'Object', + ); + } + + test_error_invocationOfNonFunction_OK_dynamic_localVariable() async { + addTestFile(r''' +main() { + var foo; + foo(); +} +'''); + await resolveTestFile(); + assertNoTestErrors(); + _assertInvalidInvocation('foo();', findElement.localVar('foo')); + } + + test_error_invocationOfNonFunction_OK_dynamicGetter_instance() async { + addTestFile(r''' +class C { + var foo; +} + +main(C c) { + c.foo(); +} +'''); + await resolveTestFile(); + assertNoTestErrors(); + _assertInvalidInvocation('c.foo();', findElement.getter('foo')); + } + + test_error_invocationOfNonFunction_OK_dynamicGetter_superClass() async { + addTestFile(r''' +class A { + var foo; +} + +class B extends A { + main() { + foo(); + } +} +'''); + await resolveTestFile(); + assertNoTestErrors(); + _assertInvalidInvocation('foo();', findElement.getter('foo')); + } + + test_error_invocationOfNonFunction_OK_dynamicGetter_thisClass() async { + addTestFile(r''' +class C { + var foo; + + main() { + foo(); + } +} +'''); + await resolveTestFile(); + assertNoTestErrors(); + _assertInvalidInvocation('foo();', findElement.getter('foo')); + } + + test_error_invocationOfNonFunction_OK_Function() async { + addTestFile(r''' +f(Function foo) { + foo(1, 2); +} +'''); + await resolveTestFile(); + assertNoTestErrors(); + _assertInvalidInvocation('foo(1, 2);', findElement.parameter('foo')); + } + + test_error_invocationOfNonFunction_OK_functionTypeTypeParameter() async { + addTestFile(r''' +typedef MyFunction = double Function(int _); + +class C<T extends MyFunction> { + T foo; + + main() { + foo(0); + } +} +'''); + await resolveTestFile(); + assertNoTestErrors(); + assertMethodInvocation( + findNode.methodInvocation('foo(0)'), + findElement.getter('foo'), + '(int) → double', + ); + } + + test_error_invocationOfNonFunction_static_hasTarget() async { + addTestFile(r''' +class C { + static int foo; +} + +main() { + C.foo(); +} +'''); + await resolveTestFile(); + assertTestErrors([ + StaticTypeWarningCode.INVOCATION_OF_NON_FUNCTION, + ]); + _assertInvalidInvocation( + 'foo()', + findElement.getter('foo'), + ); + } + + test_error_invocationOfNonFunction_static_noTarget() async { + addTestFile(r''' +class C { + static int foo; + + main() { + foo(); + } +} +'''); + await resolveTestFile(); + assertTestErrors([ + StaticTypeWarningCode.INVOCATION_OF_NON_FUNCTION, + ]); + _assertInvalidInvocation( + 'foo()', + findElement.getter('foo'), + ); + } + + test_error_invocationOfNonFunction_super_getter() async { + addTestFile(r''' +class A { + int get foo => 0; +} + +class B extends A { + main() { + super.foo(); + } +} +'''); + await resolveTestFile(); + assertTestErrors([ + StaticTypeWarningCode.INVOCATION_OF_NON_FUNCTION, + ]); + _assertInvalidInvocation( + 'foo()', + findElement.getter('foo'), + ); + } + + test_error_prefixIdentifierNotFollowedByDot() async { + newFile('/test/lib/a.dart', content: r''' +void foo() {} +'''); + + addTestFile(r''' +import 'a.dart' as prefix; + +main() { + prefix?.foo(); +} +'''); + await resolveTestFile(); + assertTestErrors([ + CompileTimeErrorCode.PREFIX_IDENTIFIER_NOT_FOLLOWED_BY_DOT, + ]); + + var import = _importFinder('package:test/a.dart'); + + var invocation = findNode.methodInvocation('foo();'); + assertMethodInvocation( + invocation, + import.topFunction('foo'), + '() → void', + ); + assertImportPrefix(invocation.target, import.prefix); + } + + test_error_prefixIdentifierNotFollowedByDot_deferred() async { + addTestFile(r''' +import 'dart:math' deferred as math; + +main() { + math?.loadLibrary(); +} +'''); + await resolveTestFile(); + assertTestErrors([ + CompileTimeErrorCode.PREFIX_IDENTIFIER_NOT_FOLLOWED_BY_DOT, + ]); + + var import = _importFinder('dart:math'); + + var invocation = findNode.methodInvocation('loadLibrary()'); + assertMethodInvocation( + invocation, + import.importedLibrary.loadLibraryFunction, + '() → Future<dynamic>', + ); + assertImportPrefix(invocation.target, import.prefix); + } + + test_error_prefixIdentifierNotFollowedByDot_invoke() async { + addTestFile(r''' +import 'dart:math' as foo; + +main() { + foo(); +} +'''); + await resolveTestFile(); + assertTestErrors([ + CompileTimeErrorCode.PREFIX_IDENTIFIER_NOT_FOLLOWED_BY_DOT, + ]); + _assertInvalidInvocation( + 'foo()', + findElement.import('dart:math').prefix, + dynamicNameType: true, + ); + } + + test_error_undefinedFunction() async { + addTestFile(r''' +main() { + foo(0); +} +'''); + await resolveTestFile(); + assertTestErrors([ + StaticTypeWarningCode.UNDEFINED_FUNCTION, + ]); + _assertUnresolvedMethodInvocation('foo(0)'); + } + + test_error_undefinedFunction_hasTarget_importPrefix() async { + addTestFile(r''' +import 'dart:math' as math; + +main() { + math.foo(0); +} +'''); + await resolveTestFile(); + assertTestErrors([ + StaticTypeWarningCode.UNDEFINED_FUNCTION, + ]); + _assertUnresolvedMethodInvocation('foo(0);'); + } + + test_error_undefinedIdentifier_target() async { + addTestFile(r''' +main() { + bar.foo(0); +} +'''); + await resolveTestFile(); + assertTestErrors([ + StaticWarningCode.UNDEFINED_IDENTIFIER, + ]); + _assertUnresolvedMethodInvocation('foo(0);'); + } + + test_error_undefinedMethod_hasTarget_class() async { + addTestFile(r''' +class C {} +main() { + C.foo(0); +} +'''); + await resolveTestFile(); + assertTestErrors([ + StaticTypeWarningCode.UNDEFINED_METHOD, + ]); + _assertUnresolvedMethodInvocation('foo(0);'); + } + + test_error_undefinedMethod_hasTarget_class_arguments() async { + addTestFile(r''' +class C {} + +int x; +main() { + C.foo(x); +} +'''); + await resolveTestFile(); + assertTestErrors([ + StaticTypeWarningCode.UNDEFINED_METHOD, + ]); + + _assertUnresolvedMethodInvocation('foo(x);'); + assertTopGetRef('x)', 'x'); + } + + test_error_undefinedMethod_hasTarget_class_inSuperclass() async { + addTestFile(r''' +class S { + static void foo(int _) {} +} + +class C extends S {} + +main() { + C.foo(0); +} +'''); + await resolveTestFile(); + assertTestErrors([ + StaticTypeWarningCode.UNDEFINED_METHOD, + ]); + _assertUnresolvedMethodInvocation('foo(0);'); + } + + test_error_undefinedMethod_hasTarget_class_typeArguments() async { + addTestFile(r''' +class C {} + +main() { + C.foo<int>(); +} +'''); + await resolveTestFile(); + assertTestErrors([ + StaticTypeWarningCode.UNDEFINED_METHOD, + ]); + + _assertUnresolvedMethodInvocation('foo<int>();'); + assertTypeName(findNode.typeName('int>'), intElement, 'int'); + } + + test_error_undefinedMethod_hasTarget_class_typeParameter() async { + addTestFile(r''' +class C<T> { + static main() => C.T(); +} +'''); + await resolveTestFile(); + assertTestErrors([ + StaticTypeWarningCode.UNDEFINED_METHOD, + ]); + _assertUnresolvedMethodInvocation('C.T();'); + } + + test_error_undefinedMethod_hasTarget_instance() async { + addTestFile(r''' +main() { + 42.foo(0); +} +'''); + await resolveTestFile(); + assertTestErrors([ + StaticTypeWarningCode.UNDEFINED_METHOD, + ]); + _assertUnresolvedMethodInvocation('foo(0);'); + } + + test_error_undefinedMethod_hasTarget_localVariable_function() async { + addTestFile(r''' +main() { + var v = () {}; + v.foo(0); +} +'''); + await resolveTestFile(); + assertTestErrors([ + StaticTypeWarningCode.UNDEFINED_METHOD, + ]); + _assertUnresolvedMethodInvocation('foo(0);'); + } + + test_error_undefinedMethod_noTarget() async { + addTestFile(r''' +class C { + main() { + foo(0); + } +} +'''); + await resolveTestFile(); + assertTestErrors([ + StaticTypeWarningCode.UNDEFINED_METHOD, + ]); + _assertUnresolvedMethodInvocation('foo(0);'); + } + + test_error_undefinedMethod_object_call() async { + addTestFile(r''' +main(Object o) { + o.call(); +} +'''); + await resolveTestFile(); + assertTestErrors([ + StaticTypeWarningCode.UNDEFINED_METHOD, + ]); + } + + test_error_undefinedMethod_OK_null() async { + addTestFile(r''' +main() { + null.foo(); +} +'''); + await resolveTestFile(); + assertNoTestErrors(); + _assertUnresolvedMethodInvocation('foo();'); + } + + test_error_undefinedMethod_private() async { + newFile('/test/lib/a.dart', content: r''' +class A { + void _foo(int _) {} +} +'''); + addTestFile(r''' +import 'a.dart'; + +class B extends A { + main() { + _foo(0); + } +} +'''); + await resolveTestFile(); + assertTestErrors([ + StaticTypeWarningCode.UNDEFINED_METHOD, + ]); + _assertUnresolvedMethodInvocation('_foo(0);'); + } + + test_error_undefinedMethod_typeLiteral_cascadeTarget() async { + addTestFile(r''' +class C { + static void foo() {} +} + +main() { + C..foo(); +} +'''); + await resolveTestFile(); + assertTestErrors([ + StaticTypeWarningCode.UNDEFINED_METHOD, + ]); + } + + test_error_undefinedMethod_typeLiteral_conditional() async { + // When applied to a type literal, the conditional access operator '?.' + // cannot be used to access instance methods of Type. + addTestFile(r''' +class A {} +main() { + A?.toString(); +} +'''); + await resolveTestFile(); + assertTestErrors([ + StaticTypeWarningCode.UNDEFINED_METHOD, + ]); + } + + test_error_undefinedSuperMethod() async { + addTestFile(r''' +class A {} + +class B extends A { + void foo(int _) { + super.foo(0); + } +} +'''); + await resolveTestFile(); + assertTestErrors([ + StaticTypeWarningCode.UNDEFINED_SUPER_METHOD, + ]); + _assertUnresolvedMethodInvocation('foo(0);'); + assertSuperExpression(findNode.super_('super.foo')); + } + + test_error_unqualifiedReferenceToNonLocalStaticMember_method() async { + addTestFile(r''' +class A { + static void foo() {} +} + +class B extends A { + main() { + foo(0); + } +} +'''); + await resolveTestFile(); + assertTestErrors([ + StaticTypeWarningCode.UNQUALIFIED_REFERENCE_TO_NON_LOCAL_STATIC_MEMBER, + ]); + + _assertInvalidInvocation( + 'foo(0)', + findElement.method('foo'), + expectedNameType: '(int) → void', + ); + } + + /// The primary purpose of this test is to ensure that we are only getting a + /// single error generated when the only problem is that an imported file + /// does not exist. + test_error_uriDoesNotExist_prefixed() async { + addTestFile(r''' +import 'missing.dart' as p; + +main() { + p.foo(1); + p.bar(2); +} +'''); + await resolveTestFile(); + assertTestErrors([ + CompileTimeErrorCode.URI_DOES_NOT_EXIST, + ]); + _assertUnresolvedMethodInvocation('foo(1);'); + _assertUnresolvedMethodInvocation('bar(2);'); + } + + /// The primary purpose of this test is to ensure that we are only getting a + /// single error generated when the only problem is that an imported file + /// does not exist. + test_error_uriDoesNotExist_show() async { + addTestFile(r''' +import 'missing.dart' show foo, bar; + +main() { + foo(1); + bar(2); +} +'''); + await resolveTestFile(); + assertTestErrors([ + CompileTimeErrorCode.URI_DOES_NOT_EXIST, + ]); + _assertUnresolvedMethodInvocation('foo(1);'); + _assertUnresolvedMethodInvocation('bar(2);'); + } + + test_error_useOfVoidResult_name_getter() async { + addTestFile(r''' +class C<T>{ + T foo; +} + +main(C<void> c) { + c.foo(); +} +'''); + await resolveTestFile(); + assertTestErrors([ + StaticWarningCode.USE_OF_VOID_RESULT, + ]); + _assertInvalidInvocation( + 'c.foo()', + findElement.getter('foo'), + expectedNameType: 'void', + ); + } + + test_error_useOfVoidResult_name_localVariable() async { + addTestFile(r''' +main() { + void foo; + foo(); +} +'''); + await resolveTestFile(); + assertTestErrors([ + StaticWarningCode.USE_OF_VOID_RESULT, + ]); + _assertInvalidInvocation( + 'foo()', + findElement.localVar('foo'), + expectedNameType: 'void', + ); + } + + test_error_useOfVoidResult_name_topFunction() async { + addTestFile(r''' +void foo() {} + +main() { + foo()(); +} +'''); + await resolveTestFile(); + assertTestErrors([ + StaticWarningCode.USE_OF_VOID_RESULT, + ]); + assertMethodInvocation( + findNode.methodInvocation('foo()()'), + findElement.topFunction('foo'), + '() → void', + ); + } + + test_error_useOfVoidResult_name_topVariable() async { + addTestFile(r''' +void foo; + +main() { + foo(); +} +'''); + await resolveTestFile(); + assertTestErrors([ + StaticWarningCode.USE_OF_VOID_RESULT, + ]); + _assertInvalidInvocation( + 'foo()', + findElement.topGet('foo'), + expectedNameType: 'void', + ); + } + + test_error_useOfVoidResult_receiver() async { + addTestFile(r''' +main() { + void foo; + foo.toString(); +} +'''); + await resolveTestFile(); + assertTestErrors([ + StaticWarningCode.USE_OF_VOID_RESULT, + ]); + // TODO(scheglov) Resolve fully, or don't resolve at all. + assertMethodInvocation( + findNode.methodInvocation('toString()'), + null, + '() → String', + ); + } + + test_error_useOfVoidResult_receiver_cascade() async { + addTestFile(r''' +main() { + void foo; + foo..toString(); +} +'''); + await resolveTestFile(); + assertTestErrors([ + StaticWarningCode.USE_OF_VOID_RESULT, + ]); + // TODO(scheglov) Resolve fully, or don't resolve at all. + assertMethodInvocation( + findNode.methodInvocation('toString()'), + null, + '() → String', + ); + } + + test_error_useOfVoidResult_receiver_withNull() async { + addTestFile(r''' +main() { + void foo; + foo?.toString(); +} +'''); + await resolveTestFile(); + assertTestErrors([ + StaticWarningCode.USE_OF_VOID_RESULT, + ]); + // TODO(scheglov) Resolve fully, or don't resolve at all. + assertMethodInvocation( + findNode.methodInvocation('toString()'), + null, + '() → String', + ); + } + + test_error_wrongNumberOfTypeArgumentsMethod_01() async { + addTestFile(r''' +void foo() {} + +main() { + foo<int>(); +} +'''); + await resolveTestFile(); + assertTestErrors([ + StaticTypeWarningCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS_METHOD, + ]); + assertMethodInvocation( + findNode.methodInvocation('foo<int>()'), + findElement.topFunction('foo'), + '() → void', + ); + assertTypeName(findNode.typeName('int>'), intElement, 'int'); + } + + test_error_wrongNumberOfTypeArgumentsMethod_21() async { + addTestFile(r''' +Map<T, U> foo<T extends num, U>() => null; + +main() { + foo<int>(); +} +'''); + await resolveTestFile(); + assertTestErrors([ + StaticTypeWarningCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS_METHOD, + ]); + assertMethodInvocation( + findNode.methodInvocation('foo<int>()'), + findElement.topFunction('foo'), + '() → Map<num, dynamic>', + ); + assertTypeName(findNode.typeName('int>'), intElement, 'int'); + } + + test_hasReceiver_class_staticGetter() async { + addTestFile(r''' +class C { + static double Function(int) get foo => null; +} + +main() { + C.foo(0); +} +'''); + await resolveTestFile(); + assertNoTestErrors(); + + var invocation = findNode.methodInvocation('foo(0);'); + assertMethodInvocation( + invocation, + findElement.getter('foo'), + '(int) → double', + ); + assertClassRef(invocation.target, findElement.class_('C')); + } + + test_hasReceiver_class_staticMethod() async { + addTestFile(r''' +class C { + static void foo(int _) {} +} + +main() { + C.foo(0); +} +'''); + await resolveTestFile(); + assertNoTestErrors(); + + var invocation = findNode.methodInvocation('foo(0);'); + assertMethodInvocation( + invocation, + findElement.method('foo'), + '(int) → void', + ); + assertClassRef(invocation.target, findElement.class_('C')); + } + + test_hasReceiver_deferredImportPrefix_loadLibrary() async { + addTestFile(r''' +import 'dart:math' deferred as math; + +main() { + math.loadLibrary(); +} +'''); + await resolveTestFile(); + assertNoTestErrors(); + + var import = _importFinder('dart:math'); + + var invocation = findNode.methodInvocation('loadLibrary()'); + assertMethodInvocation( + invocation, + import.importedLibrary.loadLibraryFunction, + '() → Future<dynamic>', + ); + assertImportPrefix(invocation.target, import.prefix); + } + + test_hasReceiver_functionTyped_call() async { + addTestFile(r''' +void foo(int _) {} + +main() { + foo.call(0); +} +'''); + await resolveTestFile(); + assertNoTestErrors(); + + var invocation = findNode.methodInvocation('call(0)'); + assertMethodInvocation( + invocation, + null, + '(int) → void', + ); + assertElement(invocation.target, findElement.topFunction('foo')); + assertType(invocation.target, '(int) → void'); + } + + test_hasReceiver_importPrefix_topFunction() async { + newFile('/test/lib/a.dart', content: r''' +T foo<T extends num>(T a, T b) => a; +'''); + + addTestFile(r''' +import 'a.dart' as prefix; + +main() { + prefix.foo(1, 2); +} +'''); + await resolveTestFile(); + assertNoTestErrors(); + + var import = _importFinder('package:test/a.dart'); + + var invocation = findNode.methodInvocation('foo(1, 2)'); + assertMethodInvocation( + invocation, + import.topFunction('foo'), + '(int, int) → int', + ); + assertImportPrefix(invocation.target, import.prefix); + } + + test_hasReceiver_importPrefix_topGetter() async { + newFile('/test/lib/a.dart', content: r''' +T Function<T>(T a, T b) get foo => null; +'''); + + addTestFile(r''' +import 'a.dart' as prefix; + +main() { + prefix.foo(1, 2); +} +'''); + await resolveTestFile(); + assertNoTestErrors(); + + var import = _importFinder('package:test/a.dart'); + + var invocation = findNode.methodInvocation('foo(1, 2)'); + assertMethodInvocation( + invocation, + import.topGetter('foo'), + '(int, int) → int', + ); + assertImportPrefix(invocation.target, import.prefix); + } + + test_hasReceiver_instance_Function_call_localVariable() async { + addTestFile(r''' +void main() { + Function foo; + + foo.call(0); +} +'''); + await resolveTestFile(); + assertNoTestErrors(); + _assertInvalidInvocation('call(0)', null); + } + + test_hasReceiver_instance_Function_call_topVariable() async { + addTestFile(r''' +Function foo; + +void main() { + foo.call(0); +} +'''); + await resolveTestFile(); + assertNoTestErrors(); + _assertInvalidInvocation('call(0)', null); + } + + test_hasReceiver_instance_getter() async { + addTestFile(r''' +class C { + double Function(int) get foo => null; +} + +main(C c) { + c.foo(0); +} +'''); + await resolveTestFile(); + assertNoTestErrors(); + + var invocation = findNode.methodInvocation('foo(0);'); + assertMethodInvocation( + invocation, + findElement.getter('foo'), + '(int) → double', + ); + } + + test_hasReceiver_instance_method() async { + addTestFile(r''' +class C { + void foo(int _) {} +} + +main(C c) { + c.foo(0); +} +'''); + await resolveTestFile(); + assertNoTestErrors(); + + var invocation = findNode.methodInvocation('foo(0);'); + assertMethodInvocation( + invocation, + findElement.method('foo'), + '(int) → void', + ); + } + + test_hasReceiver_instance_method_issue30552() async { + addTestFile(r''' +abstract class I1 { + void foo(int i); +} + +abstract class I2 { + void foo(Object o); +} + +abstract class C implements I1, I2 {} + +class D extends C { + void foo(Object o) {} +} + +void main(C c) { + c.foo('hi'); +} +'''); + await resolveTestFile(); + assertNoTestErrors(); + + var invocation = findNode.methodInvocation("foo('hi')"); + assertMethodInvocation( + invocation, + findElement.method('foo', of: 'I2'), + '(Object) → void', + ); + } + + test_hasReceiver_instance_typeParameter() async { + addTestFile(r''' +class A { + void foo(int _) {} +} + +class C<T extends A> { + T a; + + main() { + a.foo(0); + } +} +'''); + await resolveTestFile(); + assertNoTestErrors(); + + var invocation = findNode.methodInvocation('foo(0);'); + assertMethodInvocation( + invocation, + findElement.method('foo'), + '(int) → void', + ); + } + + test_hasReceiver_prefixed_class_staticGetter() async { + newFile('/test/lib/a.dart', content: r''' +class C { + static double Function(int) get foo => null; +} +'''); + + addTestFile(r''' +import 'a.dart' as prefix; + +main() { + prefix.C.foo(0); +} +'''); + await resolveTestFile(); + assertNoTestErrors(); + + var import = _importFinder('package:test/a.dart'); + + var invocation = findNode.methodInvocation('foo(0)'); + assertMethodInvocation( + invocation, + import.class_('C').getGetter('foo'), + '(int) → double', + ); + + PrefixedIdentifier target = invocation.target; + assertImportPrefix(target.prefix, import.prefix); + assertClassRef(target.identifier, import.class_('C')); + } + + test_hasReceiver_prefixed_class_staticMethod() async { + newFile('/test/lib/a.dart', content: r''' +class C { + static void foo(int _) => null; +} +'''); + + addTestFile(r''' +import 'a.dart' as prefix; + +main() { + prefix.C.foo(0); +} +'''); + await resolveTestFile(); + assertNoTestErrors(); + + var import = _importFinder('package:test/a.dart'); + + var invocation = findNode.methodInvocation('foo(0)'); + assertMethodInvocation( + invocation, + import.class_('C').getMethod('foo'), + '(int) → void', + ); + + PrefixedIdentifier target = invocation.target; + assertImportPrefix(target.prefix, import.prefix); + assertClassRef(target.identifier, import.class_('C')); + } + + test_hasReceiver_super_getter() async { + addTestFile(r''' +class A { + double Function(int) get foo => null; +} + +class B extends A { + void bar() { + super.foo(0); + } +} +'''); + await resolveTestFile(); + assertNoTestErrors(); + + var invocation = findNode.methodInvocation('foo(0);'); + assertMethodInvocation( + invocation, + findElement.getter('foo', of: 'A'), + '(int) → double', + ); + assertSuperExpression(invocation.target); + } + + test_hasReceiver_super_method() async { + addTestFile(r''' +class A { + void foo(int _) {} +} + +class B extends A { + void foo(int _) { + super.foo(0); + } +} +'''); + await resolveTestFile(); + assertNoTestErrors(); + + var invocation = findNode.methodInvocation('foo(0);'); + assertMethodInvocation( + invocation, + findElement.method('foo', of: 'A'), + '(int) → void', + ); + assertSuperExpression(invocation.target); + } + + test_namedArgument() async { + addTestFile(r''' +void foo({int a, bool b}) {} + +main() { + foo(b: false, a: 0); +} +'''); + await resolveTestFile(); + assertNoTestErrors(); + + var invocation = findNode.methodInvocation('foo(b:'); + assertMethodInvocation( + invocation, + findElement.topFunction('foo'), + '({a: int, b: bool}) → void', + ); + assertNamedParameterRef('b: false', 'b'); + assertNamedParameterRef('a: 0', 'a'); + } + + test_noReceiver_getter_superClass() async { + addTestFile(r''' +class A { + double Function(int) get foo => null; +} + +class B extends A { + void bar() { + foo(0); + } +} +'''); + await resolveTestFile(); + assertNoTestErrors(); + + var invocation = findNode.methodInvocation('foo(0)'); + assertMethodInvocation( + invocation, + findElement.getter('foo'), + '(int) → double', + ); + } + + test_noReceiver_getter_thisClass() async { + addTestFile(r''' +class C { + double Function(int) get foo => null; + + void bar() { + foo(0); + } +} +'''); + await resolveTestFile(); + assertNoTestErrors(); + + var invocation = findNode.methodInvocation('foo(0)'); + assertMethodInvocation( + invocation, + findElement.getter('foo'), + '(int) → double', + ); + } + + test_noReceiver_importPrefix() async { + addTestFile(r''' +import 'dart:math' as math; + +main() { + math(); +} +'''); + await resolveTestFile(); + assertTestErrors([ + CompileTimeErrorCode.PREFIX_IDENTIFIER_NOT_FOLLOWED_BY_DOT, + ]); + assertElement(findNode.simple('math()'), findElement.prefix('math')); + } + + test_noReceiver_localFunction() async { + addTestFile(r''' +main() { + void foo(int _) {} + + foo(0); +} +'''); + await resolveTestFile(); + assertNoTestErrors(); + + var invocation = findNode.methodInvocation('foo(0)'); + assertMethodInvocation( + invocation, + findElement.localFunction('foo'), + '(int) → void', + ); + } + + test_noReceiver_localVariable() async { + addTestFile(r''' +main() { + void Function(int) foo; + + foo(0); +} +'''); + await resolveTestFile(); + assertNoTestErrors(); + + var invocation = findNode.methodInvocation('foo(0)'); + assertMethodInvocation( + invocation, + findElement.localVar('foo'), + '(int) → void', + ); + } + + test_noReceiver_localVariable_call() async { + addTestFile(r''' +class C { + void call(int _) {} +} + +main(C c) { + c(0); +} +'''); + await resolveTestFile(); + assertNoTestErrors(); + + var invocation = findNode.methodInvocation('c(0);'); + assertMethodInvocation( + invocation, + findElement.parameter('c'), + '(int) → void', + ); + } + + test_noReceiver_localVariable_promoted() async { + addTestFile(r''' +main() { + var foo; + if (foo is void Function(int)) { + foo(0); + } +} +'''); + await resolveTestFile(); + assertNoTestErrors(); + + var invocation = findNode.methodInvocation('foo(0)'); + assertMethodInvocation( + invocation, + findElement.localVar('foo'), + '(int) → void', + ); + } + + test_noReceiver_method_superClass() async { + addTestFile(r''' +class A { + void foo(int _) {} +} + +class B extends A { + void bar() { + foo(0); + } +} +'''); + await resolveTestFile(); + assertNoTestErrors(); + + var invocation = findNode.methodInvocation('foo(0)'); + assertMethodInvocation( + invocation, + findElement.method('foo'), + '(int) → void', + ); + } + + test_noReceiver_method_thisClass() async { + addTestFile(r''' +class C { + void foo(int _) {} + + void bar() { + foo(0); + } +} +'''); + await resolveTestFile(); + assertNoTestErrors(); + + var invocation = findNode.methodInvocation('foo(0)'); + assertMethodInvocation( + invocation, + findElement.method('foo'), + '(int) → void', + ); + } + + test_noReceiver_topFunction() async { + addTestFile(r''' +void foo(int _) {} + +main() { + foo(0); +} +'''); + await resolveTestFile(); + assertNoTestErrors(); + + var invocation = findNode.methodInvocation('foo(0)'); + assertMethodInvocation( + invocation, + findElement.topFunction('foo'), + '(int) → void', + ); + } + + test_noReceiver_topGetter() async { + addTestFile(r''' +double Function(int) get foo => null; + +main() { + foo(0); +} +'''); + await resolveTestFile(); + assertNoTestErrors(); + + var invocation = findNode.methodInvocation('foo(0)'); + assertMethodInvocation( + invocation, + findElement.topGet('foo'), + '(int) → double', + ); + } + + test_noReceiver_topVariable() async { + addTestFile(r''' +void Function(int) foo; + +main() { + foo(0); +} +'''); + await resolveTestFile(); + assertNoTestErrors(); + + var invocation = findNode.methodInvocation('foo(0)'); + assertMethodInvocation( + invocation, + findElement.topGet('foo'), + '(int) → void', + ); + } + + test_objectMethodOnDynamic() async { + addTestFile(r''' +main() { + var v; + v.toString(42); +} +'''); + await resolveTestFile(); + assertNoTestErrors(); + _assertUnresolvedMethodInvocation('toString(42);'); + } + + test_objectMethodOnFunction() async { + addTestFile(r''' +void f() {} + +main() { + f.toString(); +} +'''); + await resolveTestFile(); + assertNoTestErrors(); + + var invocation = findNode.methodInvocation('toString();'); + assertMethodInvocation( + invocation, + typeProvider.objectType.getMethod('toString'), + '() → String', + ); + } + + void _assertInvalidInvocation(String search, Element expectedElement, + {String expectedNameType, bool dynamicNameType: false}) { + var invocation = findNode.methodInvocation(search); + if (dynamicNameType) { + assertTypeDynamic(invocation.methodName); + } + // TODO(scheglov) I think `invokeType` should be `null`. + assertMethodInvocation( + invocation, + expectedElement, + 'dynamic', + expectedNameType: expectedNameType, + expectedType: 'dynamic', + ); + } + + void _assertUnresolvedMethodInvocation(String search) { + // TODO(scheglov) clean up + _assertInvalidInvocation(search, null); +// var invocation = findNode.methodInvocation(search); +// assertTypeDynamic(invocation.methodName); +// // TODO(scheglov) I think `invokeType` should be `null`. +// assertMethodInvocation( +// invocation, +// null, +// 'dynamic', +// expectedType: 'dynamic', +// ); + } + + _ImportElementFinder _importFinder(String targetUri) { + var import = findElement.import(targetUri); + return _ImportElementFinder(import); + } +} + +class _ImportElementFinder { + final ImportElement import; + + _ImportElementFinder(this.import); + + CompilationUnitElement get definingUnit { + return importedLibrary.definingCompilationUnit; + } + + LibraryElement get importedLibrary => import.importedLibrary; + + PrefixElement get prefix => import.prefix; + + ClassElement class_(String name) { + for (var class_ in definingUnit.types) { + if (class_.name == name) { + return class_; + } + } + fail('Not found class: $name'); + } + + FunctionElement topFunction(String name) { + for (var function in definingUnit.functions) { + if (function.name == name) { + return function; + } + } + fail('Not found top-level function: $name'); + } + + PropertyAccessorElement topGetter(String name) { + for (var accessor in definingUnit.accessors) { + if (accessor.name == name && accessor.isGetter) { + return accessor; + } + } + fail('Not found top-level getter: $name'); + } +}
diff --git a/pkg/analyzer/test/src/dart/resolution/mixin_test.dart b/pkg/analyzer/test/src/dart/resolution/mixin_test.dart index 40ae57a..bc792f0 100644 --- a/pkg/analyzer/test/src/dart/resolution/mixin_test.dart +++ b/pkg/analyzer/test/src/dart/resolution/mixin_test.dart
@@ -23,7 +23,7 @@ class MixinDriverResolutionTest extends DriverResolutionTest with MixinResolutionMixin {} -abstract class MixinResolutionMixin implements ResolutionTest { +mixin MixinResolutionMixin implements ResolutionTest { test_accessor_getter() async { addTestFile(r''' mixin M { @@ -1004,6 +1004,28 @@ ]); } + test_error_mixinApplicationNoConcreteSuperInvokedMember_OK_hasNSM() async { + addTestFile(r''' +abstract class A { + void foo(); +} + +mixin M on A { + void bar() { + super.foo(); + } +} + +class C implements A { + noSuchMethod(_) {} +} + +class X extends C with M {} +'''); + await resolveTestFile(); + assertNoTestErrors(); + } + test_error_mixinApplicationNoConcreteSuperInvokedMember_OK_inPreviousMixin() async { addTestFile(r''' abstract class A { @@ -1134,6 +1156,30 @@ ]); } + test_error_mixinApplicationNotImplementedInterface_noMemberErrors() async { + addTestFile(r''' +class A { + void foo() {} +} + +mixin M on A { + void bar() { + super.foo(); + } +} + +class C { + noSuchMethod(_) {} +} + +class X = C with M; +'''); + await resolveTestFile(); + assertTestErrors([ + CompileTimeErrorCode.MIXIN_APPLICATION_NOT_IMPLEMENTED_INTERFACE, + ]); + } + test_error_mixinApplicationNotImplementedInterface_OK_0() async { addTestFile(r''' mixin M {} @@ -1268,6 +1314,24 @@ assertInstanceCreation(creation, m, 'M', constructorName: 'named'); } + test_error_mixinInstantiate_undefined() async { + addTestFile(r''' +mixin M {} + +main() { + new M.named(); +} +'''); + await resolveTestFile(); + assertTestErrors([ + CompileTimeErrorCode.MIXIN_INSTANTIATE, + ]); + + var creation = findNode.instanceCreation('M.named();'); + var m = findElement.mixin('M'); + assertElement(creation.constructorName.type.name, m); + } + test_error_onClause_deferredClass() async { addTestFile(r''' import 'dart:math' deferred as math;
diff --git a/pkg/analyzer/test/src/dart/resolution/optional_const_test.dart b/pkg/analyzer/test/src/dart/resolution/optional_const_test.dart index 6b9d107..df32638 100644 --- a/pkg/analyzer/test/src/dart/resolution/optional_const_test.dart +++ b/pkg/analyzer/test/src/dart/resolution/optional_const_test.dart
@@ -22,7 +22,7 @@ class OptionalConstDriverResolutionTest extends DriverResolutionTest with OptionalConstMixin {} -abstract class OptionalConstMixin implements ResolutionTest { +mixin OptionalConstMixin implements ResolutionTest { Map<String, LibraryElement> libraries = {}; LibraryElement get libraryA => libraries['package:test/a.dart'];
diff --git a/pkg/analyzer/test/src/dart/resolution/property_access_test.dart b/pkg/analyzer/test/src/dart/resolution/property_access_test.dart new file mode 100644 index 0000000..15dfcee --- /dev/null +++ b/pkg/analyzer/test/src/dart/resolution/property_access_test.dart
@@ -0,0 +1,105 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:analyzer/src/error/codes.dart'; +import 'package:test_reflective_loader/test_reflective_loader.dart'; + +import 'driver_resolution.dart'; + +main() { + defineReflectiveSuite(() { + defineReflectiveTests(PropertyAccessResolutionTest); + }); +} + +@reflectiveTest +class PropertyAccessResolutionTest extends DriverResolutionTest { + test_get_error_abstractSuperMemberReference_mixinHasNoSuchMethod() async { + addTestFile(''' +class A { + int get foo; + noSuchMethod(im) => 1; +} + +class B extends Object with A { + get foo => super.foo; // ref + noSuchMethod(im) => 2; +} +'''); + await resolveTestFile(); + assertTestErrors([CompileTimeErrorCode.ABSTRACT_SUPER_MEMBER_REFERENCE]); + + var access = findNode.propertyAccess('foo; // ref'); + assertPropertyAccess(access, findElement.getter('foo', of: 'A'), 'int'); + assertSuperExpression(access.target); + } + + test_get_error_abstractSuperMemberReference_OK_superHasNoSuchMethod() async { + addTestFile(r''' +class A { + int get foo; + noSuchMethod(im) => 1; +} + +class B extends A { + get foo => super.foo; // ref + noSuchMethod(im) => 2; +} +'''); + await resolveTestFile(); + assertNoTestErrors(); + + var access = findNode.propertyAccess('super.foo; // ref'); + assertPropertyAccess(access, findElement.getter('foo', of: 'A'), 'int'); + assertSuperExpression(access.target); + } + + test_set_error_abstractSuperMemberReference_mixinHasNoSuchMethod() async { + addTestFile(''' +class A { + set foo(int a); + noSuchMethod(im) {} +} + +class B extends Object with A { + set foo(v) => super.foo = v; // ref + noSuchMethod(im) {} +} +'''); + await resolveTestFile(); + assertTestErrors([CompileTimeErrorCode.ABSTRACT_SUPER_MEMBER_REFERENCE]); + + var access = findNode.propertyAccess('foo = v; // ref'); + assertPropertyAccess( + access, + findElement.setter('foo', className: 'A'), + 'int', + ); + assertSuperExpression(access.target); + } + + test_set_error_abstractSuperMemberReference_OK_superHasNoSuchMethod() async { + addTestFile(r''' +class A { + set foo(int a); + noSuchMethod(im) => 1; +} + +class B extends A { + set foo(v) => super.foo = v; // ref + noSuchMethod(im) => 2; +} +'''); + await resolveTestFile(); + assertNoTestErrors(); + + var access = findNode.propertyAccess('foo = v; // ref'); + assertPropertyAccess( + access, + findElement.setter('foo', className: 'A'), + 'int', + ); + assertSuperExpression(access.target); + } +}
diff --git a/pkg/analyzer/test/src/dart/resolution/resolution.dart b/pkg/analyzer/test/src/dart/resolution/resolution.dart index f6fdc6f..a762eb6 100644 --- a/pkg/analyzer/test/src/dart/resolution/resolution.dart +++ b/pkg/analyzer/test/src/dart/resolution/resolution.dart
@@ -29,7 +29,7 @@ final isVoidType = new TypeMatcher<VoidTypeImpl>(); /// Base for resolution tests. -abstract class ResolutionTest implements ResourceProviderMixin { +mixin ResolutionTest implements ResourceProviderMixin { TestAnalysisResult result; FindNode findNode; FindElement findElement; @@ -61,6 +61,16 @@ newFile('/test/lib/test.dart', content: content); } + /// Assert that the given [identifier] is a reference to a class, in the + /// form that is not a separate expression, e.g. in a static method + /// invocation like `C.staticMethod()`, or a type annotation `C c = null`. + void assertClassRef( + SimpleIdentifier identifier, ClassElement expectedElement) { + assertElement(identifier, expectedElement); + // TODO(scheglov) Enforce this. +// assertTypeNull(identifier); + } + void assertConstructorElement( ConstructorElement expected, ConstructorElement actual) { if (expected is ConstructorMember && actual is ConstructorMember) { @@ -168,6 +178,11 @@ assertType(ref, type); } + void assertImportPrefix(SimpleIdentifier identifier, PrefixElement element) { + assertElement(identifier, element); + assertTypeNull(identifier); + } + void assertInstanceCreation(InstanceCreationExpression creation, ClassElement expectedClassElement, String expectedType, {String constructorName, @@ -232,10 +247,60 @@ expect(actual.baseElement, same(expectedBase)); } + void assertMethodInvocation(MethodInvocation invocation, + Element expectedElement, String expectedInvokeType, + {String expectedNameType, String expectedType}) { + // TODO(scheglov) Check for Member. + var element = invocation.methodName.staticElement; + if (element is Member) { + element = (element as Member).baseElement; + expect(element, same(expectedElement)); + } else { + assertElement(invocation.methodName, expectedElement); + } + + // TODO(scheglov) Should we enforce this? +// if (expectedNameType == null) { +// if (expectedElement is ExecutableElement) { +// expectedNameType = expectedElement.type.displayName; +// } else if (expectedElement is VariableElement) { +// expectedNameType = expectedElement.type.displayName; +// } +// } +// assertType(invocation.methodName, expectedNameType); + + assertInvokeType(invocation, expectedInvokeType); + + expectedType ??= _extractReturnType(expectedInvokeType); + assertType(invocation, expectedType); + } + + void assertPropertyAccess( + PropertyAccess access, + Element expectedElement, + String expectedType, + ) { + assertElement(access.propertyName, expectedElement); + assertType(access, expectedType); + } + + void assertNamedParameterRef(String search, String name) { + var ref = findNode.simple(search); + assertElement(ref, findElement.parameter(name)); + assertTypeNull(ref); + } + void assertNoTestErrors() { assertTestErrors(const <ErrorCode>[]); } + void assertSuperExpression(SuperExpression superExpression) { + // TODO(scheglov) I think `super` does not have type itself. + // It is just a signal to look for implemented method in the supertype. + // With mixins there isn't a type anyway. +// assertTypeNull(superExpression); + } + void assertTestErrors(List<ErrorCode> expected) { assertErrors(result.errors, expected); } @@ -332,6 +397,12 @@ } return element; } + + static String _extractReturnType(String invokeType) { + int arrowIndex = invokeType.indexOf('→'); + expect(arrowIndex, isNonNegative); + return invokeType.substring(arrowIndex + 1).trim(); + } } class TestAnalysisResult {
diff --git a/pkg/analyzer/test/src/dart/resolution/task_resolution.dart b/pkg/analyzer/test/src/dart/resolution/task_resolution.dart index 7e02ab4..7c84ed2 100644 --- a/pkg/analyzer/test/src/dart/resolution/task_resolution.dart +++ b/pkg/analyzer/test/src/dart/resolution/task_resolution.dart
@@ -1,4 +1,4 @@ -// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. @@ -9,15 +9,14 @@ import 'package:analyzer/src/generated/sdk.dart'; import 'package:analyzer/src/generated/source.dart'; import 'package:analyzer/src/source/package_map_resolver.dart'; +import 'package:analyzer/src/test_utilities/mock_sdk.dart'; import 'package:analyzer/src/test_utilities/resource_provider_mixin.dart'; import '../../../generated/analysis_context_factory.dart'; -import '../../context/mock_sdk.dart'; import 'resolution.dart'; /// Task model based implementation of [ResolutionTest]. -class TaskResolutionTest extends Object - with ResourceProviderMixin, ResolutionTest { +class TaskResolutionTest with ResourceProviderMixin, ResolutionTest { DartSdk sdk; SourceFactory sourceFactory;
diff --git a/pkg/analyzer/test/src/dart/resolution/test_all.dart b/pkg/analyzer/test/src/dart/resolution/test_all.dart index f0c2ee6..c52454e 100644 --- a/pkg/analyzer/test/src/dart/resolution/test_all.dart +++ b/pkg/analyzer/test/src/dart/resolution/test_all.dart
@@ -6,7 +6,8 @@ import 'assignment_test.dart' as assignment_test; import 'class_test.dart' as class_test; -import 'optional_const_test.dart' as optional_const_test; +import 'comment_test.dart' as comment_test; +import 'constant_test.dart' as constant_test; import 'enum_test.dart' as enum_test; import 'for_in_test.dart' as for_in_test; import 'generic_type_alias_test.dart' as generic_type_alias_test; @@ -16,13 +17,18 @@ as instance_member_inference_class_test; import 'instance_member_inference_mixin_test.dart' as instance_member_inference_mixin_test; +import 'method_invocation_test.dart' as method_invocation_test; import 'mixin_test.dart' as mixin_test; +import 'optional_const_test.dart' as optional_const_test; +import 'property_access_test.dart' as property_access_test; import 'top_type_inference_test.dart' as top_type_inference_test; main() { defineReflectiveSuite(() { assignment_test.main(); class_test.main(); + comment_test.main(); + constant_test.main(); enum_test.main(); for_in_test.main(); generic_type_alias_test.main(); @@ -30,8 +36,10 @@ instance_creation_test.main(); instance_member_inference_class_test.main(); instance_member_inference_mixin_test.main(); + method_invocation_test.main(); mixin_test.main(); optional_const_test.main(); + property_access_test.main(); top_type_inference_test.main(); }, name: 'resolution'); }
diff --git a/pkg/analyzer/test/src/dart/resolution/top_type_inference_test.dart b/pkg/analyzer/test/src/dart/resolution/top_type_inference_test.dart index 3b6eb93..3c3defe 100644 --- a/pkg/analyzer/test/src/dart/resolution/top_type_inference_test.dart +++ b/pkg/analyzer/test/src/dart/resolution/top_type_inference_test.dart
@@ -24,7 +24,7 @@ class TopTypeInferenceTaskResolutionTest extends TaskResolutionTest with TopTypeInstanceMixin {} -abstract class TopTypeInstanceMixin implements ResolutionTest { +mixin TopTypeInstanceMixin implements ResolutionTest { test_referenceInstanceVariable_withDeclaredType() async { addTestFile(r''' class A {
diff --git a/pkg/analyzer/test/src/dart/sdk/patch_test.dart b/pkg/analyzer/test/src/dart/sdk/patch_test.dart index 6ffbf04..dd57aa6 100644 --- a/pkg/analyzer/test/src/dart/sdk/patch_test.dart +++ b/pkg/analyzer/test/src/dart/sdk/patch_test.dart
@@ -5,11 +5,11 @@ import 'package:analyzer/dart/ast/ast.dart'; import 'package:analyzer/dart/ast/token.dart'; import 'package:analyzer/file_system/file_system.dart'; -import 'package:analyzer/file_system/memory_file_system.dart'; import 'package:analyzer/src/dart/sdk/patch.dart'; import 'package:analyzer/src/dart/sdk/sdk.dart'; import 'package:analyzer/src/generated/engine.dart'; import 'package:analyzer/src/generated/source.dart'; +import 'package:analyzer/src/test_utilities/resource_provider_mixin.dart'; import 'package:test/test.dart'; import 'package:test_reflective_loader/test_reflective_loader.dart'; @@ -20,8 +20,7 @@ } @reflectiveTest -class SdkPatcherTest { - MemoryResourceProvider provider = new MemoryResourceProvider(); +class SdkPatcherTest with ResourceProviderMixin { Folder sdkFolder; FolderBasedDartSdk sdk; @@ -29,7 +28,7 @@ RecordingErrorListener listener = new RecordingErrorListener(); void setUp() { - sdkFolder = provider.getFolder(_p('/sdk')); + sdkFolder = getFolder('/sdk'); } test_class_constructor_append_fail_notPrivate_named() { @@ -717,12 +716,12 @@ };'''); _createSdk(); var patchPaths = { - 'dart:test': [_p('/sdk/lib/does_not_exist.dart')] + 'dart:test': [convertPath('/sdk/lib/does_not_exist.dart')] }; - File file = provider.newFile(_p('/sdk/lib/test/test.dart'), ''); + File file = newFile('/sdk/lib/test/test.dart'); Source source = file.createSource(Uri.parse('dart:test')); CompilationUnit unit = SdkPatcher.parse(source, listener); - patcher.patch(provider, patchPaths, listener, source, unit); + patcher.patch(resourceProvider, patchPaths, listener, source, unit); }, throwsArgumentError); } @@ -733,16 +732,16 @@ 'internal/internal.dart'), };'''); var patchPaths = { - 'dart:_internal': [_p('/sdk/lib/internal/internal_patch.dart')] + 'dart:_internal': [convertPath('/sdk/lib/internal/internal_patch.dart')] }; - File file = provider.newFile(_p('/sdk/lib/internal/internal.dart'), r''' + File file = newFile('/sdk/lib/internal/internal.dart', content: r''' library dart._internal; class A {} class B { B(); } '''); - provider.newFile(_p('/sdk/lib/internal/internal_patch.dart'), r''' + newFile(convertPath('/sdk/lib/internal/internal_patch.dart'), content: r''' @patch class B { int newField; @@ -757,7 +756,7 @@ Source source = file.createSource(Uri.parse('dart:_internal')); CompilationUnit unit = SdkPatcher.parse(source, listener); - patcher.patch(provider, patchPaths, listener, source, unit); + patcher.patch(resourceProvider, patchPaths, listener, source, unit); _assertUnitCode( unit, 'library dart._internal; class A {} ' @@ -782,12 +781,12 @@ patches: {VM_PLATFORM: ['test/test_patch.dart']}), };'''); var patchPaths = { - 'dart:test': [_p('/sdk/lib/test/test_patch.dart')] + 'dart:test': [convertPath('/sdk/lib/test/test_patch.dart')] }; - File fileLib = provider.newFile(_p('/sdk/lib/test/test.dart'), baseLibCode); + File fileLib = newFile('/sdk/lib/test/test.dart', content: baseLibCode); File filePart = - provider.newFile(_p('/sdk/lib/test/test_part.dart'), basePartCode); - provider.newFile(_p('/sdk/lib/test/test_patch.dart'), r''' + newFile('/sdk/lib/test/test_part.dart', content: basePartCode); + newFile('/sdk/lib/test/test_patch.dart', content: r''' import 'foo.dart'; @patch @@ -809,7 +808,7 @@ Uri uri = Uri.parse('dart:test'); Source source = fileLib.createSource(uri); CompilationUnit unit = SdkPatcher.parse(source, listener); - patcher.patch(provider, patchPaths, listener, source, unit); + patcher.patch(resourceProvider, patchPaths, listener, source, unit); _assertUnitCode( unit, "library test; part 'test_part.dart'; import 'foo.dart'; " @@ -820,7 +819,7 @@ Uri uri = Uri.parse('dart:test/test_part.dart'); Source source = filePart.createSource(uri); CompilationUnit unit = SdkPatcher.parse(source, listener); - patcher.patch(provider, patchPaths, listener, source, unit); + patcher.patch(resourceProvider, patchPaths, listener, source, unit); _assertUnitCode(unit, "part of test; class B {int _b() => 1;}"); } } @@ -1053,7 +1052,7 @@ } void _createSdk() { - sdk = new FolderBasedDartSdk(provider, sdkFolder); + sdk = new FolderBasedDartSdk(resourceProvider, sdkFolder); sdk.analysisOptions = new AnalysisOptionsImpl(); } @@ -1064,24 +1063,24 @@ 'test/test.dart'), };'''); var patchPaths = { - 'dart:test': [_p('/sdk/lib/test/test_patch.dart')] + 'dart:test': [convertPath('/sdk/lib/test/test_patch.dart')] }; - File file = provider.newFile(_p('/sdk/lib/test/test.dart'), baseCode); - provider.newFile(_p('/sdk/lib/test/test_patch.dart'), patchCode); + File file = newFile('/sdk/lib/test/test.dart', content: baseCode); + newFile('/sdk/lib/test/test_patch.dart', content: patchCode); _createSdk(); Source source = file.createSource(Uri.parse('dart:test')); CompilationUnit unit = SdkPatcher.parse(source, listener); - patcher.patch(provider, patchPaths, listener, source, unit); + patcher.patch(resourceProvider, patchPaths, listener, source, unit); return unit; } - String _p(String path) => provider.convertPath(path); - void _setSdkLibraries(String code) { - provider.newFile( - _p('/sdk/lib/_internal/sdk_library_metadata/lib/libraries.dart'), code); + newFile( + '/sdk/lib/_internal/sdk_library_metadata/lib/libraries.dart', + content: code, + ); } static void _assertPrevNextToken(Token prev, Token next) {
diff --git a/pkg/analyzer/test/src/dart/sdk/sdk_test.dart b/pkg/analyzer/test/src/dart/sdk/sdk_test.dart index cfc0540..b795f9d 100644 --- a/pkg/analyzer/test/src/dart/sdk/sdk_test.dart +++ b/pkg/analyzer/test/src/dart/sdk/sdk_test.dart
@@ -110,7 +110,7 @@ } @reflectiveTest -class FolderBasedDartSdkTest extends Object with ResourceProviderMixin { +class FolderBasedDartSdkTest with ResourceProviderMixin { void test_addExtensions() { FolderBasedDartSdk sdk = _createDartSdk(); String uri = 'dart:my.internal'; @@ -315,7 +315,7 @@ } @reflectiveTest -class SdkExtensionFinderTest extends Object with ResourceProviderMixin { +class SdkExtensionFinderTest with ResourceProviderMixin { void setUp() { newFile('/tmp/_sdkext', content: r''' {
diff --git a/pkg/analyzer/test/src/fasta/recovery/code_order_test.dart b/pkg/analyzer/test/src/fasta/recovery/code_order_test.dart index 17b4d06..0958f78 100644 --- a/pkg/analyzer/test/src/fasta/recovery/code_order_test.dart +++ b/pkg/analyzer/test/src/fasta/recovery/code_order_test.dart
@@ -1,8 +1,8 @@ -// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file +// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. -import 'package:analyzer/analyzer.dart'; +import 'package:analyzer/dart/ast/ast.dart'; import 'package:analyzer/src/dart/error/syntactic_errors.dart'; import 'package:test_reflective_loader/test_reflective_loader.dart'; @@ -341,14 +341,6 @@ '''); } - void test_multipleOn() { - testRecovery(''' -mixin A on B on C {} -''', [ParserErrorCode.MULTIPLE_ON_CLAUSES], ''' -mixin A on B, C {} -'''); - } - void test_multipleImplements() { testRecovery(''' mixin A implements B implements C, D {} @@ -357,6 +349,14 @@ '''); } + void test_multipleOn() { + testRecovery(''' +mixin A on B on C {} +''', [ParserErrorCode.MULTIPLE_ON_CLAUSES], ''' +mixin A on B, C {} +'''); + } + @failingTest void test_typing_implements() { testRecovery('''
diff --git a/pkg/analyzer/test/src/fasta/recovery/partial_code/annotation_test.dart b/pkg/analyzer/test/src/fasta/recovery/partial_code/annotation_test.dart index 06105e3..4087738 100644 --- a/pkg/analyzer/test/src/fasta/recovery/partial_code/annotation_test.dart +++ b/pkg/analyzer/test/src/fasta/recovery/partial_code/annotation_test.dart
@@ -41,7 +41,13 @@ [ new TestDescriptor( 'ampersand', '@', [ParserErrorCode.MISSING_IDENTIFIER], '@_s_', - failing: ['typedef', 'functionNonVoid', 'getter', 'setter']), + failing: [ + 'typedef', + 'functionNonVoid', + 'getter', + 'mixin', + 'setter' + ]), new TestDescriptor( 'leftParen', '@a(', [ScannerErrorCode.EXPECTED_TOKEN], '@a()', allFailing: true),
diff --git a/pkg/analyzer/test/src/fasta/recovery/partial_code/class_declaration_test.dart b/pkg/analyzer/test/src/fasta/recovery/partial_code/class_declaration_test.dart index e932751..372ed73 100644 --- a/pkg/analyzer/test/src/fasta/recovery/partial_code/class_declaration_test.dart +++ b/pkg/analyzer/test/src/fasta/recovery/partial_code/class_declaration_test.dart
@@ -36,7 +36,7 @@ ], 'class A extend _s_ {}', expectedErrorsInValidCode: [ParserErrorCode.EXPECTED_INSTEAD], - failing: ['functionVoid', 'functionNonVoid', 'getter']), + failing: ['functionVoid', 'functionNonVoid', 'getter', 'mixin']), new TestDescriptor( 'extends', 'class A extends', @@ -45,7 +45,7 @@ ParserErrorCode.MISSING_CLASS_BODY ], 'class A extends _s_ {}', - failing: ['functionVoid', 'functionNonVoid', 'getter']), + failing: ['functionVoid', 'functionNonVoid', 'getter', 'mixin']), new TestDescriptor( 'on', 'class A on', @@ -56,7 +56,7 @@ ], 'class A on _s_ {}', expectedErrorsInValidCode: [ParserErrorCode.EXPECTED_INSTEAD], - failing: ['functionVoid', 'functionNonVoid', 'getter']), + failing: ['functionVoid', 'functionNonVoid', 'getter', 'mixin']), new TestDescriptor('extendsBody', 'class A extends {}', [ParserErrorCode.EXPECTED_TYPE_NAME], 'class A extends _s_ {}'), new TestDescriptor( @@ -78,7 +78,7 @@ ParserErrorCode.MISSING_CLASS_BODY ], 'class A extends B with _s_ {}', - failing: ['functionVoid', 'functionNonVoid', 'getter']), + failing: ['functionVoid', 'functionNonVoid', 'getter', 'mixin']), new TestDescriptor( 'extendsNameWithBody', 'class A extends B with {}', @@ -92,7 +92,7 @@ ParserErrorCode.MISSING_CLASS_BODY ], 'class A extends B implements _s_ {}', - failing: ['functionVoid', 'functionNonVoid', 'getter']), + failing: ['functionVoid', 'functionNonVoid', 'getter', 'mixin']), new TestDescriptor( 'extendsNameImplementsBody', 'class A extends B implements {}', @@ -106,7 +106,7 @@ ParserErrorCode.MISSING_CLASS_BODY ], 'class A extends B with C implements _s_ {}', - failing: ['functionVoid', 'functionNonVoid', 'getter']), + failing: ['functionVoid', 'functionNonVoid', 'getter', 'mixin']), new TestDescriptor( 'extendsNameWithNameImplementsBody', 'class A extends B with C implements {}', @@ -120,7 +120,7 @@ ParserErrorCode.MISSING_CLASS_BODY ], 'class A implements _s_ {}', - failing: ['functionVoid', 'functionNonVoid', 'getter']), + failing: ['functionVoid', 'functionNonVoid', 'getter', 'mixin']), new TestDescriptor( 'implementsBody', 'class A implements {}', @@ -134,7 +134,7 @@ ParserErrorCode.MISSING_CLASS_BODY ], 'class A implements B, _s_ {}', - failing: ['functionVoid', 'functionNonVoid', 'getter']), + failing: ['functionVoid', 'functionNonVoid', 'getter', 'mixin']), new TestDescriptor( 'implementsNameCommaBody', 'class A implements B, {}', @@ -149,7 +149,7 @@ ParserErrorCode.EXPECTED_TOKEN ], 'class A = _s_ with _s_;', - failing: ['functionVoid', 'functionNonVoid', 'getter']), + failing: ['functionVoid', 'functionNonVoid', 'getter', 'mixin']), new TestDescriptor( 'equalsName', 'class A = B', @@ -164,7 +164,7 @@ ParserErrorCode.EXPECTED_TOKEN ], 'class A = B with _s_;', - failing: ['functionVoid', 'functionNonVoid', 'getter']), + failing: ['functionVoid', 'functionNonVoid', 'getter', 'mixin']), new TestDescriptor( 'equalsNameName', 'class A = B C',
diff --git a/pkg/analyzer/test/src/fasta/recovery/partial_code/constructor_test.dart b/pkg/analyzer/test/src/fasta/recovery/partial_code/constructor_test.dart index 3f834fd..d5a265d 100644 --- a/pkg/analyzer/test/src/fasta/recovery/partial_code/constructor_test.dart +++ b/pkg/analyzer/test/src/fasta/recovery/partial_code/constructor_test.dart
@@ -1,4 +1,8 @@ -import 'package:analyzer/analyzer.dart'; +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:analyzer/dart/ast/ast.dart'; import 'package:analyzer/dart/ast/token.dart'; import 'package:analyzer/src/dart/error/syntactic_errors.dart';
diff --git a/pkg/analyzer/test/src/fasta/recovery/partial_code/enum_declaration_test.dart b/pkg/analyzer/test/src/fasta/recovery/partial_code/enum_declaration_test.dart index 167587a..4f9ccd9 100644 --- a/pkg/analyzer/test/src/fasta/recovery/partial_code/enum_declaration_test.dart +++ b/pkg/analyzer/test/src/fasta/recovery/partial_code/enum_declaration_test.dart
@@ -50,6 +50,7 @@ 'typedef', 'functionNonVoid', 'getter', + 'mixin', 'setter' ]), new TestDescriptor( @@ -66,6 +67,7 @@ 'typedef', 'functionNonVoid', 'getter', + 'mixin', 'setter' ]), new TestDescriptor('value', 'enum E {a',
diff --git a/pkg/analyzer/test/src/fasta/recovery/partial_code/mixin_declaration_test.dart b/pkg/analyzer/test/src/fasta/recovery/partial_code/mixin_declaration_test.dart index 33fe03f..f962b3f 100644 --- a/pkg/analyzer/test/src/fasta/recovery/partial_code/mixin_declaration_test.dart +++ b/pkg/analyzer/test/src/fasta/recovery/partial_code/mixin_declaration_test.dart
@@ -34,7 +34,7 @@ ParserErrorCode.MISSING_CLASS_BODY ], 'mixin A on _s_ {}', - failing: ['functionVoid', 'functionNonVoid', 'getter']), + failing: ['functionVoid', 'functionNonVoid', 'getter', 'mixin']), new TestDescriptor( 'extend', 'mixin A extend', @@ -45,7 +45,7 @@ ], 'mixin A extend _s_ {}', expectedErrorsInValidCode: [ParserErrorCode.EXPECTED_INSTEAD], - failing: ['functionVoid', 'functionNonVoid', 'getter']), + failing: ['functionVoid', 'functionNonVoid', 'getter', 'mixin']), new TestDescriptor( 'extends', 'mixin A extends', @@ -56,7 +56,7 @@ ], 'mixin A extends _s_ {}', expectedErrorsInValidCode: [ParserErrorCode.EXPECTED_INSTEAD], - failing: ['functionVoid', 'functionNonVoid', 'getter']), + failing: ['functionVoid', 'functionNonVoid', 'getter', 'mixin']), new TestDescriptor('onBody', 'mixin A on {}', [ParserErrorCode.EXPECTED_TYPE_NAME], 'mixin A on _s_ {}'), new TestDescriptor( @@ -67,7 +67,7 @@ ParserErrorCode.MISSING_CLASS_BODY ], 'mixin A on B, _s_ {}', - failing: ['functionVoid', 'functionNonVoid', 'getter']), + failing: ['functionVoid', 'functionNonVoid', 'getter', 'mixin']), new TestDescriptor('onNameCommaBody', 'mixin A on B, {}', [ParserErrorCode.EXPECTED_TYPE_NAME], 'mixin A on B, _s_ {}'), new TestDescriptor( @@ -84,9 +84,9 @@ ParserErrorCode.MISSING_CLASS_BODY ], 'mixin A on B implements _s_ {}', - failing: ['functionVoid', 'functionNonVoid', 'getter']), + failing: ['functionVoid', 'functionNonVoid', 'getter', 'mixin']), new TestDescriptor( - 'onNameImplements', + 'onNameImplementsBody', 'mixin A on B implements {}', [ParserErrorCode.EXPECTED_TYPE_NAME], 'mixin A on B implements _s_ {}'), @@ -98,7 +98,7 @@ ParserErrorCode.MISSING_CLASS_BODY ], 'mixin A implements _s_ {}', - failing: ['functionVoid', 'functionNonVoid', 'getter']), + failing: ['functionVoid', 'functionNonVoid', 'getter', 'mixin']), new TestDescriptor( 'implementsBody', 'mixin A implements {}', @@ -112,7 +112,7 @@ ParserErrorCode.MISSING_CLASS_BODY ], 'mixin A implements B, _s_ {}', - failing: ['functionVoid', 'functionNonVoid', 'getter']), + failing: ['functionVoid', 'functionNonVoid', 'getter', 'mixin']), new TestDescriptor( 'implementsNameCommaBody', 'mixin A implements B, {}',
diff --git a/pkg/analyzer/test/src/fasta/recovery/partial_code/part_of_directive_test.dart b/pkg/analyzer/test/src/fasta/recovery/partial_code/part_of_directive_test.dart index 17da7bc..680886f 100644 --- a/pkg/analyzer/test/src/fasta/recovery/partial_code/part_of_directive_test.dart +++ b/pkg/analyzer/test/src/fasta/recovery/partial_code/part_of_directive_test.dart
@@ -34,7 +34,8 @@ ParserErrorCode.EXPECTED_STRING_LITERAL, ParserErrorCode.EXPECTED_TOKEN ], - 'part of "";'), + 'part of "";', + failing: ['mixin']), ], nonIdentifierSuffixes); buildTests(
diff --git a/pkg/analyzer/test/src/fasta/recovery/partial_code/partial_code_support.dart b/pkg/analyzer/test/src/fasta/recovery/partial_code/partial_code_support.dart index 62a722f..8634b8f 100644 --- a/pkg/analyzer/test/src/fasta/recovery/partial_code/partial_code_support.dart +++ b/pkg/analyzer/test/src/fasta/recovery/partial_code/partial_code_support.dart
@@ -1,8 +1,8 @@ -// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file +// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. -import 'package:analyzer/analyzer.dart'; +import 'package:analyzer/dart/ast/ast.dart'; import 'package:analyzer/error/error.dart'; import 'package:analyzer/src/dart/error/syntactic_errors.dart'; import 'package:test/test.dart'; @@ -46,6 +46,8 @@ */ static final List<TestSuffix> declarationSuffixes = <TestSuffix>[ new TestSuffix('class', 'class A {}'), + new TestSuffix('enum', 'enum E { v }'), + new TestSuffix('mixin', 'mixin M {}'), new TestSuffix('typedef', 'typedef A = B Function(C, D);'), new TestSuffix('functionVoid', 'void f() {}'), new TestSuffix('functionNonVoid', 'int f() {}'),
diff --git a/pkg/analyzer/test/src/fasta/recovery/partial_code/top_level_variable_test.dart b/pkg/analyzer/test/src/fasta/recovery/partial_code/top_level_variable_test.dart index e4cfd56..046e36c 100644 --- a/pkg/analyzer/test/src/fasta/recovery/partial_code/top_level_variable_test.dart +++ b/pkg/analyzer/test/src/fasta/recovery/partial_code/top_level_variable_test.dart
@@ -43,7 +43,7 @@ CompileTimeErrorCode.CONST_NOT_INITIALIZED ], "const a;", - failing: ['functionNonVoid', 'getter', 'setter'], + failing: ['functionNonVoid', 'getter', 'setter', 'mixin'], expectedErrorsInValidCode: [ CompileTimeErrorCode.CONST_NOT_INITIALIZED ], @@ -145,7 +145,7 @@ StaticWarningCode.FINAL_NOT_INITIALIZED ], "final a;", - failing: ['functionNonVoid', 'getter', 'setter'], + failing: ['functionNonVoid', 'getter', 'setter', 'mixin'], expectedErrorsInValidCode: [ StaticWarningCode.FINAL_NOT_INITIALIZED ], @@ -193,7 +193,7 @@ 'var a', [ParserErrorCode.EXPECTED_TOKEN], "var a;", - failing: ['functionNonVoid', 'getter', 'setter'], + failing: ['functionNonVoid', 'getter', 'mixin', 'setter'], ), new TestDescriptor( 'varNameEquals', @@ -209,7 +209,9 @@ 'functionVoid', 'functionNonVoid', 'const', + 'enum', 'getter', + 'mixin', 'setter' ], ),
diff --git a/pkg/analyzer/test/src/fasta/recovery/partial_code/typedef_test.dart b/pkg/analyzer/test/src/fasta/recovery/partial_code/typedef_test.dart index 95f261e..9466494 100644 --- a/pkg/analyzer/test/src/fasta/recovery/partial_code/typedef_test.dart +++ b/pkg/analyzer/test/src/fasta/recovery/partial_code/typedef_test.dart
@@ -33,7 +33,7 @@ ParserErrorCode.EXPECTED_TOKEN ], "typedef T();", - failing: ['functionNonVoid', 'getter', 'setter']), + failing: ['functionNonVoid', 'getter', 'mixin', 'setter']), new TestDescriptor( 'keywordEquals', 'typedef =', @@ -56,7 +56,7 @@ expectedErrorsInValidCode: [ ParserErrorCode.INVALID_GENERIC_FUNCTION_TYPE ], - failing: ['functionVoid', 'functionNonVoid', 'getter']), + failing: ['functionVoid', 'functionNonVoid', 'getter', 'mixin']), ], PartialCodeTest.declarationSuffixes); }
diff --git a/pkg/analyzer/test/src/hint/sdk_constraint_verifier.dart b/pkg/analyzer/test/src/hint/sdk_constraint_verifier.dart index ee9f466..ad910f0 100644 --- a/pkg/analyzer/test/src/hint/sdk_constraint_verifier.dart +++ b/pkg/analyzer/test/src/hint/sdk_constraint_verifier.dart
@@ -3,7 +3,8 @@ // BSD-style license that can be found in the LICENSE file. import 'package:analyzer/error/error.dart'; -import 'package:analyzer/file_system/file_system.dart'; +import 'package:analyzer/src/generated/engine.dart' show AnalysisOptionsImpl; +import 'package:pub_semver/pub_semver.dart'; import '../../generated/resolver_test_case.dart'; import '../../generated/test_support.dart'; @@ -15,10 +16,10 @@ verifyVersion(String version, String source, {List<ErrorCode> errorCodes}) async { - newFile('/pubspec.yaml', content: ''' -environment: - sdk: ^$version -'''); + driver.configure( + analysisOptions: AnalysisOptionsImpl() + ..sdkVersionConstraint = VersionConstraint.parse(version)); + TestAnalysisResult result = await computeTestAnalysisResult(source); GatheringErrorListener listener = new GatheringErrorListener(); listener.addAll(result.errors); @@ -28,11 +29,4 @@ listener.assertErrorsWithCodes(errorCodes); } } - - File newFile(String path, {String content = ''}) { - // Copied from ResourceProviderMixin because ResolverTestCase does not apply - // that mixin on this branch. - String convertedPath = resourceProvider.convertPath(path); - return resourceProvider.newFile(convertedPath, content); - } }
diff --git a/pkg/analyzer/test/src/hint/sdk_version_async_exported_from_core_test.dart b/pkg/analyzer/test/src/hint/sdk_version_async_exported_from_core_test.dart index 38bf64b..a9f42b6 100644 --- a/pkg/analyzer/test/src/hint/sdk_version_async_exported_from_core_test.dart +++ b/pkg/analyzer/test/src/hint/sdk_version_async_exported_from_core_test.dart
@@ -69,7 +69,7 @@ test_lessThan_explicitImportOfCore() async { await verifyVersion('2.0.0', ''' -import 'dart:core'; +import 'dart:core' show Future, int; Future<int> zero() async => 0; ''', errorCodes: [HintCode.SDK_VERSION_ASYNC_EXPORTED_FROM_CORE]); @@ -102,4 +102,28 @@ Future<int> zero() async => 0; ''', errorCodes: [HintCode.SDK_VERSION_ASYNC_EXPORTED_FROM_CORE]); } + + test_lessThan_onlyReferencedInExport_hide() async { + await verifyVersion('2.0.0', ''' +export 'dart:async' hide Future; +'''); + } + + test_lessThan_onlyReferencedInExport_show() async { + await verifyVersion('2.0.0', ''' +export 'dart:async' show Future; +'''); + } + + test_lessThan_onlyReferencedInImport_hide() async { + await verifyVersion('2.0.0', ''' +import 'dart:core' hide Future; +'''); + } + + test_lessThan_onlyReferencedInImport_show() async { + await verifyVersion('2.0.0', ''' +import 'dart:core' show Future; +'''); + } }
diff --git a/pkg/analyzer/test/src/lint/linter/linter_context_impl_test.dart b/pkg/analyzer/test/src/lint/linter/linter_context_impl_test.dart new file mode 100644 index 0000000..49e4be9 --- /dev/null +++ b/pkg/analyzer/test/src/lint/linter/linter_context_impl_test.dart
@@ -0,0 +1,121 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'dart:async'; + +import 'package:analyzer/dart/analysis/results.dart'; +import 'package:analyzer/src/dart/ast/ast.dart'; +import 'package:analyzer/src/dart/ast/utilities.dart'; +import 'package:analyzer/src/generated/source.dart'; +import 'package:analyzer/src/lint/linter.dart'; +import 'package:test/test.dart'; +import 'package:test_reflective_loader/test_reflective_loader.dart'; + +import '../../../generated/resolver_test_case.dart'; + +main() { + defineReflectiveSuite(() { + defineReflectiveTests(LinterContextImplTest); + }); +} + +@reflectiveTest +class LinterContextImplTest extends ResolverTestCase { + String testSource; + CompilationUnitImpl testUnit; + LinterContextImpl context; + + bool get enableNewAnalysisDriver => true; + + void assertCanBeConst(String snippet, bool expectedResult) { + int index = testSource.indexOf(snippet); + expect(index >= 0, isTrue); + NodeLocator visitor = new NodeLocator(index); + AstNodeImpl node = visitor.searchWithin(testUnit); + node = node.thisOrAncestorOfType<InstanceCreationExpressionImpl>(); + expect(node, isNotNull); + expect(context.canBeConst(node as InstanceCreationExpressionImpl), + expectedResult ? isTrue : isFalse); + } + + Future<void> resolve(String sourceText) async { + testSource = sourceText; + Source source = addNamedSource('/test.dart', sourceText); + ResolvedUnitResult analysisResult = await driver.getResult(source.fullName); + testUnit = analysisResult.unit; + LinterContextUnit contextUnit = new LinterContextUnit(sourceText, testUnit); + context = new LinterContextImpl( + [contextUnit], + contextUnit, + analysisResult.session.declaredVariables, + analysisResult.typeProvider, + analysisResult.typeSystem); + } + + void test_canBeConst_false_argument_invocation() async { + await resolve(''' +class A {} +class B { + const B(A a); +} +A f() => A(); +B g() => B(f()); +'''); + assertCanBeConst("B(f", false); + } + + void test_canBeConst_false_argument_invocationInList() async { + await resolve(''' +class A {} +class B { + const B(a); +} +A f() => A(); +B g() => B([f()]); +'''); + assertCanBeConst("B([", false); + } + + void test_canBeConst_false_argument_nonConstConstructor() async { + await resolve(''' +class A {} +class B { + const B(A a); +} +B f() => B(A()); +'''); + assertCanBeConst("B(A(", false); + } + + void test_canBeConst_false_nonConstConstructor() async { + await resolve(''' +class A {} +A f() => A(); +'''); + assertCanBeConst("A(", false); + } + + void test_canBeConst_true_constConstructorArg() async { + await resolve(''' +class A { + const A(); +} +class B { + const B(A a); +} +B f() => B(A()); +'''); + assertCanBeConst("B(A(", true); + } + + void test_canBeConst_true_constListArg() async { + await resolve(''' +class A { + const A(List<int> l); +} +A f() => A([1, 2, 3]); +'''); + assertCanBeConst("A([", true); + } +}
diff --git a/pkg/analyzer/test/src/lint/linter/test_all.dart b/pkg/analyzer/test/src/lint/linter/test_all.dart new file mode 100644 index 0000000..101588b --- /dev/null +++ b/pkg/analyzer/test/src/lint/linter/test_all.dart
@@ -0,0 +1,13 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:test_reflective_loader/test_reflective_loader.dart'; + +import 'linter_context_impl_test.dart' as linter_context_impl; + +main() { + defineReflectiveSuite(() { + linter_context_impl.main(); + }, name: 'linter'); +}
diff --git a/pkg/analyzer/test/src/lint/test_all.dart b/pkg/analyzer/test/src/lint/test_all.dart index 60555a3..47596f2 100644 --- a/pkg/analyzer/test/src/lint/test_all.dart +++ b/pkg/analyzer/test/src/lint/test_all.dart
@@ -1,20 +1,21 @@ -// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file +// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. import 'package:test_reflective_loader/test_reflective_loader.dart'; -import 'config_test.dart' as config_test; -import 'io_test.dart' as io_test; -import 'project_test.dart' as project_test; -import 'pub_test.dart' as pub_test; +import 'config_test.dart' as config; +import 'io_test.dart' as io; +import 'linter/test_all.dart' as linter; +import 'project_test.dart' as project; +import 'pub_test.dart' as pub; -/// Utility for manually running all tests. main() { defineReflectiveSuite(() { - config_test.main(); - io_test.main(); - project_test.main(); - pub_test.main(); + config.main(); + io.main(); + linter.main(); + project.main(); + pub.main(); }, name: 'lint'); }
diff --git a/pkg/analyzer/test/src/options/options_rule_validator_test.dart b/pkg/analyzer/test/src/options/options_rule_validator_test.dart new file mode 100644 index 0000000..fad56f3 --- /dev/null +++ b/pkg/analyzer/test/src/options/options_rule_validator_test.dart
@@ -0,0 +1,76 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:analyzer/error/error.dart'; +import 'package:analyzer/error/listener.dart'; +import 'package:analyzer/src/lint/linter.dart'; +import 'package:analyzer/src/lint/options_rule_validator.dart'; +import 'package:analyzer/src/string_source.dart'; +import 'package:analyzer/src/test_utilities/resource_provider_mixin.dart'; +import 'package:test_reflective_loader/test_reflective_loader.dart'; +import 'package:yaml/yaml.dart'; + +import '../../generated/test_support.dart'; + +main() { + defineReflectiveSuite(() { + defineReflectiveTests(OptionsRuleValidatorTest); + }); +} + +class DeprecatedLint extends LintRule { + DeprecatedLint() + : super( + name: 'deprecated_lint', + group: Group.style, + maturity: Maturity.deprecated); +} + +class StableLint extends LintRule { + StableLint() + : super( + name: 'stable_lint', group: Group.style, maturity: Maturity.stable); +} + +@reflectiveTest +class OptionsRuleValidatorTest extends Object with ResourceProviderMixin { + LinterRuleOptionsValidator validator = new LinterRuleOptionsValidator( + provider: () => [new DeprecatedLint(), new StableLint()]); + +/** + * Assert that when the validator is used on the given [content] the + * [expectedErrorCodes] are produced. + */ + void assertErrors(String content, List<ErrorCode> expectedErrorCodes) { + GatheringErrorListener listener = new GatheringErrorListener(); + ErrorReporter reporter = new ErrorReporter( + listener, new StringSource(content, 'analysis_options.yaml')); + validator.validate(reporter, loadYamlNode(content)); + listener.assertErrorsWithCodes(expectedErrorCodes); + } + + test_deprecated_rule() { + assertErrors(''' +linter: + rules: + - deprecated_lint + ''', [DEPRECATED_LINT_HINT]); + } + + test_stable_rule() { + assertErrors(''' +linter: + rules: + - stable_lint + ''', []); + } + + test_undefined_rule() { + assertErrors(''' +linter: + rules: + - this_rule_does_not_exist + ''', [UNDEFINED_LINT_WARNING]); + } +}
diff --git a/pkg/analyzer/test/src/options/test_all.dart b/pkg/analyzer/test/src/options/test_all.dart new file mode 100644 index 0000000..e38e1676 --- /dev/null +++ b/pkg/analyzer/test/src/options/test_all.dart
@@ -0,0 +1,13 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:test_reflective_loader/test_reflective_loader.dart'; + +import 'options_rule_validator_test.dart' as options_rule_validator; + +main() { + defineReflectiveSuite(() { + options_rule_validator.main(); + }, name: 'options'); +}
diff --git a/pkg/analyzer/test/src/pubspec/pubspec_validator_test.dart b/pkg/analyzer/test/src/pubspec/pubspec_validator_test.dart index f841d78..ef1cc99b 100644 --- a/pkg/analyzer/test/src/pubspec/pubspec_validator_test.dart +++ b/pkg/analyzer/test/src/pubspec/pubspec_validator_test.dart
@@ -1,4 +1,4 @@ -// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file +// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. @@ -20,7 +20,7 @@ } @reflectiveTest -class PubspecValidatorTest extends Object with ResourceProviderMixin { +class PubspecValidatorTest with ResourceProviderMixin { PubspecValidator validator; /**
diff --git a/pkg/analyzer/test/src/source/source_resource_test.dart b/pkg/analyzer/test/src/source/source_resource_test.dart index abf46f6..863117b 100644 --- a/pkg/analyzer/test/src/source/source_resource_test.dart +++ b/pkg/analyzer/test/src/source/source_resource_test.dart
@@ -1,4 +1,4 @@ -// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file +// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. @@ -10,12 +10,11 @@ import 'package:analyzer/src/generated/source.dart'; import 'package:analyzer/src/generated/utilities_dart.dart'; import 'package:analyzer/src/source/source_resource.dart'; +import 'package:analyzer/src/test_utilities/mock_sdk.dart'; import 'package:analyzer/src/test_utilities/resource_provider_mixin.dart'; import 'package:test/test.dart'; import 'package:test_reflective_loader/test_reflective_loader.dart'; -import '../context/mock_sdk.dart'; - main() { defineReflectiveSuite(() { defineReflectiveTests(FileSourceTest); @@ -23,7 +22,7 @@ } @reflectiveTest -class FileSourceTest extends Object with ResourceProviderMixin { +class FileSourceTest with ResourceProviderMixin { void test_equals_false_differentFiles() { File file1 = getFile("/does/not/exist1.dart"); File file2 = getFile("/does/not/exist2.dart");
diff --git a/pkg/analyzer/test/src/summary/expr_builder_test.dart b/pkg/analyzer/test/src/summary/expr_builder_test.dart index c17d7f8..c7d69df 100644 --- a/pkg/analyzer/test/src/summary/expr_builder_test.dart +++ b/pkg/analyzer/test/src/summary/expr_builder_test.dart
@@ -1,4 +1,4 @@ -// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. @@ -27,7 +27,7 @@ /// Mixin containing test cases exercising the [ExprBuilder]. Intended to be /// applied to a class implementing [ResynthesizeTestStrategy], along with the /// mixin [ExprBuilderTestHelpers]. -abstract class ExprBuilderTestCases implements ExprBuilderTestHelpers { +mixin ExprBuilderTestCases implements ExprBuilderTestHelpers { void test_add() { checkSimpleExpression('0 + 1'); } @@ -360,7 +360,7 @@ @failingTest void test_pushLocalFunctionReference_nested() { - prepareAnalysisContext(new AnalysisOptionsImpl()..previewDart2 = false); + prepareAnalysisContext(new AnalysisOptionsImpl()); var expr = checkSimpleExpression('(x) => (y) => x + y') as FunctionExpression; var outerFunctionElement = expr.declaredElement; @@ -383,7 +383,7 @@ @failingTest void test_pushLocalFunctionReference_paramReference() { - prepareAnalysisContext(new AnalysisOptionsImpl()..previewDart2 = false); + prepareAnalysisContext(new AnalysisOptionsImpl()); var expr = checkSimpleExpression('(x, y) => x + y') as FunctionExpression; var localFunctionElement = expr.declaredElement; var xElement = localFunctionElement.parameters[0]; @@ -478,9 +478,9 @@ } } -/// Mixin containing helper methods for testing the [ExprBuilder]. Intended to +/// Mixin containing helper methods for testing the [ExprBuilder]. Intended to /// be applied to a class implementing [ResynthesizeTestStrategy]. -abstract class ExprBuilderTestHelpers implements ResynthesizeTestStrategy { +mixin ExprBuilderTestHelpers implements ResynthesizeTestStrategy { Expression buildConstructorInitializer(String sourceText, {String className: 'C', String initializerName: 'x',
diff --git a/pkg/analyzer/test/src/summary/linker_test.dart b/pkg/analyzer/test/src/summary/linker_test.dart index 4a6136f..96d7b4d 100644 --- a/pkg/analyzer/test/src/summary/linker_test.dart +++ b/pkg/analyzer/test/src/summary/linker_test.dart
@@ -26,7 +26,7 @@ /// These test cases may be mixed into any class derived from /// [SummaryLinkerTestStrategy], allowing the linker to be unit-tested in a /// variety of ways. -abstract class LinkerUnitTestCases implements SummaryLinkerTestStrategy { +mixin LinkerUnitTestCases implements SummaryLinkerTestStrategy { Matcher get isUndefined => const TypeMatcher<UndefinedElementForLink>(); LibraryElementForLink getLibrary(String uri) {
diff --git a/pkg/analyzer/test/src/summary/package_bundle_reader_test.dart b/pkg/analyzer/test/src/summary/package_bundle_reader_test.dart index 0709a95..1061dba 100644 --- a/pkg/analyzer/test/src/summary/package_bundle_reader_test.dart +++ b/pkg/analyzer/test/src/summary/package_bundle_reader_test.dart
@@ -368,7 +368,7 @@ _TestResynthesizerResultProvider( InternalAnalysisContext context, SummaryDataStore dataStore) - : super(context, dataStore); + : super(context, null, dataStore); @override bool hasResultsForSource(Source source) {
diff --git a/pkg/analyzer/test/src/summary/resynthesize_common.dart b/pkg/analyzer/test/src/summary/resynthesize_common.dart index adbbdba..4995afb 100644 --- a/pkg/analyzer/test/src/summary/resynthesize_common.dart +++ b/pkg/analyzer/test/src/summary/resynthesize_common.dart
@@ -25,12 +25,12 @@ import 'package:analyzer/src/generated/testing/ast_test_factory.dart'; import 'package:analyzer/src/summary/idl.dart'; import 'package:analyzer/src/summary/resynthesize.dart'; +import 'package:analyzer/src/test_utilities/mock_sdk.dart'; import 'package:test/test.dart'; import 'package:test_reflective_loader/test_reflective_loader.dart'; import '../../generated/test_support.dart'; import '../abstract_single_unit.dart'; -import '../context/abstract_context.dart'; import 'element_text.dart'; import 'test_strategies.dart'; @@ -100,7 +100,7 @@ } } - DartSdk createDartSdk() => AbstractContextTest.SHARED_MOCK_SDK; + DartSdk createDartSdk() => new MockSdk(resourceProvider: resourceProvider); /** * Create the analysis options that should be used for this test. @@ -117,7 +117,7 @@ /// Mixin containing test cases exercising summary resynthesis. Intended to be /// applied to a class implementing [ResynthesizeTestStrategy], along with the /// mixin [ResynthesizeTestHelpers]. -abstract class ResynthesizeTestCases implements ResynthesizeTestHelpers { +mixin ResynthesizeTestCases implements ResynthesizeTestHelpers { test_class_abstract() async { var library = await checkLibrary('abstract class C {}'); checkElementText(library, r''' @@ -2152,7 +2152,9 @@ checkElementText(library, r''' class C { } -const dynamic V = #invalidConst; +const dynamic V = const + C/*location: test.dart;C*/. + named/*location: null*/(); '''); } @@ -2162,7 +2164,9 @@ const V = const C.named(); ''', allowErrors: true); checkElementText(library, r''' -const dynamic V = #invalidConst; +const dynamic V = const + C/*location: null*/. + named/*location: null*/(); '''); } @@ -2178,7 +2182,10 @@ ''', allowErrors: true); checkElementText(library, r''' import 'a.dart' as p; -const dynamic V = #invalidConst; +const dynamic V = const + p/*location: test.dart;p*/. + C/*location: a.dart;C*/. + named/*location: null*/(); '''); } @@ -2191,7 +2198,10 @@ ''', allowErrors: true); checkElementText(library, r''' import 'a.dart' as p; -const dynamic V = #invalidConst; +const dynamic V = const + p/*location: test.dart;p*/. + C/*location: null*/. + named/*location: null*/(); '''); } @@ -2201,7 +2211,10 @@ const V = const p.C.named(); ''', allowErrors: true); checkElementText(library, r''' -const dynamic V = #invalidConst; +const dynamic V = const + p/*location: null*/. + C/*location: null*/. + named/*location: null*/(); '''); } @@ -2214,7 +2227,9 @@ checkElementText(library, r''' class C<T> { } -const dynamic V = #invalidConst; +const dynamic V = const + C/*location: test.dart;C*/. + named/*location: null*/(); '''); } @@ -2274,7 +2289,8 @@ const V = const C(); ''', allowErrors: true); checkElementText(library, r''' -const dynamic V = #invalidConst; +const dynamic V = const + C/*location: null*/(); '''); } @@ -2287,7 +2303,9 @@ ''', allowErrors: true); checkElementText(library, r''' import 'a.dart' as p; -const dynamic V = #invalidConst; +const dynamic V = const + p/*location: test.dart;p*/. + C/*location: null*/(); '''); } @@ -2297,7 +2315,9 @@ const V = const p.C(); ''', allowErrors: true); checkElementText(library, r''' -const dynamic V = #invalidConst; +const dynamic V = const + p/*location: null*/. + C/*location: null*/(); '''); } @@ -2863,7 +2883,8 @@ const V = foo; ''', allowErrors: true); checkElementText(library, r''' -const dynamic V = #invalidConst; +const dynamic V = + foo/*location: null*/; '''); } @@ -2876,7 +2897,9 @@ checkElementText(library, r''' class C { } -const dynamic V = #invalidConst; +const dynamic V = + C/*location: test.dart;C*/. + foo/*location: null*/; '''); } @@ -2891,7 +2914,10 @@ ''', allowErrors: true); checkElementText(library, r''' import 'foo.dart' as p; -const dynamic V = #invalidConst; +const dynamic V = + p/*location: test.dart;p*/. + C/*location: foo.dart;C*/. + foo/*location: null*/; '''); } @@ -3029,7 +3055,7 @@ const vSuper = super; '''); checkElementText(library, r''' -const dynamic vSuper = #invalidConst; +const dynamic vSuper = super; '''); } @@ -3039,7 +3065,7 @@ const vThis = this; '''); checkElementText(library, r''' -const dynamic vThis = #invalidConst; +const dynamic vThis = this; '''); } @@ -5145,7 +5171,8 @@ import ''; '''); checkElementText(library, r''' -@#invalidConst +@ + foo/*location: null*/ import '<unresolved>'; '''); } @@ -5894,7 +5921,10 @@ '''); checkElementText(library, r''' import 'a.dart' as a; -@#invalidConst +@ + a/*location: test.dart;a*/. + C/*location: a.dart;C*/. + named/*location: a.dart;C;named*/ class D { } '''); @@ -5914,7 +5944,9 @@ '''); checkElementText(library, r''' import 'a.dart'; -@#invalidConst +@ + C/*location: a.dart;C*/. + named/*location: a.dart;C;named*/ class D { } '''); @@ -5948,7 +5980,8 @@ checkElementText(library, r''' import 'a.dart'; import 'b.dart'; -dynamic foo([dynamic p = #invalidConst]) {} +dynamic foo([dynamic p = + V/*location: null*/]) {} '''); } @@ -5967,7 +6000,8 @@ '''); checkElementText(library, r''' import 'c.dart'; -dynamic foo([dynamic p = #invalidConst]) {} +dynamic foo([dynamic p = + V/*location: null*/]) {} '''); } @@ -5981,7 +6015,8 @@ '''); checkElementText(library, r''' dynamic V; -dynamic foo([dynamic p = #invalidConst]) {} +dynamic foo([dynamic p = + V/*location: null*/]) {} dynamic V() {} '''); } @@ -6662,7 +6697,8 @@ shouldCompareLibraryElements = false; var library = await checkLibrary('f(_) {} @f(42) class C {}'); checkElementText(library, r''' -@#invalidConst +@ + __unresolved__/*location: null*/ class C { } dynamic f(dynamic _) {} @@ -8323,7 +8359,8 @@ class A { const A(dynamic _); } -@#invalidConst +@ + A/*location: test.dart;A*/(this) class C { } '''); @@ -8334,7 +8371,9 @@ var library = await checkLibrary('@foo.bar() class C {}', allowErrors: true); checkElementText(library, r''' -@#invalidConst +@ + foo/*location: null*/. + bar/*location: null*/() class C { } '''); @@ -8345,7 +8384,9 @@ var library = await checkLibrary('@String.foo() class C {}', allowErrors: true); checkElementText(library, r''' -@#invalidConst +@ + String/*location: dart:core;String*/. + foo/*location: null*/() class C { } '''); @@ -8355,7 +8396,9 @@ shouldCompareLibraryElements = false; var library = await checkLibrary('@foo.bar class C {}', allowErrors: true); checkElementText(library, r''' -@#invalidConst +@ + foo/*location: null*/. + bar/*location: null*/ class C { } '''); @@ -8368,7 +8411,9 @@ allowErrors: true); checkElementText(library, r''' import 'dart:async' as foo; -@#invalidConst +@ + foo/*location: test.dart;foo*/. + bar/*location: null*/ class C { } '''); @@ -8379,7 +8424,10 @@ var library = await checkLibrary('@foo.bar.baz() class C {}', allowErrors: true); checkElementText(library, r''' -@#invalidConst +@ + foo/*location: null*/. + bar/*location: null*/. + baz/*location: null*/() class C { } '''); @@ -8392,7 +8440,10 @@ allowErrors: true); checkElementText(library, r''' import 'dart:async' as foo; -@#invalidConst +@ + foo/*location: test.dart;foo*/. + bar/*location: null*/. + baz/*location: null*/() class C { } '''); @@ -8405,7 +8456,10 @@ allowErrors: true); checkElementText(library, r''' import 'dart:async' as foo; -@#invalidConst +@ + foo/*location: test.dart;foo*/. + Future/*location: dart:async;Future*/. + bar/*location: null*/() class C { } '''); @@ -8416,7 +8470,9 @@ var library = await checkLibrary('@foo.bar() class C {}', allowErrors: true); checkElementText(library, r''' -@#invalidConst +@ + foo/*location: null*/. + bar/*location: null*/() class C { } '''); @@ -8429,7 +8485,9 @@ allowErrors: true); checkElementText(library, r''' import 'dart:async' as foo; -@#invalidConst +@ + foo/*location: test.dart;foo*/. + bar/*location: null*/() class C { } '''); @@ -8439,7 +8497,8 @@ shouldCompareLibraryElements = false; var library = await checkLibrary('@foo class C {}', allowErrors: true); checkElementText(library, r''' -@#invalidConst +@ + foo/*location: null*/ class C { } '''); @@ -8449,7 +8508,8 @@ shouldCompareLibraryElements = false; var library = await checkLibrary('@foo() class C {}', allowErrors: true); checkElementText(library, r''' -@#invalidConst +@ + foo/*location: null*/() class C { } '''); @@ -8746,7 +8806,7 @@ /// Mixin containing helper methods for testing summary resynthesis. Intended /// to be applied to a class implementing [ResynthesizeTestStrategy]. -abstract class ResynthesizeTestHelpers implements ResynthesizeTestStrategy { +mixin ResynthesizeTestHelpers implements ResynthesizeTestStrategy { /** * Names of variables which have initializers that are not valid constants, * so they are not resynthesized. @@ -10012,7 +10072,7 @@ TestSummaryResynthesizer(AnalysisContext context, this.unlinkedSummaries, this.linkedSummaries, this.allowMissingFiles) - : super(context, context.sourceFactory, true) { + : super(context, null, context.sourceFactory, true) { // Clear after resynthesizing TypeProvider in super(). unlinkedSummariesRequested.clear(); linkedSummariesRequested.clear();
diff --git a/pkg/analyzer/test/src/summary/summary_common.dart b/pkg/analyzer/test/src/summary/summary_common.dart index 3f1e604..768bc8e 100644 --- a/pkg/analyzer/test/src/summary/summary_common.dart +++ b/pkg/analyzer/test/src/summary/summary_common.dart
@@ -1,8 +1,7 @@ -// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file +// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. -import 'package:analyzer/analyzer.dart'; import 'package:analyzer/dart/ast/ast.dart'; import 'package:analyzer/error/listener.dart'; import 'package:analyzer/src/dart/scanner/reader.dart'; @@ -79,7 +78,7 @@ /// These test cases may be mixed into any class derived from /// [SummaryBlackBoxTestStrategy], allowing summary generation to be unit-tested /// in a variety of ways. -abstract class SummaryTestCases implements SummaryBlackBoxTestStrategy { +mixin SummaryTestCases implements SummaryBlackBoxTestStrategy { /** * Get access to the linked defining compilation unit. */ @@ -796,8 +795,11 @@ * with the given [variableName]. */ UnlinkedVariable serializeVariableText(String text, - {String variableName: 'v', bool allowErrors: false}) { - serializeLibraryText(text, allowErrors: allowErrors); + {String variableName: 'v', + bool allowErrors: false, + bool enableSetLiterals: enableSetLiteralsDefault}) { + serializeLibraryText(text, + allowErrors: allowErrors, enableSetLiterals: enableSetLiterals); return findVariable(variableName, failIfAbsent: true); } @@ -2836,6 +2838,117 @@ ]); } + test_constExpr_makeTypedSet() { + UnlinkedVariable variable = serializeVariableText( + 'const v = const <int>{11, 22, 33};', + enableSetLiterals: true); + assertUnlinkedConst(variable.initializer.bodyExpr, operators: [ + UnlinkedExprOperation.pushInt, + UnlinkedExprOperation.pushInt, + UnlinkedExprOperation.pushInt, + UnlinkedExprOperation.makeTypedSet + ], ints: [ + 11, + 22, + 33, + 3 + ], referenceValidators: [ + (EntityRef r) => checkTypeRef(r, 'dart:core', 'int', + expectedKind: ReferenceKind.classOrEnum) + ]); + } + + test_constExpr_makeTypedSet_dynamic() { + UnlinkedVariable variable = serializeVariableText( + 'const v = const <dynamic>{11, 22, 33};', + enableSetLiterals: true); + assertUnlinkedConst(variable.initializer.bodyExpr, operators: [ + UnlinkedExprOperation.pushInt, + UnlinkedExprOperation.pushInt, + UnlinkedExprOperation.pushInt, + UnlinkedExprOperation.makeTypedSet + ], ints: [ + 11, + 22, + 33, + 3 + ], referenceValidators: [ + (EntityRef r) => checkDynamicTypeRef(r) + ]); + } + + test_constExpr_makeTypedSet_functionType() { + UnlinkedVariable variable = serializeVariableText( + 'final v = <void Function(int)>{};', + enableSetLiterals: true); + assertUnlinkedConst(variable.initializer.bodyExpr, + operators: [UnlinkedExprOperation.makeTypedSet], + ints: [ + 0 // Size of the list + ], + referenceValidators: [ + (EntityRef reference) { + expect(reference, new TypeMatcher<EntityRef>()); + expect(reference.entityKind, EntityRefKind.genericFunctionType); + expect(reference.syntheticParams, hasLength(1)); + { + final param = reference.syntheticParams[0]; + expect(param.name, ''); // no name for generic type parameters + checkTypeRef(param.type, 'dart:core', 'int', + expectedKind: ReferenceKind.classOrEnum); + } + expect(reference.paramReference, 0); + expect(reference.typeParameters, hasLength(0)); + // TODO(mfairhurst) check this references void + expect(reference.syntheticReturnType, isNotNull); + } + ], + forTypeInferenceOnly: true); + } + + test_constExpr_makeTypedSet_functionType_withTypeParameters() { + UnlinkedVariable variable = serializeVariableText( + 'final v = <void Function<T>(Function<Q>(T, Q))>{};', + enableSetLiterals: true); + assertUnlinkedConst(variable.initializer.bodyExpr, + operators: [UnlinkedExprOperation.makeTypedSet], + ints: [ + 0 // Size of the list + ], + referenceValidators: [ + (EntityRef reference) { + expect(reference, new TypeMatcher<EntityRef>()); + expect(reference.entityKind, EntityRefKind.genericFunctionType); + expect(reference.syntheticParams, hasLength(1)); + { + final param = reference.syntheticParams[0]; + expect(param.type, new TypeMatcher<EntityRef>()); + expect(param.type.entityKind, EntityRefKind.genericFunctionType); + expect(param.type.syntheticParams, hasLength(2)); + { + final subparam = param.type.syntheticParams[0]; + expect( + subparam.name, ''); // no name for generic type parameters + expect(subparam.type, new TypeMatcher<EntityRef>()); + expect(subparam.type.paramReference, 2); + } + { + final subparam = param.type.syntheticParams[1]; + expect( + subparam.name, ''); // no name for generic type parameters + expect(subparam.type, new TypeMatcher<EntityRef>()); + expect(subparam.type.paramReference, 1); + } + } + expect(reference.paramReference, 0); + expect(reference.typeParameters, hasLength(1)); + // TODO(mfairhurst) check this references void + expect(reference.syntheticReturnType, isNotNull); + } + ], + forTypeInferenceOnly: true); + } + test_constExpr_makeUntypedList() { UnlinkedVariable variable = serializeVariableText('const v = const [11, 22, 33];'); @@ -2875,6 +2988,23 @@ ]); } + test_constExpr_makeUntypedSet() { + UnlinkedVariable variable = serializeVariableText( + 'const v = const {11, 22, 33};', + enableSetLiterals: true); + assertUnlinkedConst(variable.initializer.bodyExpr, operators: [ + UnlinkedExprOperation.pushInt, + UnlinkedExprOperation.pushInt, + UnlinkedExprOperation.pushInt, + UnlinkedExprOperation.makeUntypedSet + ], ints: [ + 11, + 22, + 33, + 3 + ]); + } + test_constExpr_parenthesized() { UnlinkedVariable variable = serializeVariableText('const v = (1 + 2) * 3;'); assertUnlinkedConst(variable.initializer.bodyExpr, operators: [ @@ -7127,6 +7257,20 @@ forTypeInferenceOnly: true); } + test_expr_makeTypedSet() { + UnlinkedVariable variable = serializeVariableText( + 'var v = <int>{11, 22, 33};', + enableSetLiterals: true); + assertUnlinkedConst(variable.initializer.bodyExpr, + operators: [UnlinkedExprOperation.makeTypedSet], + ints: [0], + referenceValidators: [ + (EntityRef r) => checkTypeRef(r, 'dart:core', 'int', + expectedKind: ReferenceKind.classOrEnum) + ], + forTypeInferenceOnly: true); + } + test_expr_makeUntypedList() { UnlinkedVariable variable = serializeVariableText('var v = [11, 22, 33];'); assertUnlinkedConst(variable.initializer.bodyExpr, @@ -7158,6 +7302,20 @@ forTypeInferenceOnly: true); } + test_expr_makeUntypedSet() { + UnlinkedVariable variable = + serializeVariableText('var v = {11, 22, 33};', enableSetLiterals: true); + assertUnlinkedConst(variable.initializer.bodyExpr, + operators: [ + UnlinkedExprOperation.pushInt, + UnlinkedExprOperation.pushInt, + UnlinkedExprOperation.pushInt, + UnlinkedExprOperation.makeUntypedSet + ], + ints: [11, 22, 33, 3], + forTypeInferenceOnly: true); + } + test_expr_super() { UnlinkedVariable variable = serializeVariableText(''' final v = super; @@ -9640,6 +9798,16 @@ checkDynamicTypeRef(serializeTypeText('dynamic')); } + test_type_inference_based_on_type_parameter() { + var class_ = serializeClassText(''' +class C<T> { + var field = T; +} +'''); + var field = class_.fields[0]; + checkLinkedTypeSlot(field.inferredTypeSlot, 'dart:core', 'Type'); + } + test_type_invalid_typeParameter_asPrefix() { UnlinkedClass c = serializeClassText(''' class C<T> {
diff --git a/pkg/analyzer/test/src/summary/test_strategies.dart b/pkg/analyzer/test/src/summary/test_strategies.dart index 03c020d..b7b7958 100644 --- a/pkg/analyzer/test/src/summary/test_strategies.dart +++ b/pkg/analyzer/test/src/summary/test_strategies.dart
@@ -23,10 +23,10 @@ import 'package:analyzer/src/summary/summarize_elements.dart'; import 'package:analyzer/src/task/api/dart.dart'; import 'package:analyzer/src/task/api/general.dart'; +import 'package:analyzer/src/test_utilities/mock_sdk.dart'; import 'package:path/path.dart' show posix; import 'package:test/test.dart'; -import '../context/mock_sdk.dart'; import 'resynthesize_common.dart'; /// Convert the given Posix style file [path] to the corresponding absolute URI. @@ -35,13 +35,15 @@ return posix.toUri(absolutePath).toString(); } -CompilationUnit _parseText(String text) { +CompilationUnit _parseText(String text, + {bool enableSetLiterals: enableSetLiteralsDefault}) { CharSequenceReader reader = new CharSequenceReader(text); Scanner scanner = new Scanner(null, reader, AnalysisErrorListener.NULL_LISTENER); Token token = scanner.tokenize(); - Parser parser = new Parser( - NonExistingSource.unknown, AnalysisErrorListener.NULL_LISTENER); + Parser parser = + new Parser(NonExistingSource.unknown, AnalysisErrorListener.NULL_LISTENER) + ..enableSetLiterals = enableSetLiterals; CompilationUnit unit = parser.parseCompilationUnit(token); unit.lineInfo = new LineInfo(scanner.lineStarts); return unit; @@ -257,7 +259,9 @@ try { Map<String, UnlinkedUnit> uriToUnlinkedUnit = <String, UnlinkedUnit>{}; Map<String, LinkedLibrary> uriToLinkedLibrary = <String, LinkedLibrary>{}; - PackageBundle bundle = new MockSdk().getLinkedBundle(); + var resourceProvider = new MemoryResourceProvider(); + PackageBundle bundle = + new MockSdk(resourceProvider: resourceProvider).getLinkedBundle(); for (int i = 0; i < bundle.unlinkedUnitUris.length; i++) { String uri = bundle.unlinkedUnitUris[i]; uriToUnlinkedUnit[uri] = bundle.unlinkedUnits[i]; @@ -327,7 +331,9 @@ /// Serialize the given library [text], then deserialize it and store its /// summary in [lib]. - void serializeLibraryText(String text, {bool allowErrors: false}); + void serializeLibraryText(String text, + {bool allowErrors: false, + bool enableSetLiterals: enableSetLiteralsDefault}); } /// Implementation of [SummaryBlackBoxTestStrategy] that drives summary @@ -339,8 +345,11 @@ bool get skipFullyLinkedData => true; @override - void serializeLibraryText(String text, {bool allowErrors: false}) { - super.serializeLibraryText(text, allowErrors: allowErrors); + void serializeLibraryText(String text, + {bool allowErrors: false, + bool enableSetLiterals: enableSetLiteralsDefault}) { + super.serializeLibraryText(text, + allowErrors: allowErrors, enableSetLiterals: enableSetLiterals); UnlinkedUnit getPart(String absoluteUri) { return _linkerInputs.getUnit(absoluteUri); @@ -531,15 +540,20 @@ return assembler.assemble(); } - UnlinkedUnitBuilder createUnlinkedSummary(Uri uri, String text) => - serializeAstUnlinked(_parseText(text)); + UnlinkedUnitBuilder createUnlinkedSummary(Uri uri, String text, + {bool enableSetLiterals: enableSetLiteralsDefault}) => + serializeAstUnlinked( + _parseText(text, enableSetLiterals: enableSetLiterals)); _LinkerInputs _createLinkerInputs(String text, - {String path: '/test.dart', String uri}) { + {String path: '/test.dart', + String uri, + bool enableSetLiterals: enableSetLiteralsDefault}) { uri ??= absUri(path); Uri testDartUri = Uri.parse(uri); - UnlinkedUnitBuilder unlinkedDefiningUnit = - createUnlinkedSummary(testDartUri, text); + UnlinkedUnitBuilder unlinkedDefiningUnit = createUnlinkedSummary( + testDartUri, text, + enableSetLiterals: enableSetLiterals); _filesToLink.uriToUnit[testDartUri.toString()] = unlinkedDefiningUnit; _LinkerInputs linkerInputs = new _LinkerInputs( _allowMissingFiles, @@ -580,9 +594,12 @@ bool get containsNonConstExprs => true; @override - void serializeLibraryText(String text, {bool allowErrors: false}) { + void serializeLibraryText(String text, + {bool allowErrors: false, + bool enableSetLiterals: enableSetLiteralsDefault}) { Map<String, UnlinkedUnitBuilder> uriToUnit = this._filesToLink.uriToUnit; - _linkerInputs = _createLinkerInputs(text); + _linkerInputs = + _createLinkerInputs(text, enableSetLiterals: enableSetLiterals); linked = link( _linkerInputs.linkedLibraries, _linkerInputs.getDependency,
diff --git a/pkg/analyzer/test/src/summary/top_level_inference_test.dart b/pkg/analyzer/test/src/summary/top_level_inference_test.dart index bf6a1bc..ace76cd 100644 --- a/pkg/analyzer/test/src/summary/top_level_inference_test.dart +++ b/pkg/analyzer/test/src/summary/top_level_inference_test.dart
@@ -4,8 +4,8 @@ import 'dart:async'; +import 'package:analyzer/dart/analysis/results.dart'; import 'package:analyzer/dart/element/element.dart'; -import 'package:analyzer/src/dart/analysis/driver.dart'; import 'package:test_reflective_loader/test_reflective_loader.dart'; import '../dart/analysis/base.dart'; @@ -366,10 +366,6 @@ @reflectiveTest class TopLevelInferenceTest extends BaseAnalysisDriverTest { - void addFile(String path, String code) { - provider.newFile(_p(path), code); - } - test_initializer_additive() async { var library = await _encodeDecodeLibrary(r''' var vPlusIntInt = 1 + 2; @@ -682,11 +678,11 @@ } test_initializer_extractProperty_inOtherLibraryCycle() async { - addFile('/a.dart', r''' + newFile('/a.dart', content: r''' import 'b.dart'; var x = new C().f; '''); - addFile('/b.dart', r''' + newFile('/b.dart', content: r''' class C { var f = 0; } @@ -2532,8 +2528,7 @@ } test_method_OK_single_private_linkThroughOtherLibraryOfCycle() async { - String path = _p('/other.dart'); - provider.newFile(path, r''' + newFile('/other.dart', content: r''' import 'test.dart'; class B extends A2 {} '''); @@ -2628,11 +2623,9 @@ } Future<LibraryElement> _encodeDecodeLibrary(String text) async { - String path = _p('/test.dart'); - provider.newFile(path, text); + String path = convertPath('/test.dart'); + newFile(path, content: text); UnitElementResult result = await driver.getUnitElement(path); return result.element.library; } - - String _p(String path) => provider.convertPath(path); }
diff --git a/pkg/analyzer/test/src/task/dart_test.dart b/pkg/analyzer/test/src/task/dart_test.dart index a2a0da0..22b79c4 100644 --- a/pkg/analyzer/test/src/task/dart_test.dart +++ b/pkg/analyzer/test/src/task/dart_test.dart
@@ -3158,9 +3158,7 @@ void _performParseTask(String content) { if (content == null) { - source = resourceProvider - .getFile(resourceProvider.convertPath('/test.dart')) - .createSource(); + source = getFile('/test.dart').createSource(); } else { source = newSource('/test.dart', content); }
diff --git a/pkg/analyzer/test/src/task/options_test.dart b/pkg/analyzer/test/src/task/options_test.dart index befc23b..645c950 100644 --- a/pkg/analyzer/test/src/task/options_test.dart +++ b/pkg/analyzer/test/src/task/options_test.dart
@@ -1,14 +1,17 @@ -// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file +// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. import 'dart:mirrors'; -import 'package:analyzer/analyzer.dart'; +import 'package:analyzer/error/error.dart'; import 'package:analyzer/file_system/file_system.dart'; import 'package:analyzer/file_system/memory_file_system.dart'; import 'package:analyzer/source/error_processor.dart'; import 'package:analyzer/src/analysis_options/analysis_options_provider.dart'; +import 'package:analyzer/src/analysis_options/error/option_codes.dart'; +import 'package:analyzer/src/dart/error/hint_codes.dart'; +import 'package:analyzer/src/error/codes.dart'; import 'package:analyzer/src/file_system/file_system.dart'; import 'package:analyzer/src/generated/engine.dart'; import 'package:analyzer/src/generated/source.dart'; @@ -193,6 +196,7 @@ removeCode(StrongModeCode.INVALID_CAST_LITERAL); removeCode(StrongModeCode.INVALID_CAST_LITERAL_LIST); removeCode(StrongModeCode.INVALID_CAST_LITERAL_MAP); + removeCode(StrongModeCode.INVALID_CAST_LITERAL_SET); removeCode(StrongModeCode.INVALID_CAST_FUNCTION_EXPR); removeCode(StrongModeCode.INVALID_CAST_NEW_EXPR); removeCode(StrongModeCode.INVALID_CAST_METHOD); @@ -486,6 +490,22 @@ new OptionsFileValidator(new TestSource()); final AnalysisOptionsProvider optionsProvider = new AnalysisOptionsProvider(); + test_analyzer_enableExperiment_badValue() { + validate(''' +analyzer: + enable-experiment: + - not-an-experiment + ''', [AnalysisOptionsWarningCode.UNSUPPORTED_OPTION_WITHOUT_VALUES]); + } + + test_analyzer_enableExperiment_notAList() { + validate(''' +analyzer: + enable-experiment: + experiment: true + ''', [AnalysisOptionsWarningCode.INVALID_SECTION_FORMAT]); + } + test_analyzer_error_code_supported() { validate(''' analyzer:
diff --git a/pkg/analyzer/test/src/task/strong/checker_test.dart b/pkg/analyzer/test/src/task/strong/checker_test.dart index 5e74843..4194a0a 100644 --- a/pkg/analyzer/test/src/task/strong/checker_test.dart +++ b/pkg/analyzer/test/src/task/strong/checker_test.dart
@@ -2134,73 +2134,49 @@ addFile( 'num n; int i; void main() { i = /*info:DOWN_CAST_IMPLICIT*/n;}//yy'); await check(); + addFile( 'num n; int i; void main() { i = /*error:INVALID_ASSIGNMENT*/n;}//ny'); - await check(implicitCasts: false, declarationCasts: true); - addFile( - 'num n; int i; void main() { i = /*info:DOWN_CAST_IMPLICIT*/n;}//yn'); - await check(implicitCasts: true, declarationCasts: false); - addFile( - 'num n; int i; void main() { i = /*error:INVALID_ASSIGNMENT*/n;}//nn'); - await check(implicitCasts: false, declarationCasts: false); + await check(implicitCasts: false); } test_implicitCasts_compoundAssignment() async { addFile('''f(num n, int i) { /*info:DOWN_CAST_IMPLICIT_ASSIGN*/i += n;}//yy'''); await check(); + addFile('''f(num n, int i) { i += /*error:INVALID_ASSIGNMENT*/n;}//ny'''); - await check(implicitCasts: false, declarationCasts: true); - addFile('''f(num n, int i) { - /*info:DOWN_CAST_IMPLICIT_ASSIGN*/i += n;}//yn'''); - await check(implicitCasts: true, declarationCasts: false); - addFile('''f(num n, int i) { - i += /*error:INVALID_ASSIGNMENT*/n;}//nn'''); - await check(implicitCasts: false, declarationCasts: false); + await check(implicitCasts: false); } test_implicitCasts_constructorInitializer() async { addFile( 'class A { int i; A(num n) : i = /*info:DOWN_CAST_IMPLICIT*/n;}//yy'); await check(); + addFile( 'class A { int i; A(num n) : i = /*error:FIELD_INITIALIZER_NOT_ASSIGNABLE*/n;}//ny'); - await check(implicitCasts: false, declarationCasts: true); - addFile( - 'class A { int i; A(num n) : i = /*info:DOWN_CAST_IMPLICIT*/n;}//yn'); - await check(implicitCasts: true, declarationCasts: false); - addFile( - 'class A { int i; A(num n) : i = /*error:FIELD_INITIALIZER_NOT_ASSIGNABLE*/n;}//nn'); - await check(implicitCasts: false, declarationCasts: false); + await check(implicitCasts: false); } test_implicitCasts_defaultValue() async { addFile('''const num n = 0; f({int i = /*info:DOWN_CAST_IMPLICIT*/n}) => i;//yy'''); await check(); + addFile('''const num n = 0; f({int i = /*error:INVALID_ASSIGNMENT*/n}) => i;//ny'''); - await check(implicitCasts: false, declarationCasts: true); - addFile('''const num n = 0; - f({int i = /*info:DOWN_CAST_IMPLICIT*/n}) => i;//yn'''); - await check(implicitCasts: true, declarationCasts: false); - addFile('''const num n = 0; - f({int i = /*error:INVALID_ASSIGNMENT*/n}) => i;//nn'''); - await check(implicitCasts: false, declarationCasts: false); + await check(implicitCasts: false); } test_implicitCasts_fieldInitializer() async { addFile('class A { static num n; int i = /*info:ASSIGNMENT_CAST*/n;}//yy'); await check(); - addFile('class A { static num n; int i = /*info:ASSIGNMENT_CAST*/n;}//ny'); - await check(implicitCasts: false, declarationCasts: true); - addFile( - 'class A { static num n; int i = /*error:INVALID_ASSIGNMENT*/n;}//yn'); - await check(implicitCasts: true, declarationCasts: false); + addFile( 'class A { static num n; int i = /*error:INVALID_ASSIGNMENT*/n;}//nn'); - await check(implicitCasts: false, declarationCasts: false); + await check(implicitCasts: false); } test_implicitCasts_functionCall() async { @@ -2208,18 +2184,11 @@ f(int i) => i; var i = f(/*info:DOWN_CAST_IMPLICIT*/n);//yy'''); await check(); - addFile('''num n; - f(int i) => i; - var i = f(/*error:ARGUMENT_TYPE_NOT_ASSIGNABLE*/n);//ny'''); - await check(implicitCasts: false, declarationCasts: true); - addFile('''num n; - f(int i) => i; - var i = f(/*info:DOWN_CAST_IMPLICIT*/n);//yn'''); - await check(implicitCasts: true, declarationCasts: false); + addFile('''num n; f(int i) => i; var i = f(/*error:ARGUMENT_TYPE_NOT_ASSIGNABLE*/n);//nn'''); - await check(implicitCasts: false, declarationCasts: false); + await check(implicitCasts: false); } test_implicitCasts_genericMethods() async { @@ -2232,12 +2201,9 @@ test_implicitCasts_initializer() async { addFile('num n; int i = /*info:ASSIGNMENT_CAST*/n;//yy'); await check(); - addFile('num n; int i = /*info:ASSIGNMENT_CAST*/n;//ny'); - await check(implicitCasts: false, declarationCasts: true); - addFile('num n; int i = /*error:INVALID_ASSIGNMENT*/n;//yn'); - await check(implicitCasts: true, declarationCasts: false); + addFile('num n; int i = /*error:INVALID_ASSIGNMENT*/n;//nn'); - await check(implicitCasts: false, declarationCasts: false); + await check(implicitCasts: false); } test_implicitCasts_numericOps() async { @@ -2257,29 +2223,19 @@ int i; var r = i & /*info:DOWN_CAST_IMPLICIT*/n;//yy'''); await check(); - addFile('''num n; - int i; - var r = i & /*error:ARGUMENT_TYPE_NOT_ASSIGNABLE*/n;//ny'''); - await check(implicitCasts: false, declarationCasts: true); - addFile('''num n; - int i; - var r = i & /*info:DOWN_CAST_IMPLICIT*/n;//yn'''); - await check(implicitCasts: true, declarationCasts: false); + addFile('''num n; int i; var r = i & /*error:ARGUMENT_TYPE_NOT_ASSIGNABLE*/n;//nn'''); - await check(implicitCasts: false, declarationCasts: false); + await check(implicitCasts: false); } test_implicitCasts_return() async { addFile('int f(num n) => /*info:DOWN_CAST_IMPLICIT*/n;//yy'); await check(); - addFile('int f(num n) => /*error:RETURN_OF_INVALID_TYPE*/n;//ny'); - await check(implicitCasts: false, declarationCasts: true); - addFile('int f(num n) => /*info:DOWN_CAST_IMPLICIT*/n;//yn'); - await check(implicitCasts: true, declarationCasts: false); + addFile('int f(num n) => /*error:RETURN_OF_INVALID_TYPE*/n;//nn'); - await check(implicitCasts: false, declarationCasts: false); + await check(implicitCasts: false); } test_implicitCasts_return_async() async {
diff --git a/pkg/analyzer/test/src/task/strong/inferred_type_test.dart b/pkg/analyzer/test/src/task/strong/inferred_type_test.dart index ccef7a7..2991634 100644 --- a/pkg/analyzer/test/src/task/strong/inferred_type_test.dart +++ b/pkg/analyzer/test/src/task/strong/inferred_type_test.dart
@@ -20,7 +20,7 @@ }); } -abstract class InferredTypeMixin { +mixin InferredTypeMixin { /// Extra top-level errors if needed due to being analyze multiple times. bool get hasExtraTaskModelPass => true; @@ -39,9 +39,7 @@ * unit. */ Future<CompilationUnit> checkFile(String content, - {bool declarationCasts: true, - bool implicitCasts: true, - bool implicitDynamic: true}); + {bool implicitCasts: true, bool implicitDynamic: true}); /** * Add the file, process it (resolve, validate, etc) and return the resolved @@ -1506,7 +1504,7 @@ Iterable<Map<int, int>> bar() sync* { yield /*info:INFERRED_TYPE_LITERAL*/{}; yield /*error:YIELD_OF_INVALID_TYPE*/new List(); - yield* /*error:YIELD_OF_INVALID_TYPE*/{}; + yield* {}; yield* /*info:INFERRED_TYPE_ALLOCATION*/new List(); } '''); @@ -4484,22 +4482,8 @@ @failingTest @override - test_unsafeBlockClosureInference_functionCall_explicitDynamicParam_viaExpr2() async { - await super - .test_unsafeBlockClosureInference_functionCall_explicitDynamicParam_viaExpr2(); - } - - @failingTest - @override test_unsafeBlockClosureInference_functionCall_explicitTypeParam_viaExpr1() { return super .test_unsafeBlockClosureInference_functionCall_explicitTypeParam_viaExpr1(); } - - @failingTest - @override - test_unsafeBlockClosureInference_functionCall_explicitTypeParam_viaExpr2() async { - await super - .test_unsafeBlockClosureInference_functionCall_explicitTypeParam_viaExpr2(); - } }
diff --git a/pkg/analyzer/test/src/task/strong/strong_test_helper.dart b/pkg/analyzer/test/src/task/strong/strong_test_helper.dart index d9e4081..c9c3fcf 100644 --- a/pkg/analyzer/test/src/task/strong/strong_test_helper.dart +++ b/pkg/analyzer/test/src/task/strong/strong_test_helper.dart
@@ -25,11 +25,11 @@ import 'package:analyzer/src/file_system/file_system.dart'; import 'package:analyzer/src/generated/engine.dart'; import 'package:analyzer/src/generated/source.dart'; +import 'package:analyzer/src/test_utilities/mock_sdk.dart'; +import 'package:analyzer/src/test_utilities/resource_provider_mixin.dart'; import 'package:source_span/source_span.dart'; import 'package:test/test.dart'; -import '../../context/mock_sdk.dart'; - SourceSpanWithContext _createSpanHelper( LineInfo lineInfo, int start, Source source, String content, {int end}) { @@ -237,8 +237,7 @@ fail('Checker errors do not match expected errors:\n\n$message'); } -class AbstractStrongTest { - MemoryResourceProvider _resourceProvider = new MemoryResourceProvider(); +class AbstractStrongTest with ResourceProviderMixin { bool _checkCalled = false; AnalysisContext _context = null; @@ -266,7 +265,7 @@ /// For a single file, you may also use [checkFile]. void addFile(String content, {String name: '/main.dart'}) { name = name.replaceFirst('^package:', '/packages/'); - _resourceProvider.newFile(_resourceProvider.convertPath(name), content); + newFile(name, content: content); } /// Run the checker on a program, staring from '/main.dart', and verifies that @@ -277,27 +276,23 @@ /// /// Returns the main resolved library. This can be used for further checks. Future<CompilationUnit> check( - {bool declarationCasts: true, - bool implicitCasts: true, - bool implicitDynamic: true}) async { + {bool implicitCasts: true, bool implicitDynamic: true}) async { _checkCalled = true; - File mainFile = - _resourceProvider.getFile(_resourceProvider.convertPath('/main.dart')); + File mainFile = getFile('/main.dart'); expect(mainFile.exists, true, reason: '`/main.dart` is missing'); AnalysisOptionsImpl analysisOptions = new AnalysisOptionsImpl(); analysisOptions.strongModeHints = true; - analysisOptions.declarationCasts = declarationCasts; analysisOptions.implicitCasts = implicitCasts; analysisOptions.implicitDynamic = implicitDynamic; - var mockSdk = new MockSdk(resourceProvider: _resourceProvider); + var mockSdk = new MockSdk(resourceProvider: resourceProvider); mockSdk.context.analysisOptions = analysisOptions; SourceFactory sourceFactory; { - var uriResolver = new _TestUriResolver(_resourceProvider); + var uriResolver = new _TestUriResolver(resourceProvider); sourceFactory = new SourceFactory([new DartUriResolver(mockSdk), uriResolver]); } @@ -311,7 +306,7 @@ _driver = new AnalysisDriver( scheduler, log, - _resourceProvider, + resourceProvider, new MemoryByteStore(), fileContentOverlay, null, @@ -367,14 +362,12 @@ /// /// Also returns the resolved compilation unit. Future<CompilationUnit> checkFile(String content, - {bool declarationCasts: true, - bool implicitCasts: true, - bool implicitDynamic: true}) async { + {bool implicitCasts: true, bool implicitDynamic: true}) async { addFile(content); return await check( - declarationCasts: declarationCasts, - implicitCasts: implicitCasts, - implicitDynamic: implicitDynamic); + implicitCasts: implicitCasts, + implicitDynamic: implicitDynamic, + ); } void setUp() {
diff --git a/pkg/analyzer/test/src/task/yaml_test.dart b/pkg/analyzer/test/src/task/yaml_test.dart index d952887..4342087 100644 --- a/pkg/analyzer/test/src/task/yaml_test.dart +++ b/pkg/analyzer/test/src/task/yaml_test.dart
@@ -58,9 +58,9 @@ } void _performParseTask(String content) { - var path = resourceProvider.convertPath('/test.yaml'); + var path = '/test.yaml'; if (content == null) { - source = resourceProvider.getFile(path).createSource(); + source = getFile(path).createSource(); } else { source = newSource(path, content); }
diff --git a/pkg/analyzer/test/src/test_all.dart b/pkg/analyzer/test/src/test_all.dart index 369c7b9..20bdbbb 100644 --- a/pkg/analyzer/test/src/test_all.dart +++ b/pkg/analyzer/test/src/test_all.dart
@@ -9,6 +9,7 @@ import 'dart/test_all.dart' as dart; import 'fasta/test_all.dart' as fasta; import 'lint/test_all.dart' as lint; +import 'options/test_all.dart' as options; import 'pubspec/test_all.dart' as pubspec; import 'source/test_all.dart' as source; import 'summary/test_all.dart' as summary; @@ -23,6 +24,7 @@ dart.main(); fasta.main(); lint.main(); + options.main(); pubspec.main(); source.main(); summary.main();
diff --git a/pkg/analyzer/test/generated/bazel_test.dart b/pkg/analyzer/test/src/workspace/bazel_test.dart similarity index 98% rename from pkg/analyzer/test/generated/bazel_test.dart rename to pkg/analyzer/test/src/workspace/bazel_test.dart index e339b74..2fff988 100644 --- a/pkg/analyzer/test/generated/bazel_test.dart +++ b/pkg/analyzer/test/src/workspace/bazel_test.dart
@@ -1,10 +1,10 @@ -// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file +// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. -import 'package:analyzer/src/generated/bazel.dart'; import 'package:analyzer/src/generated/source.dart'; import 'package:analyzer/src/test_utilities/resource_provider_mixin.dart'; +import 'package:analyzer/src/workspace/bazel.dart'; import 'package:test/test.dart'; import 'package:test_reflective_loader/test_reflective_loader.dart'; @@ -17,7 +17,7 @@ } @reflectiveTest -class BazelFileUriResolverTest extends Object with ResourceProviderMixin { +class BazelFileUriResolverTest with ResourceProviderMixin { BazelWorkspace workspace; BazelFileUriResolver resolver; @@ -97,7 +97,7 @@ } @reflectiveTest -class BazelPackageUriResolverTest extends Object with ResourceProviderMixin { +class BazelPackageUriResolverTest with ResourceProviderMixin { BazelWorkspace workspace; BazelPackageUriResolver resolver; @@ -482,12 +482,12 @@ } @reflectiveTest -class BazelWorkspaceTest extends Object with ResourceProviderMixin { +class BazelWorkspaceTest with ResourceProviderMixin { void test_find_fail_notAbsolute() { expect( () => BazelWorkspace.find(resourceProvider, convertPath('not_absolute')), - throwsArgumentError); + throwsA(const TypeMatcher<AssertionError>())); } void test_find_hasReadonlyFolder() {
diff --git a/pkg/analyzer/test/generated/gn_test.dart b/pkg/analyzer/test/src/workspace/gn_test.dart similarity index 96% rename from pkg/analyzer/test/generated/gn_test.dart rename to pkg/analyzer/test/src/workspace/gn_test.dart index 46ff4ea..99e3c00 100644 --- a/pkg/analyzer/test/generated/gn_test.dart +++ b/pkg/analyzer/test/src/workspace/gn_test.dart
@@ -1,9 +1,9 @@ -// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file +// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. -import 'package:analyzer/src/generated/gn.dart'; import 'package:analyzer/src/test_utilities/resource_provider_mixin.dart'; +import 'package:analyzer/src/workspace/gn.dart'; import 'package:test/test.dart'; import 'package:test_reflective_loader/test_reflective_loader.dart'; @@ -14,7 +14,7 @@ } @reflectiveTest -class GnWorkspaceTest extends Object with ResourceProviderMixin { +class GnWorkspaceTest with ResourceProviderMixin { void test_find_noJiriRoot() { newFolder('/workspace'); GnWorkspace workspace = @@ -33,7 +33,7 @@ void test_find_notAbsolute() { expect( () => GnWorkspace.find(resourceProvider, convertPath('not_absolute')), - throwsArgumentError); + throwsA(const TypeMatcher<AssertionError>())); } void test_find_withRoot() {
diff --git a/pkg/analyzer/test/generated/package_build_test.dart b/pkg/analyzer/test/src/workspace/package_build_test.dart similarity index 96% rename from pkg/analyzer/test/generated/package_build_test.dart rename to pkg/analyzer/test/src/workspace/package_build_test.dart index 81b7d35..9f7d917 100644 --- a/pkg/analyzer/test/generated/package_build_test.dart +++ b/pkg/analyzer/test/src/workspace/package_build_test.dart
@@ -1,12 +1,12 @@ -// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. import 'package:analyzer/file_system/file_system.dart'; import 'package:analyzer/src/context/builder.dart'; -import 'package:analyzer/src/generated/package_build.dart'; import 'package:analyzer/src/generated/source.dart'; import 'package:analyzer/src/test_utilities/resource_provider_mixin.dart'; +import 'package:analyzer/src/workspace/package_build.dart'; import 'package:package_config/packages.dart'; import 'package:test/test.dart'; import 'package:test_reflective_loader/test_reflective_loader.dart'; @@ -46,8 +46,7 @@ } @reflectiveTest -class PackageBuildFileUriResolverTest extends Object - with ResourceProviderMixin { +class PackageBuildFileUriResolverTest with ResourceProviderMixin { PackageBuildWorkspace workspace; PackageBuildFileUriResolver resolver; @@ -116,16 +115,14 @@ uri); } - Source _resolvePath(String absolutePosixPath) { - String absolutePath = resourceProvider.convertPath(absolutePosixPath); - Uri uri = resourceProvider.pathContext.toUri(absolutePath); + Source _resolvePath(String path) { + Uri uri = toUri(path); return resolver.resolveAbsolute(uri); } } @reflectiveTest -class PackageBuildPackageUriResolverTest extends Object - with ResourceProviderMixin { +class PackageBuildPackageUriResolverTest with ResourceProviderMixin { PackageBuildWorkspace workspace; PackageBuildPackageUriResolver resolver; MockUriResolver packageUriResolver; @@ -230,7 +227,7 @@ } @reflectiveTest -class PackageBuildWorkspaceTest extends Object with ResourceProviderMixin { +class PackageBuildWorkspaceTest with ResourceProviderMixin { void test_builtFile_currentProject() { newFolder('/workspace/.dart_tool/build'); newFileWithBytes('/workspace/pubspec.yaml', 'name: project'.codeUnits); @@ -273,7 +270,7 @@ expect( () => PackageBuildWorkspace.find(resourceProvider, convertPath('not_absolute'), new MockContextBuilder()), - throwsArgumentError); + throwsA(const TypeMatcher<AssertionError>())); } void test_find_hasDartToolAndPubspec() {
diff --git a/pkg/analyzer/test/src/workspace/test_all.dart b/pkg/analyzer/test/src/workspace/test_all.dart new file mode 100644 index 0000000..351175b --- /dev/null +++ b/pkg/analyzer/test/src/workspace/test_all.dart
@@ -0,0 +1,17 @@ +// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:test_reflective_loader/test_reflective_loader.dart'; + +import 'bazel_test.dart' as bazel_test; +import 'gn_test.dart' as gn_test; +import 'package_build_test.dart' as package_build_test; + +main() { + defineReflectiveSuite(() { + bazel_test.main(); + gn_test.main(); + package_build_test.main(); + }, name: 'workspace'); +}
diff --git a/pkg/analyzer/tool/task_dependency_graph/generate.dart b/pkg/analyzer/tool/task_dependency_graph/generate.dart index 739ac6c..3a9aa7b 100644 --- a/pkg/analyzer/tool/task_dependency_graph/generate.dart +++ b/pkg/analyzer/tool/task_dependency_graph/generate.dart
@@ -1,4 +1,4 @@ -// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file +// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. @@ -19,13 +19,18 @@ import 'dart:io' hide File; import 'dart:io' as io; -import 'package:analyzer/analyzer.dart'; +import 'package:analyzer/dart/analysis/results.dart'; +import 'package:analyzer/dart/ast/ast.dart'; +import 'package:analyzer/dart/ast/visitor.dart'; import 'package:analyzer/dart/element/element.dart'; import 'package:analyzer/dart/element/type.dart'; import 'package:analyzer/file_system/physical_file_system.dart'; +import 'package:analyzer/src/codegen/tools.dart'; import 'package:analyzer/src/context/builder.dart'; +import 'package:analyzer/src/dart/analysis/byte_store.dart'; import 'package:analyzer/src/dart/analysis/driver.dart'; import 'package:analyzer/src/dart/analysis/file_state.dart'; +import 'package:analyzer/src/dart/analysis/performance_logger.dart'; import 'package:analyzer/src/dart/sdk/sdk.dart'; import 'package:analyzer/src/file_system/file_system.dart'; import 'package:analyzer/src/generated/constant.dart'; @@ -35,9 +40,6 @@ import 'package:analyzer/src/generated/source.dart'; import 'package:analyzer/src/generated/source_io.dart'; import 'package:analyzer/src/source/package_map_resolver.dart'; -import 'package:analyzer/src/dart/analysis/byte_store.dart'; -import 'package:analyzer/src/dart/analysis/performance_logger.dart'; -import 'package:analyzer/src/codegen/tools.dart'; import 'package:front_end/src/testing/package_root.dart' as package_root; import 'package:path/path.dart' as path; import 'package:path/path.dart';
diff --git a/pkg/analyzer_cli/lib/src/analyzer_impl.dart b/pkg/analyzer_cli/lib/src/analyzer_impl.dart index 1974fc4..e36008f 100644 --- a/pkg/analyzer_cli/lib/src/analyzer_impl.dart +++ b/pkg/analyzer_cli/lib/src/analyzer_impl.dart
@@ -7,6 +7,7 @@ import 'dart:async'; import 'dart:io'; +import 'package:analyzer/dart/analysis/results.dart'; import 'package:analyzer/dart/element/element.dart'; import 'package:analyzer/error/error.dart'; import 'package:analyzer/exception/exception.dart';
diff --git a/pkg/analyzer_cli/lib/src/build_mode.dart b/pkg/analyzer_cli/lib/src/build_mode.dart index 206341a..5228897 100644 --- a/pkg/analyzer_cli/lib/src/build_mode.dart +++ b/pkg/analyzer_cli/lib/src/build_mode.dart
@@ -1,4 +1,4 @@ -// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file +// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. @@ -9,10 +9,14 @@ import 'dart:isolate'; import 'package:analyzer/dart/analysis/declared_variables.dart'; +import 'package:analyzer/dart/analysis/results.dart'; import 'package:analyzer/error/error.dart'; import 'package:analyzer/file_system/file_system.dart'; +import 'package:analyzer/src/dart/analysis/byte_store.dart'; +import 'package:analyzer/src/dart/analysis/cache.dart'; import 'package:analyzer/src/dart/analysis/driver.dart'; import 'package:analyzer/src/dart/analysis/file_state.dart'; +import 'package:analyzer/src/dart/analysis/performance_logger.dart'; import 'package:analyzer/src/dart/sdk/sdk.dart'; import 'package:analyzer/src/generated/engine.dart'; import 'package:analyzer/src/generated/sdk.dart'; @@ -35,9 +39,6 @@ import 'package:bazel_worker/bazel_worker.dart'; import 'package:collection/collection.dart'; import 'package:convert/convert.dart'; -import 'package:analyzer/src/dart/analysis/byte_store.dart'; -import 'package:analyzer/src/dart/analysis/performance_logger.dart'; -import 'package:analyzer/src/dart/analysis/cache.dart'; /** * Persistent Bazel worker. @@ -58,14 +59,6 @@ resourceProvider, logger, 256 * 1024 * 1024); } - factory AnalyzerWorkerLoop.std(ResourceProvider resourceProvider, - {io.Stdin stdinStream, io.Stdout stdoutStream, String dartSdkPath}) { - AsyncWorkerConnection connection = new StdAsyncWorkerConnection( - inputStream: stdinStream, outputStream: stdoutStream); - return new AnalyzerWorkerLoop(resourceProvider, connection, - dartSdkPath: dartSdkPath); - } - factory AnalyzerWorkerLoop.sendPort( ResourceProvider resourceProvider, SendPort sendPort, {String dartSdkPath}) { @@ -75,6 +68,14 @@ dartSdkPath: dartSdkPath); } + factory AnalyzerWorkerLoop.std(ResourceProvider resourceProvider, + {io.Stdin stdinStream, io.Stdout stdoutStream, String dartSdkPath}) { + AsyncWorkerConnection connection = new StdAsyncWorkerConnection( + inputStream: stdinStream, outputStream: stdoutStream); + return new AnalyzerWorkerLoop(resourceProvider, connection, + dartSdkPath: dartSdkPath); + } + /** * Performs analysis with given [options]. */ @@ -174,7 +175,7 @@ /** * Analyzer used when the "--build-mode" option is supplied. */ -class BuildMode extends Object with HasContextMixin { +class BuildMode with HasContextMixin { final ResourceProvider resourceProvider; final CommandLineOptions options; final AnalysisStats stats;
diff --git a/pkg/analyzer_cli/lib/src/context_cache.dart b/pkg/analyzer_cli/lib/src/context_cache.dart index 0e875ce..3c2abe1 100644 --- a/pkg/analyzer_cli/lib/src/context_cache.dart +++ b/pkg/analyzer_cli/lib/src/context_cache.dart
@@ -1,4 +1,4 @@ -// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. @@ -87,15 +87,16 @@ /// automatically. AnalysisOptionsImpl _getAnalysisOptions() { AnalysisOptionsImpl contextOptions = builder.getAnalysisOptions( - requestedSourceDirectory, - verbosePrint: clOptions.verbose ? verbosePrint : null); + requestedSourceDirectory, + verbosePrint: clOptions.verbose ? verbosePrint : null) + as AnalysisOptionsImpl; contextOptions.trackCacheDependencies = false; contextOptions.disableCacheFlushing = clOptions.disableCacheFlushing; + contextOptions.enabledExperiments = clOptions.enabledExperiments; contextOptions.hint = !clOptions.disableHints; contextOptions.generateImplicitErrors = clOptions.showPackageWarnings; contextOptions.generateSdkErrors = clOptions.showSdkWarnings; - contextOptions.previewDart2 = clOptions.previewDart2; contextOptions.useFastaParser = clOptions.useFastaParser; return contextOptions; }
diff --git a/pkg/analyzer_cli/lib/src/driver.dart b/pkg/analyzer_cli/lib/src/driver.dart index 63ed79f..b5715bd 100644 --- a/pkg/analyzer_cli/lib/src/driver.dart +++ b/pkg/analyzer_cli/lib/src/driver.dart
@@ -1,4 +1,4 @@ -// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file +// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. @@ -93,7 +93,7 @@ _analytics = replacementAnalytics; } -class Driver extends Object with HasContextMixin implements CommandLineStarter { +class Driver with HasContextMixin implements CommandLineStarter { static final PerformanceTag _analyzeAllTag = new PerformanceTag("Driver._analyzeAll"); @@ -479,7 +479,7 @@ AnalysisOptions analysisOptions) { // Create a custom package resolver if one has been specified. if (packageResolverProvider != null) { - file_system.Folder folder = resourceProvider.getResource('.'); + file_system.Folder folder = resourceProvider.getFolder('.'); UriResolver resolver = packageResolverProvider(folder); if (resolver != null) { // TODO(brianwilkerson) This doesn't handle sdk extensions.
diff --git a/pkg/analyzer_cli/lib/src/error_formatter.dart b/pkg/analyzer_cli/lib/src/error_formatter.dart index 0c84618..e5ca66b 100644 --- a/pkg/analyzer_cli/lib/src/error_formatter.dart +++ b/pkg/analyzer_cli/lib/src/error_formatter.dart
@@ -262,7 +262,7 @@ void formatError( Map<AnalysisError, LineInfo> errorToLine, AnalysisError error) { Source source = error.source; - CharacterLocation location = errorToLine[error].getLocation(error.offset); + var location = errorToLine[error].getLocation(error.offset); ErrorSeverity severity = _severityProcessor(error); @@ -323,7 +323,7 @@ void formatError( Map<AnalysisError, LineInfo> errorToLine, AnalysisError error) { Source source = error.source; - CharacterLocation location = errorToLine[error].getLocation(error.offset); + var location = errorToLine[error].getLocation(error.offset); int length = error.length; ErrorSeverity severity = _severityProcessor(error);
diff --git a/pkg/analyzer_cli/lib/src/options.dart b/pkg/analyzer_cli/lib/src/options.dart index 640fd1a..6b4215b 100644 --- a/pkg/analyzer_cli/lib/src/options.dart +++ b/pkg/analyzer_cli/lib/src/options.dart
@@ -1,4 +1,4 @@ -// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file +// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. @@ -7,6 +7,7 @@ import 'package:analyzer/file_system/physical_file_system.dart'; import 'package:analyzer/src/command_line/arguments.dart'; import 'package:analyzer/src/context/builder.dart'; +import 'package:analyzer/src/dart/analysis/experiments.dart'; import 'package:analyzer/src/util/sdk.dart'; import 'package:analyzer_cli/src/ansi.dart' as ansi; import 'package:analyzer_cli/src/driver.dart'; @@ -35,9 +36,6 @@ /// Analyzer commandline configuration options. class CommandLineOptions { - /// Whether declaration casts are enabled (in strong mode) - final bool declarationCasts; - /// The path to output analysis results when in build mode. final String buildAnalysisOutput; @@ -93,6 +91,9 @@ /// Whether to display version information final bool displayVersion; + /// A list of the names of the experiments that are to be enabled. + final List<String> enabledExperiments; + /// Whether to ignore unrecognized flags final bool ignoreUnrecognizedFlags; @@ -176,12 +177,11 @@ contextBuilderOptions = createContextBuilderOptions(args), dartSdkPath = cast(args['dart-sdk']), dartSdkSummaryPath = cast(args['dart-sdk-summary']), - declarationCasts = args.wasParsed(declarationCastsFlag) - ? cast(args[declarationCastsFlag]) - : cast(args[implicitCastsFlag]), disableCacheFlushing = cast(args['disable-cache-flushing']), disableHints = cast(args['no-hints']), displayVersion = cast(args['version']), + enabledExperiments = + cast(args['enable-experiment'] ?? const <String>[]), ignoreUnrecognizedFlags = cast(args['ignore-unrecognized-flags']), lints = cast(args[lintsFlag]), log = cast(args['log']), @@ -219,11 +219,6 @@ String get packageRootPath => contextBuilderOptions.defaultPackagesDirectoryPath; - /// Whether to enable the Dart 2.0 Preview. - /// - /// This flag is deprecated and hard-coded to `true`. - bool get previewDart2 => true; - /// The source files to analyze List<String> get sourceFiles => _sourceFiles; @@ -338,6 +333,11 @@ help: 'Print the analyzer version.', defaultsTo: false, negatable: false) + ..addMultiOption('enable-experiment', + help: + 'Enable one or more experimental features. If multiple features ' + 'are being added, they should be comma separated.', + splitCommas: true) ..addFlag('no-hints', help: 'Do not show hint results.', defaultsTo: false, @@ -592,6 +592,23 @@ 'Note: the --strong flag is deprecated and will be removed in an ' 'future release.\n'); } + if (results.wasParsed('enable-experiment')) { + List<String> names = + (results['enable-experiment'] as List).cast<String>().toList(); + for (String knownName in Experiments.activeExperimentNames) { + names.remove(knownName); + } + if (names.isNotEmpty) { + StringBuffer buffer = new StringBuffer(); + for (String invalidName in names) { + if (buffer.length > 0) { + buffer.write(', '); + } + buffer.write(invalidName); + } + errorSink.writeln('Unknown experiments: $buffer'); + } + } return new CommandLineOptions._fromArgs(results); } on FormatException catch (e) {
diff --git a/pkg/analyzer_cli/test/all.dart b/pkg/analyzer_cli/test/all.dart index b5015f7..a16799b 100644 --- a/pkg/analyzer_cli/test/all.dart +++ b/pkg/analyzer_cli/test/all.dart
@@ -1,4 +1,4 @@ -// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file +// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. @@ -6,7 +6,6 @@ import 'build_mode_test.dart' as build_mode_test; import 'driver_test.dart' as driver_test; import 'embedder_test.dart' as embedder_test; -import 'error_test.dart' as error_test; import 'errors_reported_once_test.dart' as errors_reported_once_test; import 'errors_upgrade_fails_cli_test.dart' as errors_upgrade_fails_cli_test; import 'options_test.dart' as options_test; @@ -21,7 +20,6 @@ build_mode_test.main(); driver_test.main(); embedder_test.main(); - error_test.main(); errors_reported_once_test.main(); errors_upgrade_fails_cli_test.main(); options_test.main();
diff --git a/pkg/analyzer_cli/test/driver_test.dart b/pkg/analyzer_cli/test/driver_test.dart index cb85943..7b205a1 100644 --- a/pkg/analyzer_cli/test/driver_test.dart +++ b/pkg/analyzer_cli/test/driver_test.dart
@@ -1,4 +1,4 @@ -// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file +// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. @@ -952,15 +952,11 @@ } void _expectUndefinedClassErrorsWithoutExclusions() { - bool isStrong = usePreviewDart2 || new AnalysisOptionsImpl().previewDart2; - final String issueType = isStrong ? 'error' : 'warning'; expect(bulletToDash(outSink), - contains("$issueType - Undefined class 'IncludedUndefinedClass'")); - expect( - bulletToDash(outSink), - isNot( - contains("$issueType - Undefined class 'ExcludedUndefinedClass'"))); - expect(outSink.toString(), contains("1 $issueType found.")); + contains("error - Undefined class 'IncludedUndefinedClass'")); + expect(bulletToDash(outSink), + isNot(contains("error - Undefined class 'ExcludedUndefinedClass'"))); + expect(outSink.toString(), contains("1 error found.")); } }
diff --git a/pkg/analyzer_cli/test/error_test.dart b/pkg/analyzer_cli/test/error_test.dart deleted file mode 100644 index c8d1d0f..0000000 --- a/pkg/analyzer_cli/test/error_test.dart +++ /dev/null
@@ -1,55 +0,0 @@ -// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file -// for details. All rights reserved. Use of this source code is governed by a -// BSD-style license that can be found in the LICENSE file. - -library analyzer_cli.test.error; - -import 'package:test/test.dart'; - -import 'utils.dart'; - -const badDeclaration = 'var int foo;'; -const badDeclarationMessage = 'Error in test.dart: ' - 'Variables can\'t be declared using both \'var\' and a type name.\n'; - -void main() { - group('error', () { - test("a valid Dart file doesn't throw any errors", () { - expect(errorsForFile('void main() => print("Hello, world!");'), isNull); - }); - - test("an empty Dart file doesn't throw any errors", () { - expect(errorsForFile(''), isNull); - }); - - test("an error on the first line", () { - expect(errorsForFile('$badDeclaration\n'), equals(badDeclarationMessage)); - }); - - test("an error on the last line", () { - expect(errorsForFile('\n$badDeclaration'), equals(badDeclarationMessage)); - }); - - test("an error in the middle", () { - expect( - errorsForFile('\n$badDeclaration\n'), equals(badDeclarationMessage)); - }); - - var veryLongString = new List.filled(107, ' ').join(''); - - test("an error at the end of a very long line", () { - expect(errorsForFile('$veryLongString $badDeclaration'), - equals(badDeclarationMessage)); - }); - - test("an error at the beginning of a very long line", () { - expect(errorsForFile('$badDeclaration $veryLongString'), - equals(badDeclarationMessage)); - }); - - test("an error in the middle of a very long line", () { - expect(errorsForFile('$veryLongString $badDeclaration$veryLongString'), - equals(badDeclarationMessage)); - }); - }); -}
diff --git a/pkg/analyzer_cli/test/mocks.dart b/pkg/analyzer_cli/test/mocks.dart index 985464c..49f7251 100644 --- a/pkg/analyzer_cli/test/mocks.dart +++ b/pkg/analyzer_cli/test/mocks.dart
@@ -1,8 +1,8 @@ -// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file +// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. -import 'package:analyzer/analyzer.dart'; +import 'package:analyzer/error/error.dart'; import 'package:analyzer/source/line_info.dart'; import 'package:analyzer/src/generated/engine.dart'; import 'package:analyzer/src/generated/source.dart';
diff --git a/pkg/analyzer_cli/test/options_test.dart b/pkg/analyzer_cli/test/options_test.dart index b0c8a8c..6001816 100644 --- a/pkg/analyzer_cli/test/options_test.dart +++ b/pkg/analyzer_cli/test/options_test.dart
@@ -1,9 +1,7 @@ -// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file +// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. -library analyzer_cli.test.options; - import 'dart:io'; import 'package:analyzer_cli/src/driver.dart'; @@ -58,6 +56,7 @@ expect(options.dartSdkPath, isNotNull); expect(options.disableCacheFlushing, isFalse); expect(options.disableHints, isFalse); + expect(options.enabledExperiments, isEmpty); expect(options.lints, isFalse); expect(options.displayVersion, isFalse); expect(options.infosAreFatal, isFalse); @@ -72,7 +71,6 @@ expect(options.warningsAreFatal, isFalse); expect(options.strongMode, isTrue); expect(options.lintsAreFatal, isFalse); - expect(options.previewDart2, isTrue); expect(options.trainSnapshot, isFalse); }); @@ -95,6 +93,49 @@ expect(options.disableCacheFlushing, isTrue); }); + group('enable experiment', () { + test('no values', () { + CommandLineOptions options = CommandLineOptions.parse(['foo.dart']); + expect(options.enabledExperiments, isEmpty); + }); + + test('single value', () { + CommandLineOptions options = CommandLineOptions.parse( + ['--enable-experiment', 'a', 'foo.dart']); + expect(options.enabledExperiments, ['a']); + }); + + group('multiple values', () { + test('single flag', () { + CommandLineOptions options = CommandLineOptions.parse( + ['--enable-experiment', 'a,b', 'foo.dart']); + expect(options.enabledExperiments, ['a', 'b']); + }); + + test('mixed single and multiple flags', () { + CommandLineOptions options = CommandLineOptions.parse([ + '--enable-experiment', + 'a,b', + '--enable-experiment', + 'c', + 'foo.dart' + ]); + expect(options.enabledExperiments, ['a', 'b', 'c']); + }); + + test('multiple flags', () { + CommandLineOptions options = CommandLineOptions.parse([ + '--enable-experiment', + 'a', + '--enable-experiment', + 'b', + 'foo.dart' + ]); + expect(options.enabledExperiments, ['a', 'b']); + }); + }); + }); + test('hintsAreFatal', () { CommandLineOptions options = CommandLineOptions.parse( ['--dart-sdk', '.', '--fatal-hints', 'foo.dart']); @@ -231,12 +272,6 @@ expect(options.useFastaParser, isTrue); }); - test('--preview-dart-2', () { - CommandLineOptions options = - CommandLineOptions.parse(['--preview-dart-2', 'foo.dart']); - expect(options.previewDart2, isTrue); - }); - test('--train-snapshot', () { CommandLineOptions options = CommandLineOptions.parse(['--train-snapshot', 'foo.dart']);
diff --git a/pkg/analyzer_cli/test/reporter_test.dart b/pkg/analyzer_cli/test/reporter_test.dart index a86c03d..26d37ac 100644 --- a/pkg/analyzer_cli/test/reporter_test.dart +++ b/pkg/analyzer_cli/test/reporter_test.dart
@@ -1,8 +1,8 @@ -// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file +// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. -import 'package:analyzer/analyzer.dart'; +import 'package:analyzer/error/error.dart'; import 'package:analyzer/source/line_info.dart'; import 'package:analyzer/src/generated/engine.dart'; import 'package:analyzer_cli/src/ansi.dart' as ansi;
diff --git a/pkg/analyzer_cli/test/utils.dart b/pkg/analyzer_cli/test/utils.dart index fd431a2..3803341 100644 --- a/pkg/analyzer_cli/test/utils.dart +++ b/pkg/analyzer_cli/test/utils.dart
@@ -1,14 +1,11 @@ -// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file +// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. -library analyzer_cli.test.utils; - import 'dart:async'; import 'dart:io'; import 'dart:mirrors'; -import 'package:analyzer/analyzer.dart'; import 'package:path/path.dart' as pathos; /// Gets the test directory in a way that works with package:test @@ -16,30 +13,6 @@ final String testDirectory = pathos.dirname( pathos.fromUri((reflectClass(_TestUtils).owner as LibraryMirror).uri)); -/// Returns the string representation of the [AnalyzerErrorGroup] thrown when -/// parsing [contents] as a Dart file. If [contents] doesn't throw any errors, -/// this will return null. -/// -/// This replaces the filename in the error string with its basename, since the -/// full path will vary from machine to machine. It also replaces the exception -/// message with "..." to decouple these tests from the specific exception -/// messages. -String errorsForFile(String contents) { - return withTempDir((temp) { - var path = pathos.join(temp, 'test.dart'); - new File(path).writeAsStringSync(contents); - try { - parseDartFile(path); - } on AnalyzerErrorGroup catch (e) { - return e.toString().replaceAllMapped( - new RegExp(r"^(Error on line \d+ of )((?:[A-Z]+:)?[^:]+): .*$", - multiLine: true), - (match) => match[1] + pathos.basename(match[2]) + ': ...'); - } - return null; - }); -} - /// Recursively copy the specified [src] directory (or file) /// to the specified destination path. Future<Null> recursiveCopy(FileSystemEntity src, String dstPath) async {
diff --git a/pkg/analyzer_plugin/lib/plugin/assist_mixin.dart b/pkg/analyzer_plugin/lib/plugin/assist_mixin.dart index 9eb8286..d17d4cd 100644 --- a/pkg/analyzer_plugin/lib/plugin/assist_mixin.dart +++ b/pkg/analyzer_plugin/lib/plugin/assist_mixin.dart
@@ -17,10 +17,10 @@ * A mixin that can be used when creating a subclass of [ServerPlugin] to * provide most of the implementation for handling assist requests. * - * Clients may not extend or implement this class, but are allowed to use it as - * a mix-in when creating a subclass of [ServerPlugin]. + * Clients may not implement this mixin, but are allowed to use it as a mix-in + * when creating a subclass of [ServerPlugin]. */ -abstract class AssistsMixin implements ServerPlugin { +mixin AssistsMixin implements ServerPlugin { /** * Return a list containing the assist contributors that should be used to * create assists for the file with the given [path]. @@ -67,7 +67,7 @@ // TODO(brianwilkerson) Determine whether this await is necessary. await null; String path = parameters.file; - ResolveResult result = await getResolveResult(path); + ResolvedUnitResult result = await getResolvedUnitResult(path); return new DartAssistRequestImpl( resourceProvider, parameters.offset, parameters.length, result); }
diff --git a/pkg/analyzer_plugin/lib/plugin/completion_mixin.dart b/pkg/analyzer_plugin/lib/plugin/completion_mixin.dart index 72de7ce..a8aa3b8 100644 --- a/pkg/analyzer_plugin/lib/plugin/completion_mixin.dart +++ b/pkg/analyzer_plugin/lib/plugin/completion_mixin.dart
@@ -17,10 +17,10 @@ * A mixin that can be used when creating a subclass of [ServerPlugin] to * provide most of the implementation for handling code completion requests. * - * Clients may not extend or implement this class, but are allowed to use it as - * a mix-in when creating a subclass of [ServerPlugin]. + * Clients may not implement this mixin, but are allowed to use it as a mix-in + * when creating a subclass of [ServerPlugin]. */ -abstract class CompletionMixin implements ServerPlugin { +mixin CompletionMixin implements ServerPlugin { /** * Return a list containing the completion contributors that should be used to * create completion suggestions for the file with the given [path]. @@ -68,7 +68,7 @@ CompletionGetSuggestionsParams parameters) async { // TODO(brianwilkerson) Determine whether this await is necessary. await null; - ResolveResult result = await getResolveResult(parameters.file); + ResolvedUnitResult result = await getResolvedUnitResult(parameters.file); return new DartCompletionRequestImpl( resourceProvider, parameters.offset, result); }
diff --git a/pkg/analyzer_plugin/lib/plugin/fix_mixin.dart b/pkg/analyzer_plugin/lib/plugin/fix_mixin.dart index 917dc3e..a4a113d 100644 --- a/pkg/analyzer_plugin/lib/plugin/fix_mixin.dart +++ b/pkg/analyzer_plugin/lib/plugin/fix_mixin.dart
@@ -20,23 +20,23 @@ * mixing in [FixesMixin]. This implements the creation of the fixes request * based on the assumption that the driver being created is an [AnalysisDriver]. * - * Clients may not extend or implement this class, but are allowed to use it as - * a mix-in when creating a subclass of [ServerPlugin] that also uses - * [FixesMixin] as a mix-in. + * Clients may not implement this mixin, but are allowed to use it as a mix-in + * when creating a subclass of [ServerPlugin] that also uses [FixesMixin] as a + * mix-in. */ -abstract class DartFixesMixin implements FixesMixin { +mixin DartFixesMixin implements FixesMixin { @override Future<FixesRequest> getFixesRequest(EditGetFixesParams parameters) async { // TODO(brianwilkerson) Determine whether this await is necessary. await null; String path = parameters.file; int offset = parameters.offset; - ResolveResult result = await getResolveResult(path); + ResolvedUnitResult result = await getResolvedUnitResult(path); return new DartFixesRequestImpl( resourceProvider, offset, _getErrors(offset, result), result); } - List<AnalysisError> _getErrors(int offset, ResolveResult result) { + List<AnalysisError> _getErrors(int offset, ResolvedUnitResult result) { LineInfo lineInfo = result.lineInfo; int offsetLine = lineInfo.getLocation(offset).lineNumber; return result.errors.where((AnalysisError error) { @@ -50,10 +50,10 @@ * A mixin that can be used when creating a subclass of [ServerPlugin] to * provide most of the implementation for handling fix requests. * - * Clients may not extend or implement this class, but are allowed to use it as - * a mix-in when creating a subclass of [ServerPlugin]. + * Clients may not implement this mixin, but are allowed to use it as a mix-in + * when creating a subclass of [ServerPlugin]. */ -abstract class FixesMixin implements ServerPlugin { +mixin FixesMixin implements ServerPlugin { /** * Return a list containing the fix contributors that should be used to create * fixes for the file with the given [path].
diff --git a/pkg/analyzer_plugin/lib/plugin/folding_mixin.dart b/pkg/analyzer_plugin/lib/plugin/folding_mixin.dart index 3c8d88c..1ca0f81 100644 --- a/pkg/analyzer_plugin/lib/plugin/folding_mixin.dart +++ b/pkg/analyzer_plugin/lib/plugin/folding_mixin.dart
@@ -18,16 +18,16 @@ * request based on the assumption that the driver being created is an * [AnalysisDriver]. * - * Clients may not extend or implement this class, but are allowed to use it as - * a mix-in when creating a subclass of [ServerPlugin] that also uses - * [FoldingMixin] as a mix-in. + * Clients may not implement this mixin, but are allowed to use it as a mix-in + * when creating a subclass of [ServerPlugin] that also uses [FoldingMixin] as a + * mix-in. */ -abstract class DartFoldingMixin implements FoldingMixin { +mixin DartFoldingMixin implements FoldingMixin { @override Future<FoldingRequest> getFoldingRequest(String path) async { // TODO(brianwilkerson) Determine whether this await is necessary. await null; - ResolveResult result = await getResolveResult(path); + ResolvedUnitResult result = await getResolvedUnitResult(path); return new DartFoldingRequestImpl(resourceProvider, result); } } @@ -36,10 +36,10 @@ * A mixin that can be used when creating a subclass of [ServerPlugin] to * provide most of the implementation for producing folding notifications. * - * Clients may not extend or implement this class, but are allowed to use it as - * a mix-in when creating a subclass of [ServerPlugin]. + * Clients may not implement this mixin, but are allowed to use it as a mix-in + * when creating a subclass of [ServerPlugin]. */ -abstract class FoldingMixin implements ServerPlugin { +mixin FoldingMixin implements ServerPlugin { /** * Return a list containing the folding contributors that should be used * to create folding regions for the file with the given [path].
diff --git a/pkg/analyzer_plugin/lib/plugin/highlights_mixin.dart b/pkg/analyzer_plugin/lib/plugin/highlights_mixin.dart index a401db8..20748c9 100644 --- a/pkg/analyzer_plugin/lib/plugin/highlights_mixin.dart +++ b/pkg/analyzer_plugin/lib/plugin/highlights_mixin.dart
@@ -18,16 +18,16 @@ * highlighting request based on the assumption that the driver being created is * an [AnalysisDriver]. * - * Clients may not extend or implement this class, but are allowed to use it as - * a mix-in when creating a subclass of [ServerPlugin] that also uses - * [HighlightsMixin] as a mix-in. + * Clients may not implement this mixin, but are allowed to use it as a mix-in + * when creating a subclass of [ServerPlugin] that also uses [HighlightsMixin] + * as a mix-in. */ -abstract class DartHighlightsMixin implements HighlightsMixin { +mixin DartHighlightsMixin implements HighlightsMixin { @override Future<HighlightsRequest> getHighlightsRequest(String path) async { // TODO(brianwilkerson) Determine whether this await is necessary. await null; - ResolveResult result = await getResolveResult(path); + ResolvedUnitResult result = await getResolvedUnitResult(path); return new DartHighlightsRequestImpl(resourceProvider, result); } } @@ -36,10 +36,10 @@ * A mixin that can be used when creating a subclass of [ServerPlugin] to * provide most of the implementation for producing highlighting notifications. * - * Clients may not extend or implement this class, but are allowed to use it as - * a mix-in when creating a subclass of [ServerPlugin]. + * Clients may not implement this mixin, but are allowed to use it as a mix-in + * when creating a subclass of [ServerPlugin]. */ -abstract class HighlightsMixin implements ServerPlugin { +mixin HighlightsMixin implements ServerPlugin { /** * Return a list containing the highlighting contributors that should be used * to create highlighting information for the file with the given [path].
diff --git a/pkg/analyzer_plugin/lib/plugin/kythe_mixin.dart b/pkg/analyzer_plugin/lib/plugin/kythe_mixin.dart index 999ba57..be89c6c 100644 --- a/pkg/analyzer_plugin/lib/plugin/kythe_mixin.dart +++ b/pkg/analyzer_plugin/lib/plugin/kythe_mixin.dart
@@ -19,18 +19,18 @@ * request based on the assumption that the driver being created is an * [AnalysisDriver]. * - * Clients may not extend or implement this class, but are allowed to use it as - * a mix-in when creating a subclass of [ServerPlugin] that also uses - * [KytheMixin] as a mix-in. + * Clients may not implement this mixin, but are allowed to use it as a mix-in + * when creating a subclass of [ServerPlugin] that also uses [KytheMixin] as a + * mix-in. */ -abstract class DartEntryMixin implements EntryMixin { +mixin DartEntryMixin implements EntryMixin { @override Future<EntryRequest> getEntryRequest( KytheGetKytheEntriesParams parameters) async { // TODO(brianwilkerson) Determine whether this await is necessary. await null; String path = parameters.file; - ResolveResult result = await getResolveResult(path); + ResolvedUnitResult result = await getResolvedUnitResult(path); return new DartEntryRequestImpl(resourceProvider, result); } } @@ -39,10 +39,10 @@ * A mixin that can be used when creating a subclass of [ServerPlugin] to * provide most of the implementation for handling kythe.getEntries requests. * - * Clients may not extend or implement this class, but are allowed to use it as - * a mix-in when creating a subclass of [ServerPlugin]. + * Clients may not implement this mixin, but are allowed to use it as a mix-in + * when creating a subclass of [ServerPlugin]. */ -abstract class EntryMixin implements ServerPlugin { +mixin EntryMixin implements ServerPlugin { /** * Return a list containing the entry contributors that should be used to * create entries for the file with the given [path]
diff --git a/pkg/analyzer_plugin/lib/plugin/navigation_mixin.dart b/pkg/analyzer_plugin/lib/plugin/navigation_mixin.dart index e1e6e28..96bfdc5 100644 --- a/pkg/analyzer_plugin/lib/plugin/navigation_mixin.dart +++ b/pkg/analyzer_plugin/lib/plugin/navigation_mixin.dart
@@ -19,18 +19,18 @@ * request based on the assumption that the driver being created is an * [AnalysisDriver]. * - * Clients may not extend or implement this class, but are allowed to use it as - * a mix-in when creating a subclass of [ServerPlugin] that also uses - * [NavigationMixin] as a mix-in. + * Clients may not implement this mixin, but are allowed to use it as a mix-in + * when creating a subclass of [ServerPlugin] that also uses [NavigationMixin] + * as a mix-in. */ -abstract class DartNavigationMixin implements NavigationMixin { +mixin DartNavigationMixin implements NavigationMixin { @override Future<NavigationRequest> getNavigationRequest( AnalysisGetNavigationParams parameters) async { // TODO(brianwilkerson) Determine whether this await is necessary. await null; String path = parameters.file; - ResolveResult result = await getResolveResult(path); + ResolvedUnitResult result = await getResolvedUnitResult(path); int offset = parameters.offset; int length = parameters.length; if (offset < 0 && length < 0) { @@ -46,10 +46,10 @@ * A mixin that can be used when creating a subclass of [ServerPlugin] to * provide most of the implementation for handling navigation requests. * - * Clients may not extend or implement this class, but are allowed to use it as - * a mix-in when creating a subclass of [ServerPlugin]. + * Clients may not implement this mixin, but are allowed to use it as a mix-in + * when creating a subclass of [ServerPlugin]. */ -abstract class NavigationMixin implements ServerPlugin { +mixin NavigationMixin implements ServerPlugin { /** * Return a list containing the navigation contributors that should be used to * create navigation information for the file with the given [path]
diff --git a/pkg/analyzer_plugin/lib/plugin/occurrences_mixin.dart b/pkg/analyzer_plugin/lib/plugin/occurrences_mixin.dart index 5766d9b..8547779 100644 --- a/pkg/analyzer_plugin/lib/plugin/occurrences_mixin.dart +++ b/pkg/analyzer_plugin/lib/plugin/occurrences_mixin.dart
@@ -18,16 +18,16 @@ * request based on the assumption that the driver being created is an * [AnalysisDriver]. * - * Clients may not extend or implement this class, but are allowed to use it as - * a mix-in when creating a subclass of [ServerPlugin] that also uses - * [OccurrencesMixin] as a mix-in. + * Clients may not implement this mixin, but are allowed to use it as a mix-in + * when creating a subclass of [ServerPlugin] that also uses [OccurrencesMixin] + * as a mix-in. */ -abstract class DartOccurrencesMixin implements OccurrencesMixin { +mixin DartOccurrencesMixin implements OccurrencesMixin { @override Future<OccurrencesRequest> getOccurrencesRequest(String path) async { // TODO(brianwilkerson) Determine whether this await is necessary. await null; - ResolveResult result = await getResolveResult(path); + ResolvedUnitResult result = await getResolvedUnitResult(path); return new DartOccurrencesRequestImpl(resourceProvider, result); } } @@ -36,10 +36,10 @@ * A mixin that can be used when creating a subclass of [ServerPlugin] to * provide most of the implementation for producing occurrences notifications. * - * Clients may not extend or implement this class, but are allowed to use it as - * a mix-in when creating a subclass of [ServerPlugin]. + * Clients may not implement this mixin, but are allowed to use it as a mix-in + * when creating a subclass of [ServerPlugin]. */ -abstract class OccurrencesMixin implements ServerPlugin { +mixin OccurrencesMixin implements ServerPlugin { /** * Return a list containing the occurrences contributors that should be used * to create occurrences information for the file with the given [path].
diff --git a/pkg/analyzer_plugin/lib/plugin/outline_mixin.dart b/pkg/analyzer_plugin/lib/plugin/outline_mixin.dart index 96bbdc4..4207a25 100644 --- a/pkg/analyzer_plugin/lib/plugin/outline_mixin.dart +++ b/pkg/analyzer_plugin/lib/plugin/outline_mixin.dart
@@ -18,16 +18,16 @@ * request based on the assumption that the driver being created is an * [AnalysisDriver]. * - * Clients may not extend or implement this class, but are allowed to use it as - * a mix-in when creating a subclass of [ServerPlugin] that also uses - * [OutlineMixin] as a mix-in. + * Clients may not implement this mixin, but are allowed to use it as a mix-in + * when creating a subclass of [ServerPlugin] that also uses [OutlineMixin] as a + * mix-in. */ -abstract class DartOutlineMixin implements OutlineMixin { +mixin DartOutlineMixin implements OutlineMixin { @override Future<OutlineRequest> getOutlineRequest(String path) async { // TODO(brianwilkerson) Determine whether this await is necessary. await null; - ResolveResult result = await getResolveResult(path); + ResolvedUnitResult result = await getResolvedUnitResult(path); return new DartOutlineRequestImpl(resourceProvider, result); } } @@ -36,10 +36,10 @@ * A mixin that can be used when creating a subclass of [ServerPlugin] to * provide most of the implementation for producing outline notifications. * - * Clients may not extend or implement this class, but are allowed to use it as - * a mix-in when creating a subclass of [ServerPlugin]. + * Clients may not implement this mixin, but are allowed to use it as a mix-in + * when creating a subclass of [ServerPlugin]. */ -abstract class OutlineMixin implements ServerPlugin { +mixin OutlineMixin implements ServerPlugin { /** * Return a list containing the outline contributors that should be used to * create outline information for the file with the given [path].
diff --git a/pkg/analyzer_plugin/lib/plugin/plugin.dart b/pkg/analyzer_plugin/lib/plugin/plugin.dart index 5fb6296..44ad8e9 100644 --- a/pkg/analyzer_plugin/lib/plugin/plugin.dart +++ b/pkg/analyzer_plugin/lib/plugin/plugin.dart
@@ -208,7 +208,7 @@ * Throw a [RequestFailure] is the file cannot be analyzed or if the driver * associated with the file is not an [AnalysisDriver]. */ - Future<ResolveResult> getResolveResult(String path) async { + Future<ResolvedUnitResult> getResolvedUnitResult(String path) async { // TODO(brianwilkerson) Determine whether this await is necessary. await null; AnalysisDriverGeneric driver = driverForPath(path); @@ -217,7 +217,8 @@ throw new RequestFailure( RequestErrorFactory.pluginError('Failed to analyze $path', null)); } - ResolveResult result = await (driver as AnalysisDriver).getResult(path); + ResolvedUnitResult result = + await (driver as AnalysisDriver).getResult(path); ResultState state = result.state; if (state != ResultState.VALID) { // Return an error from the request. @@ -228,6 +229,16 @@ } /** + * Return the result of analyzing the file with the given [path]. + * + * Throw a [RequestFailure] is the file cannot be analyzed or if the driver + * associated with the file is not an [AnalysisDriver]. + */ + @deprecated + Future<ResolveResult> getResolveResult(String path) => + getResolvedUnitResult(path); + + /** * Handle an 'analysis.getNavigation' request. * * Throw a [RequestFailure] if the request could not be handled.
diff --git a/pkg/analyzer_plugin/lib/src/channel/isolate_channel.dart b/pkg/analyzer_plugin/lib/src/channel/isolate_channel.dart index 8d7b094..aa65532 100644 --- a/pkg/analyzer_plugin/lib/src/channel/isolate_channel.dart +++ b/pkg/analyzer_plugin/lib/src/channel/isolate_channel.dart
@@ -121,7 +121,7 @@ void listen(void onRequest(Request request), {Function onError, void onDone()}) { void onData(data) { - Map<String, Object> requestMap = data; + Map<String, Object> requestMap = data as Map<String, Object>; Request request = new Request.fromJson(requestMap); if (request != null) { onRequest(request);
diff --git a/pkg/analyzer_plugin/lib/src/utilities/assist/assist.dart b/pkg/analyzer_plugin/lib/src/utilities/assist/assist.dart index dcbe5eb..95b0893 100644 --- a/pkg/analyzer_plugin/lib/src/utilities/assist/assist.dart +++ b/pkg/analyzer_plugin/lib/src/utilities/assist/assist.dart
@@ -36,7 +36,7 @@ final int length; @override - final ResolveResult result; + final ResolvedUnitResult result; /** * Initialize a newly create request with the given data.
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 7618568..8a9eba3 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
@@ -44,7 +44,7 @@ String path, void buildFileEdit(DartFileEditBuilder builder), {ImportPrefixGenerator importPrefixGenerator}) { return super.addFileEdit(path, (builder) { - DartFileEditBuilderImpl dartBuilder = builder; + DartFileEditBuilderImpl dartBuilder = builder as DartFileEditBuilderImpl; dartBuilder.importPrefixGenerator = importPrefixGenerator; buildFileEdit(dartBuilder); }); @@ -54,7 +54,7 @@ Future<DartFileEditBuilderImpl> createFileEditBuilder(String path) async { // TODO(brianwilkerson) Determine whether this await is necessary. await null; - ResolveResult result = await session.getResolvedAst(path); + ResolvedUnitResult result = await session.getResolvedUnit(path); ResultState state = result?.state ?? ResultState.INVALID_FILE_TYPE; if (state == ResultState.INVALID_FILE_TYPE) { throw new AnalysisException('Cannot analyze "$path"'); @@ -402,7 +402,7 @@ } } - ExecutableElement element = signature.element; + ExecutableElement element = signature.element as ExecutableElement; String prefix = getIndent(1); String prefix2 = getIndent(2); ElementKind elementKind = element.kind; @@ -472,10 +472,11 @@ // TO-DO write(prefix2); - writeln('// TODO: implement $memberName'); + write('// TODO: implement $memberName'); if (isSetter) { if (invokeSuper) { + writeln(); write(prefix2); selectAll(() { write('super.'); @@ -485,9 +486,13 @@ write(';'); }); writeln(); + } else { + selectHere(); + writeln(); } } else if (returnType.isVoid) { if (invokeSuper) { + writeln(); write(prefix2); selectAll(() { write('super.'); @@ -502,8 +507,12 @@ write(');'); }); writeln(); + } else { + selectHere(); + writeln(); } } else { + writeln(); write(prefix2); if (invokeSuper) { selectAll(() {
diff --git a/pkg/analyzer_plugin/lib/src/utilities/completion/completion_core.dart b/pkg/analyzer_plugin/lib/src/utilities/completion/completion_core.dart index 209e451..7bf30d5 100644 --- a/pkg/analyzer_plugin/lib/src/utilities/completion/completion_core.dart +++ b/pkg/analyzer_plugin/lib/src/utilities/completion/completion_core.dart
@@ -84,7 +84,7 @@ final int offset; @override - final ResolveResult result; + final ResolvedUnitResult result; /** * A flag indicating whether completion has been aborted.
diff --git a/pkg/analyzer_plugin/lib/src/utilities/completion/completion_target.dart b/pkg/analyzer_plugin/lib/src/utilities/completion/completion_target.dart index 03fcb97..69a0aae 100644 --- a/pkg/analyzer_plugin/lib/src/utilities/completion/completion_target.dart +++ b/pkg/analyzer_plugin/lib/src/utilities/completion/completion_target.dart
@@ -154,7 +154,7 @@ if (containingNode is Comment) { // Comments are handled specially: we descend into any CommentReference // child node that contains the cursor offset. - Comment comment = containingNode; + Comment comment = containingNode as Comment; for (CommentReference commentReference in comment.references) { if (commentReference.offset <= offset && offset <= commentReference.end) { @@ -276,7 +276,7 @@ token.type.isKeyword || token.type == TokenType.IDENTIFIER; Token token = droppedToken ?? - (entity is AstNode ? (entity as AstNode).beginToken : entity); + (entity is AstNode ? (entity as AstNode).beginToken : entity as Token); if (token != null && requestOffset < token.offset) { token = containingNode.findPrevious(token); }
diff --git a/pkg/analyzer_plugin/lib/src/utilities/completion/element_suggestion_builder.dart b/pkg/analyzer_plugin/lib/src/utilities/completion/element_suggestion_builder.dart index 546f664..8b93677 100644 --- a/pkg/analyzer_plugin/lib/src/utilities/completion/element_suggestion_builder.dart +++ b/pkg/analyzer_plugin/lib/src/utilities/completion/element_suggestion_builder.dart
@@ -13,7 +13,7 @@ /** * Common mixin for sharing behavior. */ -abstract class ElementSuggestionBuilder { +mixin ElementSuggestionBuilder { // Copied from analysis_server/lib/src/services/completion/dart/suggestion_builder.dart /** * A collection of completion suggestions.
diff --git a/pkg/analyzer_plugin/lib/src/utilities/completion/optype.dart b/pkg/analyzer_plugin/lib/src/utilities/completion/optype.dart index a77fe18..e005b30 100644 --- a/pkg/analyzer_plugin/lib/src/utilities/completion/optype.dart +++ b/pkg/analyzer_plugin/lib/src/utilities/completion/optype.dart
@@ -129,21 +129,26 @@ return optype; } - target.containingNode - .accept(new _OpTypeAstVisitor(optype, target.entity, offset)); - var methodDeclaration = - target.containingNode.getAncestor((node) => node is MethodDeclaration); - optype.inMethodBody = methodDeclaration != null; - optype.inStaticMethodBody = - methodDeclaration is MethodDeclaration && methodDeclaration.isStatic; + var targetNode = target.containingNode; + targetNode.accept(new _OpTypeAstVisitor(optype, target.entity, offset)); - var functionDeclaration = target.containingNode - .getAncestor((node) => node is FunctionDeclaration); - optype.inFunctionBody = functionDeclaration != null; + var functionBody = targetNode.thisOrAncestorOfType<FunctionBody>(); + if (functionBody != null) { + var parent = functionBody.parent; - var constructorDeclaration = target.containingNode - .getAncestor((node) => node is ConstructorDeclaration); - optype.inConstructorBody = constructorDeclaration != null; + if (parent is ConstructorDeclaration) { + optype.inConstructorBody = true; + } + + if (parent is FunctionExpression) { + optype.inFunctionBody = true; + } + + if (parent is MethodDeclaration) { + optype.inMethodBody = true; + optype.inStaticMethodBody = parent.isStatic; + } + } // If a value should be suggested, suggest also constructors. if (optype.includeReturnValueSuggestions) { @@ -482,6 +487,14 @@ } @override + visitConstructorFieldInitializer(ConstructorFieldInitializer node) { + if (identical(entity, node.expression)) { + optype.includeReturnValueSuggestions = true; + optype.includeTypeNameSuggestions = true; + } + } + + @override visitConstructorName(ConstructorName node) { // some PrefixedIdentifier nodes are transformed into // ConstructorName nodes during the resolution process. @@ -548,7 +561,7 @@ // Given f[], the parser drops the [] from the expression statement // but the [] token is the CompletionTarget entity if (entity is Token) { - Token token = entity; + Token token = entity as Token; if (token.lexeme == '[]' && offset == token.offset + 1) { optype.includeReturnValueSuggestions = true; optype.includeTypeNameSuggestions = true; @@ -976,7 +989,7 @@ @override void visitTopLevelVariableDeclaration(TopLevelVariableDeclaration node) { if (entity is Token) { - Token token = entity; + Token token = entity as Token; if (token.isSynthetic || token.lexeme == ';') { optype.includeVarNameSuggestions = true; }
diff --git a/pkg/analyzer_plugin/lib/src/utilities/fixes/fixes.dart b/pkg/analyzer_plugin/lib/src/utilities/fixes/fixes.dart index 54d9b45..8973624 100644 --- a/pkg/analyzer_plugin/lib/src/utilities/fixes/fixes.dart +++ b/pkg/analyzer_plugin/lib/src/utilities/fixes/fixes.dart
@@ -23,7 +23,7 @@ final List<AnalysisError> errorsToFix; @override - final ResolveResult result; + final ResolvedUnitResult result; /** * Initialize a newly create request with the given data.
diff --git a/pkg/analyzer_plugin/lib/src/utilities/folding/folding.dart b/pkg/analyzer_plugin/lib/src/utilities/folding/folding.dart index 1e7eb67f..2d5578c 100644 --- a/pkg/analyzer_plugin/lib/src/utilities/folding/folding.dart +++ b/pkg/analyzer_plugin/lib/src/utilities/folding/folding.dart
@@ -17,7 +17,7 @@ final ResourceProvider resourceProvider; @override - final ResolveResult result; + final ResolvedUnitResult result; /** * Initialize a newly create request with the given data.
diff --git a/pkg/analyzer_plugin/lib/src/utilities/highlights/highlights.dart b/pkg/analyzer_plugin/lib/src/utilities/highlights/highlights.dart index bb24bcb..8412dac 100644 --- a/pkg/analyzer_plugin/lib/src/utilities/highlights/highlights.dart +++ b/pkg/analyzer_plugin/lib/src/utilities/highlights/highlights.dart
@@ -17,7 +17,7 @@ final ResourceProvider resourceProvider; @override - final ResolveResult result; + final ResolvedUnitResult result; /** * Initialize a newly create request with the given data.
diff --git a/pkg/analyzer_plugin/lib/src/utilities/kythe/entries.dart b/pkg/analyzer_plugin/lib/src/utilities/kythe/entries.dart index 72256df..eb4163a 100644 --- a/pkg/analyzer_plugin/lib/src/utilities/kythe/entries.dart +++ b/pkg/analyzer_plugin/lib/src/utilities/kythe/entries.dart
@@ -15,7 +15,7 @@ final ResourceProvider resourceProvider; @override - final ResolveResult result; + final ResolvedUnitResult result; /** * Initialize a newly create request with the given data.
diff --git a/pkg/analyzer_plugin/lib/src/utilities/navigation/navigation.dart b/pkg/analyzer_plugin/lib/src/utilities/navigation/navigation.dart index f8b4b11..31e004b 100644 --- a/pkg/analyzer_plugin/lib/src/utilities/navigation/navigation.dart +++ b/pkg/analyzer_plugin/lib/src/utilities/navigation/navigation.dart
@@ -23,7 +23,7 @@ final int offset; @override - final ResolveResult result; + final ResolvedUnitResult result; /** * Initialize a newly create request with the given data.
diff --git a/pkg/analyzer_plugin/lib/src/utilities/occurrences/occurrences.dart b/pkg/analyzer_plugin/lib/src/utilities/occurrences/occurrences.dart index 42b95c2..2538191 100644 --- a/pkg/analyzer_plugin/lib/src/utilities/occurrences/occurrences.dart +++ b/pkg/analyzer_plugin/lib/src/utilities/occurrences/occurrences.dart
@@ -16,7 +16,7 @@ final ResourceProvider resourceProvider; @override - final ResolveResult result; + final ResolvedUnitResult result; /** * Initialize a newly create request with the given data.
diff --git a/pkg/analyzer_plugin/lib/src/utilities/outline/outline.dart b/pkg/analyzer_plugin/lib/src/utilities/outline/outline.dart index f87c5fc..47fba67 100644 --- a/pkg/analyzer_plugin/lib/src/utilities/outline/outline.dart +++ b/pkg/analyzer_plugin/lib/src/utilities/outline/outline.dart
@@ -16,7 +16,7 @@ final ResourceProvider resourceProvider; @override - final ResolveResult result; + final ResolvedUnitResult result; /** * Initialize a newly create request with the given data.
diff --git a/pkg/analyzer_plugin/lib/src/utilities/visitors/local_declaration_visitor.dart b/pkg/analyzer_plugin/lib/src/utilities/visitors/local_declaration_visitor.dart index ec525ca..ba1ec8f 100644 --- a/pkg/analyzer_plugin/lib/src/utilities/visitors/local_declaration_visitor.dart +++ b/pkg/analyzer_plugin/lib/src/utilities/visitors/local_declaration_visitor.dart
@@ -35,6 +35,8 @@ void declaredFunctionTypeAlias(FunctionTypeAlias declaration); + void declaredGenericTypeAlias(GenericTypeAlias declaration); + void declaredLabel(Label label, bool isCaseLabel); void declaredLocalVar(SimpleIdentifier name, TypeAnnotation type); @@ -113,6 +115,8 @@ declaredClassTypeAlias(declaration); } else if (declaration is FunctionTypeAlias) { declaredFunctionTypeAlias(declaration); + } else if (declaration is GenericTypeAlias) { + declaredGenericTypeAlias(declaration); } }); }
diff --git a/pkg/analyzer_plugin/lib/utilities/analyzer_converter.dart b/pkg/analyzer_plugin/lib/utilities/analyzer_converter.dart index 5fd4f25..c4fe0c2 100644 --- a/pkg/analyzer_plugin/lib/utilities/analyzer_converter.dart +++ b/pkg/analyzer_plugin/lib/utilities/analyzer_converter.dart
@@ -36,7 +36,8 @@ int startLine = -1; int startColumn = -1; if (lineInfo != null) { - analyzer.CharacterLocation lineLocation = lineInfo.getLocation(offset); + analyzer.CharacterLocation lineLocation = + lineInfo.getLocation(offset) as analyzer.CharacterLocation; if (lineLocation != null) { startLine = lineLocation.lineNumber; startColumn = lineLocation.columnNumber; @@ -126,6 +127,8 @@ return plugin.ElementKind.FUNCTION; } else if (kind == analyzer.ElementKind.FUNCTION_TYPE_ALIAS) { return plugin.ElementKind.FUNCTION_TYPE_ALIAS; + } else if (kind == analyzer.ElementKind.GENERIC_FUNCTION_TYPE) { + return plugin.ElementKind.FUNCTION_TYPE_ALIAS; } else if (kind == analyzer.ElementKind.GETTER) { return plugin.ElementKind.GETTER; } else if (kind == analyzer.ElementKind.LABEL) { @@ -340,7 +343,7 @@ analyzer.LineInfo lineInfo = unitElement.lineInfo; if (lineInfo != null) { analyzer.CharacterLocation offsetLocation = - lineInfo.getLocation(range.offset); + lineInfo.getLocation(range.offset) as analyzer.CharacterLocation; startLine = offsetLocation.lineNumber; startColumn = offsetLocation.columnNumber; }
diff --git a/pkg/analyzer_plugin/lib/utilities/assist/assist.dart b/pkg/analyzer_plugin/lib/utilities/assist/assist.dart index 72c3e0d..7e02aea 100644 --- a/pkg/analyzer_plugin/lib/utilities/assist/assist.dart +++ b/pkg/analyzer_plugin/lib/utilities/assist/assist.dart
@@ -145,5 +145,5 @@ /** * The analysis result for the file in which the assists are being requested. */ - ResolveResult get result; + ResolvedUnitResult get result; }
diff --git a/pkg/analyzer_plugin/lib/utilities/completion/completion_core.dart b/pkg/analyzer_plugin/lib/utilities/completion/completion_core.dart index c037112..6a354cd 100644 --- a/pkg/analyzer_plugin/lib/utilities/completion/completion_core.dart +++ b/pkg/analyzer_plugin/lib/utilities/completion/completion_core.dart
@@ -160,5 +160,5 @@ * The analysis result for the file in which the completion is being * requested. */ - ResolveResult get result; + ResolvedUnitResult get result; }
diff --git a/pkg/analyzer_plugin/lib/utilities/completion/inherited_reference_contributor.dart b/pkg/analyzer_plugin/lib/utilities/completion/inherited_reference_contributor.dart index c3af0db..e3567fc 100644 --- a/pkg/analyzer_plugin/lib/utilities/completion/inherited_reference_contributor.dart +++ b/pkg/analyzer_plugin/lib/utilities/completion/inherited_reference_contributor.dart
@@ -21,7 +21,7 @@ * Plugin developers should extend this function and primarily * overload `computeSuggestions` (if needed). */ -class InheritedReferenceContributor extends Object +class InheritedReferenceContributor with ElementSuggestionBuilder implements CompletionContributor { @override
diff --git a/pkg/analyzer_plugin/lib/utilities/completion/type_member_contributor.dart b/pkg/analyzer_plugin/lib/utilities/completion/type_member_contributor.dart index 28ab1f9..dd4a046 100644 --- a/pkg/analyzer_plugin/lib/utilities/completion/type_member_contributor.dart +++ b/pkg/analyzer_plugin/lib/utilities/completion/type_member_contributor.dart
@@ -151,7 +151,7 @@ // Determine the name of the containing method because // the most likely completion is a super expression with same name MethodDeclaration containingMethod = - expression.getAncestor((p) => p is MethodDeclaration); + expression.thisOrAncestorOfType<MethodDeclaration>(); if (containingMethod != null) { SimpleIdentifier id = containingMethod.name; if (id != null) { @@ -241,6 +241,17 @@ } @override + void declaredGenericTypeAlias(GenericTypeAlias declaration) { + if (declaration.name.name == targetName) { + TypeAnnotation typeName = declaration.functionType.returnType; + if (typeName != null) { + typeFound = typeName.type; + } + finished(); + } + } + + @override void declaredLabel(Label label, bool isCaseLabel) { if (label.label.name == targetName) { // no type
diff --git a/pkg/analyzer_plugin/lib/utilities/fixes/fixes.dart b/pkg/analyzer_plugin/lib/utilities/fixes/fixes.dart index 3b0ab66..377fe37 100644 --- a/pkg/analyzer_plugin/lib/utilities/fixes/fixes.dart +++ b/pkg/analyzer_plugin/lib/utilities/fixes/fixes.dart
@@ -20,7 +20,7 @@ /** * The analysis result for the file in which the fixes are being requested. */ - ResolveResult get result; + ResolvedUnitResult get result; } /** @@ -147,11 +147,6 @@ final String appliedTogetherMessage; /** - * The change can be made with other fixes of this [FixKind]. - */ - bool canBeAppliedTogether() => appliedTogetherMessage != null; - - /** * Initialize a newly created kind of fix to have the given [name], * [priority], [message], and optionally [canBeAppliedTogether] and * [appliedTogetherMessage]. @@ -160,11 +155,16 @@ {this.appliedTogetherMessage: null}); @override - String toString() => name; + int get hashCode => name.hashCode; @override bool operator ==(o) => o is FixKind && o.name == name; + /** + * The change can be made with other fixes of this [FixKind]. + */ + bool canBeAppliedTogether() => appliedTogetherMessage != null; + @override - int get hashCode => name.hashCode; + String toString() => name; }
diff --git a/pkg/analyzer_plugin/lib/utilities/folding/folding.dart b/pkg/analyzer_plugin/lib/utilities/folding/folding.dart index 7eab6ad..6408d2f 100644 --- a/pkg/analyzer_plugin/lib/utilities/folding/folding.dart +++ b/pkg/analyzer_plugin/lib/utilities/folding/folding.dart
@@ -23,7 +23,7 @@ * The analysis result for the file for which the folding regions are being * requested. */ - ResolveResult get result; + ResolvedUnitResult get result; } /**
diff --git a/pkg/analyzer_plugin/lib/utilities/highlights/highlights.dart b/pkg/analyzer_plugin/lib/utilities/highlights/highlights.dart index 59acbe4..f24b280 100644 --- a/pkg/analyzer_plugin/lib/utilities/highlights/highlights.dart +++ b/pkg/analyzer_plugin/lib/utilities/highlights/highlights.dart
@@ -22,7 +22,7 @@ * The analysis result for the file for which the highlight regions are being * requested. */ - ResolveResult get result; + ResolvedUnitResult get result; } /**
diff --git a/pkg/analyzer_plugin/lib/utilities/kythe/entries.dart b/pkg/analyzer_plugin/lib/utilities/kythe/entries.dart index b89cab9..11b42d1 100644 --- a/pkg/analyzer_plugin/lib/utilities/kythe/entries.dart +++ b/pkg/analyzer_plugin/lib/utilities/kythe/entries.dart
@@ -20,7 +20,7 @@ /** * The analysis result for the file in which the entries are being requested. */ - ResolveResult get result; + ResolvedUnitResult get result; } /**
diff --git a/pkg/analyzer_plugin/lib/utilities/navigation/navigation.dart b/pkg/analyzer_plugin/lib/utilities/navigation/navigation.dart index d3233bc..3bc3471 100644 --- a/pkg/analyzer_plugin/lib/utilities/navigation/navigation.dart +++ b/pkg/analyzer_plugin/lib/utilities/navigation/navigation.dart
@@ -23,7 +23,7 @@ * The analysis result for the file in which the navigation regions are being * requested. */ - ResolveResult get result; + ResolvedUnitResult get result; } /**
diff --git a/pkg/analyzer_plugin/lib/utilities/occurrences/occurrences.dart b/pkg/analyzer_plugin/lib/utilities/occurrences/occurrences.dart index 820f38e..1fe0c1b 100644 --- a/pkg/analyzer_plugin/lib/utilities/occurrences/occurrences.dart +++ b/pkg/analyzer_plugin/lib/utilities/occurrences/occurrences.dart
@@ -22,7 +22,7 @@ * The analysis result for the file for which the occurrences information is * being requested. */ - ResolveResult get result; + ResolvedUnitResult get result; } /**
diff --git a/pkg/analyzer_plugin/lib/utilities/outline/outline.dart b/pkg/analyzer_plugin/lib/utilities/outline/outline.dart index f675976..21983f6 100644 --- a/pkg/analyzer_plugin/lib/utilities/outline/outline.dart +++ b/pkg/analyzer_plugin/lib/utilities/outline/outline.dart
@@ -21,7 +21,7 @@ /** * The analysis result for the file for which the outline is being requested. */ - ResolveResult get result; + ResolvedUnitResult get result; } /**
diff --git a/pkg/analyzer_plugin/test/integration/support/integration_tests.dart b/pkg/analyzer_plugin/test/integration/support/integration_tests.dart index 4a58401..e27ac4c 100644 --- a/pkg/analyzer_plugin/test/integration/support/integration_tests.dart +++ b/pkg/analyzer_plugin/test/integration/support/integration_tests.dart
@@ -548,10 +548,10 @@ return; } outOfTestExpect(message, isMap); - Map messageAsMap = message; + Map messageAsMap = message as Map; if (messageAsMap.containsKey('id')) { outOfTestExpect(messageAsMap['id'], isString); - String id = message['id']; + String id = message['id'] as String; Completer completer = _pendingCommands[id]; if (completer == null) { fail('Unexpected response from server: id=$id');
diff --git a/pkg/analyzer_plugin/test/plugin/assist_mixin_test.dart b/pkg/analyzer_plugin/test/plugin/assist_mixin_test.dart index 51e9802..f3d65c5 100644 --- a/pkg/analyzer_plugin/test/plugin/assist_mixin_test.dart +++ b/pkg/analyzer_plugin/test/plugin/assist_mixin_test.dart
@@ -5,14 +5,12 @@ import 'dart:async'; import 'package:analyzer/file_system/file_system.dart'; -import 'package:analyzer/file_system/memory_file_system.dart'; -import 'package:analyzer/src/dart/analysis/driver.dart'; +import 'package:analyzer/src/test_utilities/resource_provider_mixin.dart'; import 'package:analyzer_plugin/plugin/assist_mixin.dart'; import 'package:analyzer_plugin/protocol/protocol_common.dart'; import 'package:analyzer_plugin/protocol/protocol_generated.dart'; import 'package:analyzer_plugin/src/utilities/assist/assist.dart'; import 'package:analyzer_plugin/utilities/assist/assist.dart'; -import 'package:path/src/context.dart'; import 'package:test/test.dart'; import 'package:test_reflective_loader/test_reflective_loader.dart'; @@ -23,9 +21,7 @@ } @reflectiveTest -class AssistsMixinTest { - MemoryResourceProvider resourceProvider = new MemoryResourceProvider(); - +class AssistsMixinTest with ResourceProviderMixin { String packagePath1; String filePath1; ContextRoot contextRoot1; @@ -34,11 +30,9 @@ _TestServerPlugin plugin; void setUp() { - Context pathContext = resourceProvider.pathContext; - - packagePath1 = resourceProvider.convertPath('/package1'); - filePath1 = pathContext.join(packagePath1, 'lib', 'test.dart'); - resourceProvider.newFile(filePath1, ''); + packagePath1 = convertPath('/package1'); + filePath1 = join(packagePath1, 'lib', 'test.dart'); + newFile(filePath1); contextRoot1 = new ContextRoot(packagePath1, <String>[]); channel = new MockChannel(); @@ -90,7 +84,7 @@ @override Future<AssistRequest> getAssistRequest( EditGetAssistsParams parameters) async { - AnalysisResult result = new MockAnalysisResult(); + var result = new MockResolvedUnitResult(); return new DartAssistRequestImpl( resourceProvider, parameters.offset, parameters.length, result); }
diff --git a/pkg/analyzer_plugin/test/plugin/completion_mixin_test.dart b/pkg/analyzer_plugin/test/plugin/completion_mixin_test.dart index 0dcc99e..0c51a0a 100644 --- a/pkg/analyzer_plugin/test/plugin/completion_mixin_test.dart +++ b/pkg/analyzer_plugin/test/plugin/completion_mixin_test.dart
@@ -5,14 +5,12 @@ import 'dart:async'; import 'package:analyzer/file_system/file_system.dart'; -import 'package:analyzer/file_system/memory_file_system.dart'; -import 'package:analyzer/src/dart/analysis/driver.dart'; +import 'package:analyzer/src/test_utilities/resource_provider_mixin.dart'; import 'package:analyzer_plugin/plugin/completion_mixin.dart'; import 'package:analyzer_plugin/protocol/protocol_common.dart'; import 'package:analyzer_plugin/protocol/protocol_generated.dart'; import 'package:analyzer_plugin/src/utilities/completion/completion_core.dart'; import 'package:analyzer_plugin/utilities/completion/completion_core.dart'; -import 'package:path/src/context.dart'; import 'package:test/test.dart'; import 'package:test_reflective_loader/test_reflective_loader.dart'; @@ -23,9 +21,7 @@ } @reflectiveTest -class CompletionMixinTest { - MemoryResourceProvider resourceProvider = new MemoryResourceProvider(); - +class CompletionMixinTest with ResourceProviderMixin { String packagePath1; String filePath1; ContextRoot contextRoot1; @@ -34,11 +30,9 @@ _TestServerPlugin plugin; void setUp() { - Context pathContext = resourceProvider.pathContext; - - packagePath1 = resourceProvider.convertPath('/package1'); - filePath1 = pathContext.join(packagePath1, 'lib', 'test.dart'); - resourceProvider.newFile(filePath1, 'int foo = bar;'); + packagePath1 = convertPath('/package1'); + filePath1 = join(packagePath1, 'lib', 'test.dart'); + newFile(filePath1, content: 'int foo = bar;'); contextRoot1 = new ContextRoot(packagePath1, <String>[]); channel = new MockChannel(); @@ -98,7 +92,7 @@ @override Future<CompletionRequest> getCompletionRequest( CompletionGetSuggestionsParams parameters) async { - AnalysisResult result = new MockAnalysisResult(); + var result = new MockResolvedUnitResult(); return new DartCompletionRequestImpl( resourceProvider, parameters.offset, result); }
diff --git a/pkg/analyzer_plugin/test/plugin/fix_mixin_test.dart b/pkg/analyzer_plugin/test/plugin/fix_mixin_test.dart index 1d785dd..decd70d 100644 --- a/pkg/analyzer_plugin/test/plugin/fix_mixin_test.dart +++ b/pkg/analyzer_plugin/test/plugin/fix_mixin_test.dart
@@ -6,17 +6,15 @@ import 'package:analyzer/error/error.dart'; import 'package:analyzer/file_system/file_system.dart'; -import 'package:analyzer/file_system/memory_file_system.dart'; -import 'package:analyzer/src/dart/analysis/driver.dart'; import 'package:analyzer/src/error/codes.dart'; import 'package:analyzer/src/generated/source.dart'; +import 'package:analyzer/src/test_utilities/resource_provider_mixin.dart'; import 'package:analyzer_plugin/plugin/fix_mixin.dart'; import 'package:analyzer_plugin/protocol/protocol_common.dart' hide AnalysisError; import 'package:analyzer_plugin/protocol/protocol_generated.dart'; import 'package:analyzer_plugin/src/utilities/fixes/fixes.dart'; import 'package:analyzer_plugin/utilities/fixes/fixes.dart'; -import 'package:path/src/context.dart'; import 'package:test/test.dart'; import 'package:test_reflective_loader/test_reflective_loader.dart'; @@ -27,9 +25,7 @@ } @reflectiveTest -class FixesMixinTest { - MemoryResourceProvider resourceProvider = new MemoryResourceProvider(); - +class FixesMixinTest with ResourceProviderMixin { String packagePath1; String filePath1; ContextRoot contextRoot1; @@ -38,11 +34,9 @@ _TestServerPlugin plugin; void setUp() { - Context pathContext = resourceProvider.pathContext; - - packagePath1 = resourceProvider.convertPath('/package1'); - filePath1 = pathContext.join(packagePath1, 'lib', 'test.dart'); - resourceProvider.newFile(filePath1, ''); + packagePath1 = convertPath('/package1'); + filePath1 = join(packagePath1, 'lib', 'test.dart'); + newFile(filePath1); contextRoot1 = new ContextRoot(packagePath1, <String>[]); channel = new MockChannel(); @@ -98,7 +92,7 @@ int offset = parameters.offset; AnalysisError error = new AnalysisError( new MockSource(), 0, 0, CompileTimeErrorCode.AWAIT_IN_WRONG_CONTEXT); - AnalysisResult result = new MockAnalysisResult( + var result = new MockResolvedUnitResult( lineInfo: new LineInfo([0, 20]), errors: [error]); return new DartFixesRequestImpl(resourceProvider, offset, [error], result); }
diff --git a/pkg/analyzer_plugin/test/plugin/folding_mixin_test.dart b/pkg/analyzer_plugin/test/plugin/folding_mixin_test.dart index 5123b40..0b429bc 100644 --- a/pkg/analyzer_plugin/test/plugin/folding_mixin_test.dart +++ b/pkg/analyzer_plugin/test/plugin/folding_mixin_test.dart
@@ -5,15 +5,13 @@ import 'dart:async'; import 'package:analyzer/file_system/file_system.dart'; -import 'package:analyzer/file_system/memory_file_system.dart'; -import 'package:analyzer/src/dart/analysis/driver.dart'; +import 'package:analyzer/src/test_utilities/resource_provider_mixin.dart'; import 'package:analyzer_plugin/plugin/folding_mixin.dart'; import 'package:analyzer_plugin/protocol/protocol.dart'; import 'package:analyzer_plugin/protocol/protocol_common.dart'; import 'package:analyzer_plugin/protocol/protocol_generated.dart'; import 'package:analyzer_plugin/src/utilities/folding/folding.dart'; import 'package:analyzer_plugin/utilities/folding/folding.dart'; -import 'package:path/src/context.dart'; import 'package:test/test.dart'; import 'package:test_reflective_loader/test_reflective_loader.dart'; @@ -24,9 +22,7 @@ } @reflectiveTest -class FoldingMixinTest { - MemoryResourceProvider resourceProvider = new MemoryResourceProvider(); - +class FoldingMixinTest with ResourceProviderMixin { String packagePath1; String filePath1; ContextRoot contextRoot1; @@ -35,11 +31,9 @@ _TestServerPlugin plugin; void setUp() { - Context pathContext = resourceProvider.pathContext; - - packagePath1 = resourceProvider.convertPath('/package1'); - filePath1 = pathContext.join(packagePath1, 'lib', 'test.dart'); - resourceProvider.newFile(filePath1, ''); + packagePath1 = convertPath('/package1'); + filePath1 = join(packagePath1, 'lib', 'test.dart'); + newFile(filePath1); contextRoot1 = new ContextRoot(packagePath1, <String>[]); channel = new MockChannel(); @@ -93,7 +87,7 @@ @override Future<FoldingRequest> getFoldingRequest(String path) async { - AnalysisResult result = new MockAnalysisResult(path: path); + var result = new MockResolvedUnitResult(path: path); return new DartFoldingRequestImpl(resourceProvider, result); } }
diff --git a/pkg/analyzer_plugin/test/plugin/highlights_mixin_test.dart b/pkg/analyzer_plugin/test/plugin/highlights_mixin_test.dart index c0b4543..ced8227 100644 --- a/pkg/analyzer_plugin/test/plugin/highlights_mixin_test.dart +++ b/pkg/analyzer_plugin/test/plugin/highlights_mixin_test.dart
@@ -5,15 +5,13 @@ import 'dart:async'; import 'package:analyzer/file_system/file_system.dart'; -import 'package:analyzer/file_system/memory_file_system.dart'; -import 'package:analyzer/src/dart/analysis/driver.dart'; +import 'package:analyzer/src/test_utilities/resource_provider_mixin.dart'; import 'package:analyzer_plugin/plugin/highlights_mixin.dart'; import 'package:analyzer_plugin/protocol/protocol.dart'; import 'package:analyzer_plugin/protocol/protocol_common.dart'; import 'package:analyzer_plugin/protocol/protocol_generated.dart'; import 'package:analyzer_plugin/src/utilities/highlights/highlights.dart'; import 'package:analyzer_plugin/utilities/highlights/highlights.dart'; -import 'package:path/src/context.dart'; import 'package:test/test.dart'; import 'package:test_reflective_loader/test_reflective_loader.dart'; @@ -24,9 +22,7 @@ } @reflectiveTest -class HighlightsMixinTest { - MemoryResourceProvider resourceProvider = new MemoryResourceProvider(); - +class HighlightsMixinTest with ResourceProviderMixin { String packagePath1; String filePath1; ContextRoot contextRoot1; @@ -35,11 +31,9 @@ _TestServerPlugin plugin; void setUp() { - Context pathContext = resourceProvider.pathContext; - - packagePath1 = resourceProvider.convertPath('/package1'); - filePath1 = pathContext.join(packagePath1, 'lib', 'test.dart'); - resourceProvider.newFile(filePath1, ''); + packagePath1 = convertPath('/package1'); + filePath1 = join(packagePath1, 'lib', 'test.dart'); + newFile(filePath1); contextRoot1 = new ContextRoot(packagePath1, <String>[]); channel = new MockChannel(); @@ -93,7 +87,7 @@ @override Future<HighlightsRequest> getHighlightsRequest(String path) async { - AnalysisResult result = new MockAnalysisResult(path: path); + var result = new MockResolvedUnitResult(path: path); return new DartHighlightsRequestImpl(resourceProvider, result); } }
diff --git a/pkg/analyzer_plugin/test/plugin/kythe_mixin_test.dart b/pkg/analyzer_plugin/test/plugin/kythe_mixin_test.dart index 0ce5e0a..63f0f63 100644 --- a/pkg/analyzer_plugin/test/plugin/kythe_mixin_test.dart +++ b/pkg/analyzer_plugin/test/plugin/kythe_mixin_test.dart
@@ -5,14 +5,12 @@ import 'dart:async'; import 'package:analyzer/file_system/file_system.dart'; -import 'package:analyzer/file_system/memory_file_system.dart'; -import 'package:analyzer/src/dart/analysis/driver.dart'; +import 'package:analyzer/src/test_utilities/resource_provider_mixin.dart'; import 'package:analyzer_plugin/plugin/kythe_mixin.dart'; import 'package:analyzer_plugin/protocol/protocol_common.dart'; import 'package:analyzer_plugin/protocol/protocol_generated.dart'; import 'package:analyzer_plugin/src/utilities/kythe/entries.dart'; import 'package:analyzer_plugin/utilities/kythe/entries.dart'; -import 'package:path/src/context.dart'; import 'package:test/test.dart'; import 'package:test_reflective_loader/test_reflective_loader.dart'; @@ -23,9 +21,7 @@ } @reflectiveTest -class KytheMixinTest { - MemoryResourceProvider resourceProvider = new MemoryResourceProvider(); - +class KytheMixinTest with ResourceProviderMixin { String packagePath1; String filePath1; ContextRoot contextRoot1; @@ -34,11 +30,9 @@ _TestServerPlugin plugin; void setUp() { - Context pathContext = resourceProvider.pathContext; - - packagePath1 = resourceProvider.convertPath('/package1'); - filePath1 = pathContext.join(packagePath1, 'lib', 'test.dart'); - resourceProvider.newFile(filePath1, ''); + packagePath1 = convertPath('/package1'); + filePath1 = join(packagePath1, 'lib', 'test.dart'); + newFile(filePath1); contextRoot1 = new ContextRoot(packagePath1, <String>[]); channel = new MockChannel(); @@ -94,7 +88,7 @@ @override Future<EntryRequest> getEntryRequest( KytheGetKytheEntriesParams parameters) async { - AnalysisResult result = new MockAnalysisResult(); + var result = new MockResolvedUnitResult(); return new DartEntryRequestImpl(resourceProvider, result); } }
diff --git a/pkg/analyzer_plugin/test/plugin/mocks.dart b/pkg/analyzer_plugin/test/plugin/mocks.dart index 3e7d651..79bb3bb 100644 --- a/pkg/analyzer_plugin/test/plugin/mocks.dart +++ b/pkg/analyzer_plugin/test/plugin/mocks.dart
@@ -5,6 +5,7 @@ import 'dart:async'; import 'dart:collection'; +import 'package:analyzer/dart/analysis/results.dart'; import 'package:analyzer/error/error.dart'; import 'package:analyzer/file_system/file_system.dart'; import 'package:analyzer/src/dart/analysis/driver.dart'; @@ -56,22 +57,6 @@ Future<Null> performWork() => new Future.value(null); } -class MockAnalysisResult implements AnalysisResult { - @override - final List<AnalysisError> errors; - - @override - final LineInfo lineInfo; - - @override - final String path; - - MockAnalysisResult({this.errors, this.lineInfo, this.path}); - - @override - noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation); -} - class MockChannel implements PluginCommunicationChannel { bool _closed = false; @@ -143,6 +128,22 @@ } } +class MockResolvedUnitResult implements ResolvedUnitResult { + @override + final List<AnalysisError> errors; + + @override + final LineInfo lineInfo; + + @override + final String path; + + MockResolvedUnitResult({this.errors, this.lineInfo, this.path}); + + @override + noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation); +} + class MockResourceProvider implements ResourceProvider { @override noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
diff --git a/pkg/analyzer_plugin/test/plugin/navigation_mixin_test.dart b/pkg/analyzer_plugin/test/plugin/navigation_mixin_test.dart index 7996888..f4f2ffa 100644 --- a/pkg/analyzer_plugin/test/plugin/navigation_mixin_test.dart +++ b/pkg/analyzer_plugin/test/plugin/navigation_mixin_test.dart
@@ -5,15 +5,13 @@ import 'dart:async'; import 'package:analyzer/file_system/file_system.dart'; -import 'package:analyzer/file_system/memory_file_system.dart'; -import 'package:analyzer/src/dart/analysis/driver.dart'; +import 'package:analyzer/src/test_utilities/resource_provider_mixin.dart'; import 'package:analyzer_plugin/plugin/navigation_mixin.dart'; import 'package:analyzer_plugin/protocol/protocol.dart'; import 'package:analyzer_plugin/protocol/protocol_common.dart'; import 'package:analyzer_plugin/protocol/protocol_generated.dart'; import 'package:analyzer_plugin/src/utilities/navigation/navigation.dart'; import 'package:analyzer_plugin/utilities/navigation/navigation.dart'; -import 'package:path/src/context.dart'; import 'package:test/test.dart'; import 'package:test_reflective_loader/test_reflective_loader.dart'; @@ -24,9 +22,7 @@ } @reflectiveTest -class NavigationMixinTest { - MemoryResourceProvider resourceProvider = new MemoryResourceProvider(); - +class NavigationMixinTest with ResourceProviderMixin { String packagePath1; String filePath1; ContextRoot contextRoot1; @@ -35,11 +31,9 @@ _TestServerPlugin plugin; void setUp() { - Context pathContext = resourceProvider.pathContext; - - packagePath1 = resourceProvider.convertPath('/package1'); - filePath1 = pathContext.join(packagePath1, 'lib', 'test.dart'); - resourceProvider.newFile(filePath1, ''); + packagePath1 = convertPath('/package1'); + filePath1 = join(packagePath1, 'lib', 'test.dart'); + newFile(filePath1); contextRoot1 = new ContextRoot(packagePath1, <String>[]); channel = new MockChannel(); @@ -109,7 +103,7 @@ @override Future<NavigationRequest> getNavigationRequest( AnalysisGetNavigationParams parameters) async { - AnalysisResult result = new MockAnalysisResult(path: parameters.file); + var result = new MockResolvedUnitResult(path: parameters.file); return new DartNavigationRequestImpl( resourceProvider, parameters.offset, parameters.length, result); }
diff --git a/pkg/analyzer_plugin/test/plugin/occurrences_mixin_test.dart b/pkg/analyzer_plugin/test/plugin/occurrences_mixin_test.dart index 6555427..cf2b96f 100644 --- a/pkg/analyzer_plugin/test/plugin/occurrences_mixin_test.dart +++ b/pkg/analyzer_plugin/test/plugin/occurrences_mixin_test.dart
@@ -5,15 +5,13 @@ import 'dart:async'; import 'package:analyzer/file_system/file_system.dart'; -import 'package:analyzer/file_system/memory_file_system.dart'; -import 'package:analyzer/src/dart/analysis/driver.dart'; +import 'package:analyzer/src/test_utilities/resource_provider_mixin.dart'; import 'package:analyzer_plugin/plugin/occurrences_mixin.dart'; import 'package:analyzer_plugin/protocol/protocol.dart'; import 'package:analyzer_plugin/protocol/protocol_common.dart'; import 'package:analyzer_plugin/protocol/protocol_generated.dart'; import 'package:analyzer_plugin/src/utilities/occurrences/occurrences.dart'; import 'package:analyzer_plugin/utilities/occurrences/occurrences.dart'; -import 'package:path/src/context.dart'; import 'package:test/test.dart'; import 'package:test_reflective_loader/test_reflective_loader.dart'; @@ -24,9 +22,7 @@ } @reflectiveTest -class OccurrencesMixinTest { - MemoryResourceProvider resourceProvider = new MemoryResourceProvider(); - +class OccurrencesMixinTest with ResourceProviderMixin { String packagePath1; String filePath1; ContextRoot contextRoot1; @@ -35,11 +31,9 @@ _TestServerPlugin plugin; void setUp() { - Context pathContext = resourceProvider.pathContext; - - packagePath1 = resourceProvider.convertPath('/package1'); - filePath1 = pathContext.join(packagePath1, 'lib', 'test.dart'); - resourceProvider.newFile(filePath1, ''); + packagePath1 = convertPath('/package1'); + filePath1 = join(packagePath1, 'lib', 'test.dart'); + newFile(filePath1); contextRoot1 = new ContextRoot(packagePath1, <String>[]); channel = new MockChannel(); @@ -120,7 +114,7 @@ @override Future<OccurrencesRequest> getOccurrencesRequest(String path) async { - AnalysisResult result = new MockAnalysisResult(path: path); + var result = new MockResolvedUnitResult(path: path); return new DartOccurrencesRequestImpl(resourceProvider, result); } }
diff --git a/pkg/analyzer_plugin/test/plugin/outline_mixin_test.dart b/pkg/analyzer_plugin/test/plugin/outline_mixin_test.dart index 2ac58ad..cd15cfa 100644 --- a/pkg/analyzer_plugin/test/plugin/outline_mixin_test.dart +++ b/pkg/analyzer_plugin/test/plugin/outline_mixin_test.dart
@@ -5,15 +5,13 @@ import 'dart:async'; import 'package:analyzer/file_system/file_system.dart'; -import 'package:analyzer/file_system/memory_file_system.dart'; -import 'package:analyzer/src/dart/analysis/driver.dart'; +import 'package:analyzer/src/test_utilities/resource_provider_mixin.dart'; import 'package:analyzer_plugin/plugin/outline_mixin.dart'; import 'package:analyzer_plugin/protocol/protocol.dart'; import 'package:analyzer_plugin/protocol/protocol_common.dart'; import 'package:analyzer_plugin/protocol/protocol_generated.dart'; import 'package:analyzer_plugin/src/utilities/outline/outline.dart'; import 'package:analyzer_plugin/utilities/outline/outline.dart'; -import 'package:path/src/context.dart'; import 'package:test/test.dart'; import 'package:test_reflective_loader/test_reflective_loader.dart'; @@ -24,9 +22,7 @@ } @reflectiveTest -class OutlineMixinTest { - MemoryResourceProvider resourceProvider = new MemoryResourceProvider(); - +class OutlineMixinTest with ResourceProviderMixin { String packagePath1; String filePath1; ContextRoot contextRoot1; @@ -35,11 +31,9 @@ _TestServerPlugin plugin; void setUp() { - Context pathContext = resourceProvider.pathContext; - - packagePath1 = resourceProvider.convertPath('/package1'); - filePath1 = pathContext.join(packagePath1, 'lib', 'test.dart'); - resourceProvider.newFile(filePath1, ''); + packagePath1 = convertPath('/package1'); + filePath1 = join(packagePath1, 'lib', 'test.dart'); + newFile(filePath1); contextRoot1 = new ContextRoot(packagePath1, <String>[]); channel = new MockChannel(); @@ -94,7 +88,7 @@ @override Future<OutlineRequest> getOutlineRequest(String path) async { - AnalysisResult result = new MockAnalysisResult(path: path); + var result = new MockResolvedUnitResult(path: path); return new DartOutlineRequestImpl(resourceProvider, result); } }
diff --git a/pkg/analyzer_plugin/test/plugin/plugin_test.dart b/pkg/analyzer_plugin/test/plugin/plugin_test.dart index 0356e77..118f33e 100644 --- a/pkg/analyzer_plugin/test/plugin/plugin_test.dart +++ b/pkg/analyzer_plugin/test/plugin/plugin_test.dart
@@ -5,12 +5,11 @@ import 'dart:async'; import 'package:analyzer/file_system/file_system.dart'; -import 'package:analyzer/file_system/memory_file_system.dart'; import 'package:analyzer/src/dart/analysis/driver.dart'; +import 'package:analyzer/src/test_utilities/resource_provider_mixin.dart'; import 'package:analyzer_plugin/protocol/protocol.dart'; import 'package:analyzer_plugin/protocol/protocol_common.dart'; import 'package:analyzer_plugin/protocol/protocol_generated.dart'; -import 'package:path/src/context.dart'; import 'package:test/test.dart'; import 'package:test_reflective_loader/test_reflective_loader.dart'; @@ -21,9 +20,7 @@ } @reflectiveTest -class ServerPluginTest { - MemoryResourceProvider resourceProvider = new MemoryResourceProvider(); - +class ServerPluginTest with ResourceProviderMixin { MockChannel channel; _TestServerPlugin plugin; @@ -36,16 +33,14 @@ ContextRoot contextRoot2; void setUp() { - Context pathContext = resourceProvider.pathContext; - - packagePath1 = resourceProvider.convertPath('/package1'); - filePath1 = pathContext.join(packagePath1, 'lib', 'test.dart'); - resourceProvider.newFile(filePath1, ''); + packagePath1 = convertPath('/package1'); + filePath1 = join(packagePath1, 'lib', 'test.dart'); + newFile(filePath1); contextRoot1 = new ContextRoot(packagePath1, <String>[]); - packagePath2 = resourceProvider.convertPath('/package2'); - filePath2 = pathContext.join(packagePath2, 'lib', 'test.dart'); - resourceProvider.newFile(filePath2, ''); + packagePath2 = convertPath('/package2'); + filePath2 = join(packagePath2, 'lib', 'test.dart'); + newFile(filePath2); contextRoot2 = new ContextRoot(packagePath2, <String>[]); channel = new MockChannel();
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 0f8e505..34ec98d 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
@@ -4,14 +4,12 @@ import 'dart:async'; +import 'package:analyzer/dart/analysis/results.dart'; import 'package:analyzer/dart/ast/ast.dart'; import 'package:analyzer/dart/ast/standard_resolution_map.dart'; import 'package:analyzer/dart/element/element.dart'; import 'package:analyzer/dart/element/type.dart'; -import 'package:analyzer/src/context/source.dart'; -import 'package:analyzer/src/dart/analysis/driver.dart'; import 'package:analyzer/src/dart/element/inheritance_manager2.dart'; -import 'package:analyzer/src/generated/engine.dart'; import 'package:analyzer/src/generated/resolver.dart'; import 'package:analyzer/src/generated/source.dart'; import 'package:analyzer/src/generated/testing/test_type_provider.dart'; @@ -33,7 +31,7 @@ }); } -abstract class BuilderTestMixin { +mixin BuilderTestMixin implements AbstractContextTest { SourceEdit getEdit(DartChangeBuilder builder) { SourceChange sourceChange = builder.sourceChange; expect(sourceChange, isNotNull); @@ -55,14 +53,19 @@ expect(fileEdit, isNotNull); return fileEdit.edits; } + + /// Return a newly created Dart change builder. + DartChangeBuilderImpl newBuilder() => + new DartChangeBuilder(session) as DartChangeBuilderImpl; } @reflectiveTest -class DartChangeBuilderImplTest extends AbstractContextTest { +class DartChangeBuilderImplTest extends AbstractContextTest + with BuilderTestMixin { test_createFileEditBuilder() async { - String path = provider.convertPath('/test.dart'); + String path = convertPath('/test.dart'); addSource(path, 'library test;'); - DartChangeBuilderImpl builder = new DartChangeBuilder(session); + DartChangeBuilderImpl builder = newBuilder(); DartFileEditBuilderImpl fileEditBuilder = await builder.createFileEditBuilder(path); expect(fileEditBuilder, const TypeMatcher<DartFileEditBuilder>()); @@ -387,11 +390,11 @@ } test_writeClassDeclaration_interfaces() async { - String path = provider.convertPath('/test.dart'); + String path = convertPath('/test.dart'); addSource(path, 'class A {}'); DartType typeA = await _getType(path, 'A'); - DartChangeBuilderImpl builder = new DartChangeBuilder(session); + DartChangeBuilderImpl builder = newBuilder(); await builder.addFileEdit(path, (FileEditBuilder builder) { builder.addInsertion(0, (EditBuilder builder) { (builder as DartEditBuilder) @@ -404,10 +407,10 @@ } test_writeClassDeclaration_isAbstract() async { - String path = provider.convertPath('/test.dart'); + String path = convertPath('/test.dart'); addSource(path, ''); - DartChangeBuilderImpl builder = new DartChangeBuilder(session); + DartChangeBuilderImpl builder = newBuilder(); await builder.addFileEdit(path, (FileEditBuilder builder) { builder.addInsertion(0, (EditBuilder builder) { (builder as DartEditBuilder) @@ -419,10 +422,10 @@ } test_writeClassDeclaration_memberWriter() async { - String path = provider.convertPath('/test.dart'); + String path = convertPath('/test.dart'); addSource(path, ''); - DartChangeBuilderImpl builder = new DartChangeBuilder(session); + DartChangeBuilderImpl builder = newBuilder(); await builder.addFileEdit(path, (FileEditBuilder builder) { builder.addInsertion(0, (EditBuilder builder) { (builder as DartEditBuilder).writeClassDeclaration('C', @@ -436,11 +439,11 @@ } test_writeClassDeclaration_mixins_noSuperclass() async { - String path = provider.convertPath('/test.dart'); + String path = convertPath('/test.dart'); addSource(path, 'class A {}'); DartType typeA = await _getType(path, 'A'); - DartChangeBuilderImpl builder = new DartChangeBuilder(session); + DartChangeBuilderImpl builder = newBuilder(); await builder.addFileEdit(path, (FileEditBuilder builder) { builder.addInsertion(0, (EditBuilder builder) { (builder as DartEditBuilder) @@ -453,12 +456,12 @@ } test_writeClassDeclaration_mixins_superclass() async { - String path = provider.convertPath('/test.dart'); + String path = convertPath('/test.dart'); addSource(path, 'class A {} class B {}'); DartType typeA = await _getType(path, 'A'); DartType typeB = await _getType(path, 'B'); - DartChangeBuilderImpl builder = new DartChangeBuilder(session); + DartChangeBuilderImpl builder = newBuilder(); await builder.addFileEdit(path, (FileEditBuilder builder) { builder.addInsertion(0, (EditBuilder builder) { (builder as DartEditBuilder) @@ -471,10 +474,10 @@ } test_writeClassDeclaration_nameGroupName() async { - String path = provider.convertPath('/test.dart'); + String path = convertPath('/test.dart'); addSource(path, ''); - DartChangeBuilderImpl builder = new DartChangeBuilder(session); + DartChangeBuilderImpl builder = newBuilder(); await builder.addFileEdit(path, (FileEditBuilder builder) { builder.addInsertion(0, (EditBuilder builder) { (builder as DartEditBuilder) @@ -493,11 +496,11 @@ } test_writeClassDeclaration_superclass() async { - String path = provider.convertPath('/test.dart'); + String path = convertPath('/test.dart'); addSource(path, 'class B {}'); DartType typeB = await _getType(path, 'B'); - DartChangeBuilderImpl builder = new DartChangeBuilder(session); + DartChangeBuilderImpl builder = newBuilder(); await builder.addFileEdit(path, (FileEditBuilder builder) { builder.addInsertion(0, (EditBuilder builder) { (builder as DartEditBuilder).writeClassDeclaration('C', @@ -516,10 +519,10 @@ } test_writeConstructorDeclaration_bodyWriter() async { - String path = provider.convertPath('/test.dart'); + String path = convertPath('/test.dart'); addSource(path, 'class C {}'); - DartChangeBuilderImpl builder = new DartChangeBuilder(session); + DartChangeBuilderImpl builder = newBuilder(); await builder.addFileEdit(path, (DartFileEditBuilder builder) { builder.addInsertion(9, (DartEditBuilder builder) { builder.writeConstructorDeclaration('A', bodyWriter: () { @@ -532,7 +535,7 @@ } test_writeConstructorDeclaration_fieldNames() async { - String path = provider.convertPath('/test.dart'); + String path = convertPath('/test.dart'); addSource(path, r''' class C { final int a; @@ -540,7 +543,7 @@ } '''); - DartChangeBuilderImpl builder = new DartChangeBuilder(session); + DartChangeBuilderImpl builder = newBuilder(); await builder.addFileEdit(path, (DartFileEditBuilder builder) { builder.addInsertion(42, (DartEditBuilder builder) { builder.writeConstructorDeclaration('A', fieldNames: ['a', 'bb']); @@ -551,10 +554,10 @@ } test_writeConstructorDeclaration_initializerWriter() async { - String path = provider.convertPath('/test.dart'); + String path = convertPath('/test.dart'); addSource(path, 'class C {}'); - DartChangeBuilderImpl builder = new DartChangeBuilder(session); + DartChangeBuilderImpl builder = newBuilder(); await builder.addFileEdit(path, (DartFileEditBuilder builder) { builder.addInsertion(9, (DartEditBuilder builder) { builder.writeConstructorDeclaration('A', initializerWriter: () { @@ -567,10 +570,10 @@ } test_writeConstructorDeclaration_parameterWriter() async { - String path = provider.convertPath('/test.dart'); + String path = convertPath('/test.dart'); addSource(path, 'class C {}'); - DartChangeBuilderImpl builder = new DartChangeBuilder(session); + DartChangeBuilderImpl builder = newBuilder(); await builder.addFileEdit(path, (DartFileEditBuilder builder) { builder.addInsertion(9, (DartEditBuilder builder) { builder.writeConstructorDeclaration('A', parameterWriter: () { @@ -583,11 +586,11 @@ } test_writeFieldDeclaration_initializerWriter() async { - String path = provider.convertPath('/test.dart'); + String path = convertPath('/test.dart'); String content = 'class A {}'; addSource(path, content); - DartChangeBuilderImpl builder = new DartChangeBuilder(session); + DartChangeBuilderImpl builder = newBuilder(); await builder.addFileEdit(path, (FileEditBuilder builder) { builder.addInsertion(content.length - 1, (EditBuilder builder) { (builder as DartEditBuilder).writeFieldDeclaration('f', @@ -601,11 +604,11 @@ } test_writeFieldDeclaration_isConst() async { - String path = provider.convertPath('/test.dart'); + String path = convertPath('/test.dart'); String content = 'class A {}'; addSource(path, content); - DartChangeBuilderImpl builder = new DartChangeBuilder(session); + DartChangeBuilderImpl builder = newBuilder(); await builder.addFileEdit(path, (FileEditBuilder builder) { builder.addInsertion(content.length - 1, (EditBuilder builder) { (builder as DartEditBuilder).writeFieldDeclaration('f', isConst: true); @@ -616,11 +619,11 @@ } test_writeFieldDeclaration_isConst_isFinal() async { - String path = provider.convertPath('/test.dart'); + String path = convertPath('/test.dart'); String content = 'class A {}'; addSource(path, content); - DartChangeBuilderImpl builder = new DartChangeBuilder(session); + DartChangeBuilderImpl builder = newBuilder(); await builder.addFileEdit(path, (FileEditBuilder builder) { builder.addInsertion(content.length - 1, (EditBuilder builder) { (builder as DartEditBuilder) @@ -632,12 +635,12 @@ } test_writeFieldDeclaration_isConst_type() async { - String path = provider.convertPath('/test.dart'); + String path = convertPath('/test.dart'); String content = 'class A {}'; addSource(path, content); DartType typeA = await _getType(path, 'A'); - DartChangeBuilderImpl builder = new DartChangeBuilder(session); + DartChangeBuilderImpl builder = newBuilder(); await builder.addFileEdit(path, (FileEditBuilder builder) { builder.addInsertion(content.length - 1, (EditBuilder builder) { (builder as DartEditBuilder) @@ -649,11 +652,11 @@ } test_writeFieldDeclaration_isFinal() async { - String path = provider.convertPath('/test.dart'); + String path = convertPath('/test.dart'); String content = 'class A {}'; addSource(path, content); - DartChangeBuilderImpl builder = new DartChangeBuilder(session); + DartChangeBuilderImpl builder = newBuilder(); await builder.addFileEdit(path, (FileEditBuilder builder) { builder.addInsertion(content.length - 1, (EditBuilder builder) { (builder as DartEditBuilder).writeFieldDeclaration('f', isFinal: true); @@ -664,12 +667,12 @@ } test_writeFieldDeclaration_isFinal_type() async { - String path = provider.convertPath('/test.dart'); + String path = convertPath('/test.dart'); String content = 'class A {}'; addSource(path, content); DartType typeA = await _getType(path, 'A'); - DartChangeBuilderImpl builder = new DartChangeBuilder(session); + DartChangeBuilderImpl builder = newBuilder(); await builder.addFileEdit(path, (FileEditBuilder builder) { builder.addInsertion(content.length - 1, (EditBuilder builder) { (builder as DartEditBuilder) @@ -681,11 +684,11 @@ } test_writeFieldDeclaration_isStatic() async { - String path = provider.convertPath('/test.dart'); + String path = convertPath('/test.dart'); String content = 'class A {}'; addSource(path, content); - DartChangeBuilderImpl builder = new DartChangeBuilder(session); + DartChangeBuilderImpl builder = newBuilder(); await builder.addFileEdit(path, (FileEditBuilder builder) { builder.addInsertion(content.length - 1, (EditBuilder builder) { (builder as DartEditBuilder).writeFieldDeclaration('f', isStatic: true); @@ -696,11 +699,11 @@ } test_writeFieldDeclaration_nameGroupName() async { - String path = provider.convertPath('/test.dart'); + String path = convertPath('/test.dart'); String content = 'class A {}'; addSource(path, content); - DartChangeBuilderImpl builder = new DartChangeBuilder(session); + DartChangeBuilderImpl builder = newBuilder(); await builder.addFileEdit(path, (FileEditBuilder builder) { builder.addInsertion(content.length - 1, (EditBuilder builder) { (builder as DartEditBuilder) @@ -721,12 +724,12 @@ } test_writeFieldDeclaration_type_typeGroupName() async { - String path = provider.convertPath('/test.dart'); + String path = convertPath('/test.dart'); String content = 'class A {} class B {}'; addSource(path, content); DartType typeA = await _getType(path, 'A'); - DartChangeBuilderImpl builder = new DartChangeBuilder(session); + DartChangeBuilderImpl builder = newBuilder(); await builder.addFileEdit(path, (FileEditBuilder builder) { builder.addInsertion(content.length - 1, (EditBuilder builder) { (builder as DartEditBuilder) @@ -747,11 +750,11 @@ } test_writeFunctionDeclaration_noReturnType_noParams_body() async { - String path = provider.convertPath('/test.dart'); + String path = convertPath('/test.dart'); String content = ''; addSource(path, content); - DartChangeBuilderImpl builder = new DartChangeBuilder(session); + DartChangeBuilderImpl builder = newBuilder(); await builder.addFileEdit(path, (FileEditBuilder builder) { builder.addInsertion(0, (EditBuilder builder) { (builder as DartEditBuilder).writeFunctionDeclaration('fib', @@ -765,11 +768,11 @@ } test_writeFunctionDeclaration_noReturnType_noParams_noBody() async { - String path = provider.convertPath('/test.dart'); + String path = convertPath('/test.dart'); String content = ''; addSource(path, content); - DartChangeBuilderImpl builder = new DartChangeBuilder(session); + DartChangeBuilderImpl builder = newBuilder(); await builder.addFileEdit(path, (FileEditBuilder builder) { builder.addInsertion(0, (EditBuilder builder) { (builder as DartEditBuilder) @@ -788,11 +791,11 @@ } test_writeFunctionDeclaration_noReturnType_params_noBody() async { - String path = provider.convertPath('/test.dart'); + String path = convertPath('/test.dart'); String content = ''; addSource(path, content); - DartChangeBuilderImpl builder = new DartChangeBuilder(session); + DartChangeBuilderImpl builder = newBuilder(); await builder.addFileEdit(path, (FileEditBuilder builder) { builder.addInsertion(0, (EditBuilder builder) { (builder as DartEditBuilder).writeFunctionDeclaration('fib', @@ -806,13 +809,13 @@ } test_writeFunctionDeclaration_returnType_noParams_noBody() async { - String path = provider.convertPath('/test.dart'); + String path = convertPath('/test.dart'); String content = 'class A {}'; addSource(path, content); DartType typeA = await _getType(path, 'A'); - DartChangeBuilderImpl builder = new DartChangeBuilder(session); + DartChangeBuilderImpl builder = newBuilder(); await builder.addFileEdit(path, (FileEditBuilder builder) { builder.addInsertion(0, (EditBuilder builder) { (builder as DartEditBuilder).writeFunctionDeclaration('fib', @@ -831,11 +834,11 @@ } test_writeGetterDeclaration_bodyWriter() async { - String path = provider.convertPath('/test.dart'); + String path = convertPath('/test.dart'); String content = 'class A {}'; addSource(path, content); - DartChangeBuilderImpl builder = new DartChangeBuilder(session); + DartChangeBuilderImpl builder = newBuilder(); await builder.addFileEdit(path, (FileEditBuilder builder) { builder.addInsertion(content.length - 1, (EditBuilder builder) { (builder as DartEditBuilder).writeGetterDeclaration('g', @@ -849,11 +852,11 @@ } test_writeGetterDeclaration_isStatic() async { - String path = provider.convertPath('/test.dart'); + String path = convertPath('/test.dart'); String content = 'class A {}'; addSource(path, content); - DartChangeBuilderImpl builder = new DartChangeBuilder(session); + DartChangeBuilderImpl builder = newBuilder(); await builder.addFileEdit(path, (FileEditBuilder builder) { builder.addInsertion(content.length - 1, (EditBuilder builder) { (builder as DartEditBuilder) @@ -865,11 +868,11 @@ } test_writeGetterDeclaration_nameGroupName() async { - String path = provider.convertPath('/test.dart'); + String path = convertPath('/test.dart'); String content = 'class A {}'; addSource(path, content); - DartChangeBuilderImpl builder = new DartChangeBuilder(session); + DartChangeBuilderImpl builder = newBuilder(); await builder.addFileEdit(path, (FileEditBuilder builder) { builder.addInsertion(content.length - 1, (EditBuilder builder) { (builder as DartEditBuilder) @@ -890,12 +893,12 @@ } test_writeGetterDeclaration_returnType() async { - String path = provider.convertPath('/test.dart'); + String path = convertPath('/test.dart'); String content = 'class A {} class B {}'; addSource(path, content); DartType typeA = await _getType(path, 'A'); - DartChangeBuilderImpl builder = new DartChangeBuilder(session); + DartChangeBuilderImpl builder = newBuilder(); await builder.addFileEdit(path, (FileEditBuilder builder) { builder.addInsertion(content.length - 1, (EditBuilder builder) { (builder as DartEditBuilder).writeGetterDeclaration('g', @@ -916,7 +919,7 @@ } test_writeLocalVariableDeclaration_noType_initializer() async { - String path = provider.convertPath('/test.dart'); + String path = convertPath('/test.dart'); String content = ''' void f() { @@ -924,7 +927,7 @@ addSource(path, content); await driver.getResult(path); - DartChangeBuilderImpl builder = new DartChangeBuilder(session); + DartChangeBuilderImpl builder = newBuilder(); await builder.addFileEdit(path, (FileEditBuilder builder) { builder.addInsertion(11, (EditBuilder builder) { (builder as DartEditBuilder).writeLocalVariableDeclaration('foo', @@ -938,7 +941,7 @@ } test_writeLocalVariableDeclaration_noType_noInitializer() async { - String path = provider.convertPath('/test.dart'); + String path = convertPath('/test.dart'); String content = ''' void f() { @@ -946,7 +949,7 @@ addSource(path, content); await driver.getResult(path); - DartChangeBuilderImpl builder = new DartChangeBuilder(session); + DartChangeBuilderImpl builder = newBuilder(); await builder.addFileEdit(path, (FileEditBuilder builder) { builder.addInsertion(11, (EditBuilder builder) { (builder as DartEditBuilder) @@ -965,7 +968,7 @@ } test_writeLocalVariableDeclaration_noType_noInitializer_const() async { - String path = provider.convertPath('/test.dart'); + String path = convertPath('/test.dart'); String content = ''' void f() { @@ -973,7 +976,7 @@ addSource(path, content); await driver.getResult(path); - DartChangeBuilderImpl builder = new DartChangeBuilder(session); + DartChangeBuilderImpl builder = newBuilder(); await builder.addFileEdit(path, (FileEditBuilder builder) { builder.addInsertion(11, (EditBuilder builder) { (builder as DartEditBuilder) @@ -985,7 +988,7 @@ } test_writeLocalVariableDeclaration_noType_noInitializer_final() async { - String path = provider.convertPath('/test.dart'); + String path = convertPath('/test.dart'); String content = ''' void f() { @@ -993,7 +996,7 @@ addSource(path, content); await driver.getResult(path); - DartChangeBuilderImpl builder = new DartChangeBuilder(session); + DartChangeBuilderImpl builder = newBuilder(); await builder.addFileEdit(path, (FileEditBuilder builder) { builder.addInsertion(11, (EditBuilder builder) { (builder as DartEditBuilder) @@ -1005,7 +1008,7 @@ } test_writeLocalVariableDeclaration_type_initializer() async { - String path = provider.convertPath('/test.dart'); + String path = convertPath('/test.dart'); String content = ''' void f() { @@ -1014,9 +1017,9 @@ addSource(path, content); CompilationUnit unit = (await driver.getResult(path))?.unit; - ClassDeclaration A = unit.declarations[1]; + ClassDeclaration A = unit.declarations[1] as ClassDeclaration; - DartChangeBuilderImpl builder = new DartChangeBuilder(session); + DartChangeBuilderImpl builder = newBuilder(); await builder.addFileEdit(path, (FileEditBuilder builder) { builder.addInsertion(11, (EditBuilder builder) { (builder as DartEditBuilder).writeLocalVariableDeclaration('foo', @@ -1030,7 +1033,7 @@ } test_writeLocalVariableDeclaration_type_noInitializer() async { - String path = provider.convertPath('/test.dart'); + String path = convertPath('/test.dart'); String content = ''' void f() { @@ -1039,9 +1042,9 @@ addSource(path, content); CompilationUnit unit = (await driver.getResult(path))?.unit; - ClassDeclaration A = unit.declarations[1]; + ClassDeclaration A = unit.declarations[1] as ClassDeclaration; - DartChangeBuilderImpl builder = new DartChangeBuilder(session); + DartChangeBuilderImpl builder = newBuilder(); await builder.addFileEdit(path, (FileEditBuilder builder) { builder.addInsertion(11, (EditBuilder builder) { (builder as DartEditBuilder).writeLocalVariableDeclaration('foo', @@ -1060,7 +1063,7 @@ } test_writeLocalVariableDeclaration_type_noInitializer_final() async { - String path = provider.convertPath('/test.dart'); + String path = convertPath('/test.dart'); String content = ''' void f() { @@ -1069,9 +1072,9 @@ addSource(path, content); CompilationUnit unit = (await driver.getResult(path))?.unit; - ClassDeclaration A = unit.declarations[1]; + ClassDeclaration A = unit.declarations[1] as ClassDeclaration; - DartChangeBuilderImpl builder = new DartChangeBuilder(session); + DartChangeBuilderImpl builder = newBuilder(); await builder.addFileEdit(path, (FileEditBuilder builder) { builder.addInsertion(11, (EditBuilder builder) { (builder as DartEditBuilder).writeLocalVariableDeclaration('foo', @@ -1090,11 +1093,11 @@ } test_writeMixinDeclaration_interfaces() async { - String path = provider.convertPath('/test.dart'); + String path = convertPath('/test.dart'); addSource(path, 'class A {}'); DartType typeA = await _getType(path, 'A'); - DartChangeBuilderImpl builder = new DartChangeBuilder(session); + DartChangeBuilderImpl builder = newBuilder(); await builder.addFileEdit(path, (FileEditBuilder builder) { builder.addInsertion(0, (EditBuilder builder) { (builder as DartEditBuilder) @@ -1107,12 +1110,12 @@ } test_writeMixinDeclaration_interfacesAndSuperclassConstraints() async { - String path = provider.convertPath('/test.dart'); + String path = convertPath('/test.dart'); addSource(path, 'class A {} class B {}'); DartType typeA = await _getType(path, 'A'); DartType typeB = await _getType(path, 'B'); - DartChangeBuilderImpl builder = new DartChangeBuilder(session); + DartChangeBuilderImpl builder = newBuilder(); await builder.addFileEdit(path, (FileEditBuilder builder) { builder.addInsertion(0, (EditBuilder builder) { (builder as DartEditBuilder).writeMixinDeclaration('M', @@ -1125,10 +1128,10 @@ } test_writeMixinDeclaration_memberWriter() async { - String path = provider.convertPath('/test.dart'); + String path = convertPath('/test.dart'); addSource(path, ''); - DartChangeBuilderImpl builder = new DartChangeBuilder(session); + DartChangeBuilderImpl builder = newBuilder(); await builder.addFileEdit(path, (FileEditBuilder builder) { builder.addInsertion(0, (EditBuilder builder) { (builder as DartEditBuilder).writeMixinDeclaration('M', @@ -1142,10 +1145,10 @@ } test_writeMixinDeclaration_nameGroupName() async { - String path = provider.convertPath('/test.dart'); + String path = convertPath('/test.dart'); addSource(path, ''); - DartChangeBuilderImpl builder = new DartChangeBuilder(session); + DartChangeBuilderImpl builder = newBuilder(); await builder.addFileEdit(path, (FileEditBuilder builder) { builder.addInsertion(0, (EditBuilder builder) { (builder as DartEditBuilder) @@ -1164,11 +1167,11 @@ } test_writeMixinDeclaration_superclassConstraints() async { - String path = provider.convertPath('/test.dart'); + String path = convertPath('/test.dart'); addSource(path, 'class A {}'); DartType typeA = await _getType(path, 'A'); - DartChangeBuilderImpl builder = new DartChangeBuilder(session); + DartChangeBuilderImpl builder = newBuilder(); await builder.addFileEdit(path, (FileEditBuilder builder) { builder.addInsertion(0, (EditBuilder builder) { (builder as DartEditBuilder) @@ -1529,6 +1532,27 @@ ); } + test_writeOverride_method_returnVoid_abstract() async { + await _assertWriteOverride( + content: ''' +abstract class A { + void test(); +} +class B extends A { +} +''', + nameToOverride: 'test', + expected: ''' + @override + void test() { + // TODO: implement test + } +''', + displayText: 'test() { … }', + selection: new SourceRange(109, 0), + ); + } + test_writeOverride_method_voidAsTypeArgument_abstract() async { await _assertWriteOverride( content: ''' @@ -1590,6 +1614,7 @@ } ''', displayText: 'value(int value) { … }', + selection: new SourceRange(133, 0), ); } @@ -1616,11 +1641,11 @@ } test_writeParameter() async { - String path = provider.convertPath('/test.dart'); + String path = convertPath('/test.dart'); String content = 'class A {}'; addSource(path, content); - DartChangeBuilderImpl builder = new DartChangeBuilder(session); + DartChangeBuilderImpl builder = newBuilder(); await builder.addFileEdit(path, (FileEditBuilder builder) { builder.addInsertion(content.length - 1, (EditBuilder builder) { (builder as DartEditBuilder).writeParameter('a'); @@ -1631,12 +1656,12 @@ } test_writeParameter_type() async { - String path = provider.convertPath('/test.dart'); + String path = convertPath('/test.dart'); String content = 'class A {}'; addSource(path, content); DartType typeA = await _getType(path, 'A'); - DartChangeBuilderImpl builder = new DartChangeBuilder(session); + DartChangeBuilderImpl builder = newBuilder(); await builder.addFileEdit(path, (FileEditBuilder builder) { builder.addInsertion(content.length - 1, (EditBuilder builder) { (builder as DartEditBuilder).writeParameter('a', type: typeA); @@ -1647,7 +1672,7 @@ } test_writeParameterMatchingArgument() async { - String path = provider.convertPath('/test.dart'); + String path = convertPath('/test.dart'); String content = r''' f() {} g() { @@ -1657,13 +1682,14 @@ '''; addSource(path, content); CompilationUnit unit = (await driver.getResult(path))?.unit; - FunctionDeclaration g = unit.declarations[1]; - BlockFunctionBody body = g.functionExpression.body; - ExpressionStatement statement = body.block.statements[0]; - MethodInvocation invocation = statement.expression; + FunctionDeclaration g = unit.declarations[1] as FunctionDeclaration; + BlockFunctionBody body = g.functionExpression.body as BlockFunctionBody; + ExpressionStatement statement = + body.block.statements[0] as ExpressionStatement; + MethodInvocation invocation = statement.expression as MethodInvocation; Expression argument = invocation.argumentList.arguments[0]; - DartChangeBuilderImpl builder = new DartChangeBuilder(session); + DartChangeBuilderImpl builder = newBuilder(); await builder.addFileEdit(path, (FileEditBuilder builder) { builder.addInsertion(2, (EditBuilder builder) { (builder as DartEditBuilder) @@ -1675,17 +1701,17 @@ } test_writeParameters_named() async { - String path = provider.convertPath('/test.dart'); + String path = convertPath('/test.dart'); String content = 'f(int a, {bool b = false, String c}) {}'; addSource(path, content); CompilationUnit unit = (await driver.getResult(path))?.unit; - FunctionDeclaration f = unit.declarations[0]; + FunctionDeclaration f = unit.declarations[0] as FunctionDeclaration; FormalParameterList parameters = f.functionExpression.parameters; Iterable<ParameterElement> elements = parameters.parameters .map(resolutionMap.elementDeclaredByFormalParameter); - DartChangeBuilderImpl builder = new DartChangeBuilder(session); + DartChangeBuilderImpl builder = newBuilder(); await builder.addFileEdit(path, (FileEditBuilder builder) { builder.addInsertion(content.length - 1, (EditBuilder builder) { (builder as DartEditBuilder).writeParameters(elements); @@ -1697,16 +1723,16 @@ } test_writeParameters_positional() async { - String path = provider.convertPath('/test.dart'); + String path = convertPath('/test.dart'); String content = 'f(int a, [bool b = false, String c]) {}'; addSource(path, content); CompilationUnit unit = (await driver.getResult(path))?.unit; - FunctionDeclaration f = unit.declarations[0]; + FunctionDeclaration f = unit.declarations[0] as FunctionDeclaration; FormalParameterList parameters = f.functionExpression.parameters; Iterable<ParameterElement> elements = parameters.parameters .map(resolutionMap.elementDeclaredByFormalParameter); - DartChangeBuilderImpl builder = new DartChangeBuilder(session); + DartChangeBuilderImpl builder = newBuilder(); await builder.addFileEdit(path, (FileEditBuilder builder) { builder.addInsertion(content.length - 1, (EditBuilder builder) { (builder as DartEditBuilder).writeParameters(elements); @@ -1718,16 +1744,16 @@ } test_writeParameters_required() async { - String path = provider.convertPath('/test.dart'); + String path = convertPath('/test.dart'); String content = 'f(int i, String s) {}'; addSource(path, content); CompilationUnit unit = (await driver.getResult(path))?.unit; - FunctionDeclaration f = unit.declarations[0]; + FunctionDeclaration f = unit.declarations[0] as FunctionDeclaration; FormalParameterList parameters = f.functionExpression.parameters; Iterable<ParameterElement> elements = parameters.parameters .map(resolutionMap.elementDeclaredByFormalParameter); - DartChangeBuilderImpl builder = new DartChangeBuilder(session); + DartChangeBuilderImpl builder = newBuilder(); await builder.addFileEdit(path, (FileEditBuilder builder) { builder.addInsertion(content.length - 1, (EditBuilder builder) { (builder as DartEditBuilder).writeParameters(elements); @@ -1738,19 +1764,20 @@ } test_writeParametersMatchingArguments_named() async { - String path = provider.convertPath('/test.dart'); + String path = convertPath('/test.dart'); String content = ''' f(int i, String s) { g(s, index: i); }'''; addSource(path, content); CompilationUnit unit = (await driver.getResult(path))?.unit; - FunctionDeclaration f = unit.declarations[0]; - BlockFunctionBody body = f.functionExpression.body; - ExpressionStatement statement = body.block.statements[0]; - MethodInvocation invocation = statement.expression; + FunctionDeclaration f = unit.declarations[0] as FunctionDeclaration; + BlockFunctionBody body = f.functionExpression.body as BlockFunctionBody; + ExpressionStatement statement = + body.block.statements[0] as ExpressionStatement; + MethodInvocation invocation = statement.expression as MethodInvocation; - DartChangeBuilderImpl builder = new DartChangeBuilder(session); + DartChangeBuilderImpl builder = newBuilder(); await builder.addFileEdit(path, (FileEditBuilder builder) { builder.addInsertion(content.length - 1, (EditBuilder builder) { (builder as DartEditBuilder) @@ -1762,19 +1789,20 @@ } test_writeParametersMatchingArguments_required() async { - String path = provider.convertPath('/test.dart'); + String path = convertPath('/test.dart'); String content = ''' f(int i, String s) { g(s, i); }'''; addSource(path, content); CompilationUnit unit = (await driver.getResult(path))?.unit; - FunctionDeclaration f = unit.declarations[0]; - BlockFunctionBody body = f.functionExpression.body; - ExpressionStatement statement = body.block.statements[0]; - MethodInvocation invocation = statement.expression; + FunctionDeclaration f = unit.declarations[0] as FunctionDeclaration; + BlockFunctionBody body = f.functionExpression.body as BlockFunctionBody; + ExpressionStatement statement = + body.block.statements[0] as ExpressionStatement; + MethodInvocation invocation = statement.expression as MethodInvocation; - DartChangeBuilderImpl builder = new DartChangeBuilder(session); + DartChangeBuilderImpl builder = newBuilder(); await builder.addFileEdit(path, (FileEditBuilder builder) { builder.addInsertion(content.length - 1, (EditBuilder builder) { (builder as DartEditBuilder) @@ -1786,14 +1814,14 @@ } test_writeReference_method() async { - String aPath = provider.convertPath('/a.dart'); + String aPath = convertPath('/a.dart'); addSource(aPath, r''' class A { void foo() {} } '''); - String path = provider.convertPath('/test.dart'); + String path = convertPath('/test.dart'); String content = r''' import 'a.dart'; '''; @@ -1802,7 +1830,7 @@ var aElement = await _getClassElement(aPath, 'A'); var fooElement = aElement.methods[0]; - DartChangeBuilderImpl builder = new DartChangeBuilder(session); + DartChangeBuilderImpl builder = newBuilder(); await builder.addFileEdit(path, (DartFileEditBuilder builder) { builder.addInsertion(content.length - 1, (DartEditBuilder builder) { builder.writeReference(fooElement); @@ -1813,10 +1841,10 @@ } test_writeReference_topLevel_hasImport_noPrefix() async { - String aPath = provider.convertPath('/a.dart'); + String aPath = convertPath('/a.dart'); addSource(aPath, 'const a = 42;'); - String path = provider.convertPath('/test.dart'); + String path = convertPath('/test.dart'); String content = r''' import 'a.dart'; '''; @@ -1824,7 +1852,7 @@ var aElement = await _getTopLevelAccessorElement(aPath, 'a'); - DartChangeBuilderImpl builder = new DartChangeBuilder(session); + DartChangeBuilderImpl builder = newBuilder(); await builder.addFileEdit(path, (DartFileEditBuilder builder) { builder.addInsertion(content.length - 1, (DartEditBuilder builder) { builder.writeReference(aElement); @@ -1835,10 +1863,10 @@ } test_writeReference_topLevel_hasImport_prefix() async { - String aPath = provider.convertPath('/a.dart'); + String aPath = convertPath('/a.dart'); addSource(aPath, 'const a = 42;'); - String path = provider.convertPath('/test.dart'); + String path = convertPath('/test.dart'); String content = r''' import 'a.dart' as p; '''; @@ -1846,7 +1874,7 @@ var aElement = await _getTopLevelAccessorElement(aPath, 'a'); - DartChangeBuilderImpl builder = new DartChangeBuilder(session); + DartChangeBuilderImpl builder = newBuilder(); await builder.addFileEdit(path, (DartFileEditBuilder builder) { builder.addInsertion(content.length - 1, (DartEditBuilder builder) { builder.writeReference(aElement); @@ -1857,16 +1885,16 @@ } test_writeReference_topLevel_noImport() async { - String aPath = provider.convertPath('/a.dart'); + String aPath = convertPath('/a.dart'); addSource(aPath, 'const a = 42;'); - String path = provider.convertPath('/test.dart'); + String path = convertPath('/test.dart'); String content = ''; addSource(path, content); var aElement = await _getTopLevelAccessorElement(aPath, 'a'); - DartChangeBuilderImpl builder = new DartChangeBuilder(session); + DartChangeBuilderImpl builder = newBuilder(); await builder.addFileEdit(path, (DartFileEditBuilder builder) { builder.addInsertion(content.length - 1, (DartEditBuilder builder) { builder.writeReference(aElement); @@ -1879,12 +1907,12 @@ } test_writeType_dynamic() async { - String path = provider.convertPath('/test.dart'); + String path = convertPath('/test.dart'); String content = 'class A {}'; addSource(path, content); CompilationUnit unit = (await driver.getResult(path))?.unit; - DartChangeBuilderImpl builder = new DartChangeBuilder(session); + DartChangeBuilderImpl builder = newBuilder(); await builder.addFileEdit(path, (FileEditBuilder builder) { builder.addInsertion(content.length - 1, (EditBuilder builder) { (builder as DartEditBuilder).writeType(resolutionMap @@ -1925,13 +1953,13 @@ } test_writeType_genericType() async { - String path = provider.convertPath('/test.dart'); + String path = convertPath('/test.dart'); String content = 'class A {} class B<E> {}'; addSource(path, content); InterfaceType typeA = await _getType(path, 'A'); InterfaceType typeB = await _getType(path, 'B'); - DartChangeBuilderImpl builder = new DartChangeBuilder(session); + DartChangeBuilderImpl builder = newBuilder(); await builder.addFileEdit(path, (FileEditBuilder builder) { builder.addInsertion(content.length - 1, (EditBuilder builder) { (builder as DartEditBuilder).writeType(typeB.instantiate([typeA])); @@ -1942,12 +1970,12 @@ } test_writeType_groupName() async { - String path = provider.convertPath('/test.dart'); + String path = convertPath('/test.dart'); String content = 'class A {} class B extends A {} class C extends B {}'; addSource(path, content); DartType typeC = await _getType(path, 'C'); - DartChangeBuilderImpl builder = new DartChangeBuilder(session); + DartChangeBuilderImpl builder = newBuilder(); await builder.addFileEdit(path, (FileEditBuilder builder) { builder.addInsertion(content.length - 1, (EditBuilder builder) { (builder as DartEditBuilder).writeType(typeC, groupName: 'type'); @@ -1964,12 +1992,12 @@ } test_writeType_groupName_addSupertypeProposals() async { - String path = provider.convertPath('/test.dart'); + String path = convertPath('/test.dart'); String content = 'class A {} class B extends A {} class C extends B {}'; addSource(path, content); DartType typeC = await _getType(path, 'C'); - DartChangeBuilderImpl builder = new DartChangeBuilder(session); + DartChangeBuilderImpl builder = newBuilder(); await builder.addFileEdit(path, (FileEditBuilder builder) { builder.addInsertion(content.length - 1, (EditBuilder builder) { (builder as DartEditBuilder) @@ -1997,14 +2025,14 @@ } test_writeType_groupName_invalidType() async { - String path = provider.convertPath('/test.dart'); + String path = convertPath('/test.dart'); String content = 'class A<T> {}'; addSource(path, content); InterfaceType typeA = await _getType(path, 'A'); DartType typeT = typeA.typeParameters.single.type; - var builder = new DartChangeBuilder(session); + var builder = newBuilder(); await builder.addFileEdit(path, (builder) { builder.addInsertion(content.length, (builder) { // "T" cannot be written, because we are outside of "A". @@ -2024,11 +2052,11 @@ } test_writeType_null() async { - String path = provider.convertPath('/test.dart'); + String path = convertPath('/test.dart'); String content = 'class A {}'; addSource(path, content); - DartChangeBuilderImpl builder = new DartChangeBuilder(session); + DartChangeBuilderImpl builder = newBuilder(); await builder.addFileEdit(path, (FileEditBuilder builder) { builder.addInsertion(content.length - 1, (EditBuilder builder) { (builder as DartEditBuilder).writeType(null); @@ -2039,8 +2067,8 @@ } test_writeType_prefixGenerator() async { - String aPath = provider.convertPath('/a.dart'); - String bPath = provider.convertPath('/b.dart'); + String aPath = convertPath('/a.dart'); + String bPath = convertPath('/b.dart'); addSource(aPath, r''' class A1 {} @@ -2050,7 +2078,7 @@ class B {} '''); - String path = provider.convertPath('/test.dart'); + String path = convertPath('/test.dart'); String content = ''; addSource(path, content); @@ -2063,7 +2091,7 @@ return '_prefix${nextPrefixIndex++}'; } - var builder = new DartChangeBuilder(session); + var builder = newBuilder(); await builder.addFileEdit(path, (builder) { builder.addInsertion(content.length - 1, (builder) { builder.writeType(a1.type); @@ -2089,12 +2117,12 @@ } test_writeType_required_dynamic() async { - String path = provider.convertPath('/test.dart'); + String path = convertPath('/test.dart'); String content = 'class A {}'; addSource(path, content); CompilationUnit unit = (await driver.getResult(path))?.unit; - DartChangeBuilderImpl builder = new DartChangeBuilder(session); + DartChangeBuilderImpl builder = newBuilder(); await builder.addFileEdit(path, (FileEditBuilder builder) { builder.addInsertion(content.length - 1, (EditBuilder builder) { (builder as DartEditBuilder).writeType( @@ -2111,12 +2139,12 @@ } test_writeType_required_notNull() async { - String path = provider.convertPath('/test.dart'); + String path = convertPath('/test.dart'); String content = 'class A {}'; addSource(path, content); DartType typeA = await _getType(path, 'A'); - DartChangeBuilderImpl builder = new DartChangeBuilder(session); + DartChangeBuilderImpl builder = newBuilder(); await builder.addFileEdit(path, (FileEditBuilder builder) { builder.addInsertion(content.length - 1, (EditBuilder builder) { (builder as DartEditBuilder).writeType(typeA, required: true); @@ -2127,11 +2155,11 @@ } test_writeType_required_null() async { - String path = provider.convertPath('/test.dart'); + String path = convertPath('/test.dart'); String content = 'class A {}'; addSource(path, content); - DartChangeBuilderImpl builder = new DartChangeBuilder(session); + DartChangeBuilderImpl builder = newBuilder(); await builder.addFileEdit(path, (FileEditBuilder builder) { builder.addInsertion(content.length - 1, (EditBuilder builder) { (builder as DartEditBuilder).writeType(null, required: true); @@ -2142,12 +2170,12 @@ } test_writeType_simpleType() async { - String path = provider.convertPath('/test.dart'); + String path = convertPath('/test.dart'); String content = 'class A {}'; addSource(path, content); DartType typeA = await _getType(path, 'A'); - DartChangeBuilderImpl builder = new DartChangeBuilder(session); + DartChangeBuilderImpl builder = newBuilder(); await builder.addFileEdit(path, (FileEditBuilder builder) { builder.addInsertion(content.length - 1, (EditBuilder builder) { (builder as DartEditBuilder).writeType(typeA); @@ -2167,11 +2195,11 @@ } test_writeTypes_empty() async { - String path = provider.convertPath('/test.dart'); + String path = convertPath('/test.dart'); String content = 'class A {}'; addSource(path, content); - DartChangeBuilderImpl builder = new DartChangeBuilder(session); + DartChangeBuilderImpl builder = newBuilder(); await builder.addFileEdit(path, (FileEditBuilder builder) { builder.addInsertion(content.length - 1, (EditBuilder builder) { (builder as DartEditBuilderImpl).writeTypes([]); @@ -2182,13 +2210,13 @@ } test_writeTypes_noPrefix() async { - String path = provider.convertPath('/test.dart'); + String path = convertPath('/test.dart'); String content = 'class A {} class B {}'; addSource(path, content); DartType typeA = await _getType(path, 'A'); DartType typeB = await _getType(path, 'B'); - DartChangeBuilderImpl builder = new DartChangeBuilder(session); + DartChangeBuilderImpl builder = newBuilder(); await builder.addFileEdit(path, (FileEditBuilder builder) { builder.addInsertion(content.length - 1, (EditBuilder builder) { (builder as DartEditBuilderImpl).writeTypes([typeA, typeB]); @@ -2199,11 +2227,11 @@ } test_writeTypes_null() async { - String path = provider.convertPath('/test.dart'); + String path = convertPath('/test.dart'); String content = 'class A {}'; addSource(path, content); - DartChangeBuilderImpl builder = new DartChangeBuilder(session); + DartChangeBuilderImpl builder = newBuilder(); await builder.addFileEdit(path, (FileEditBuilder builder) { builder.addInsertion(content.length - 1, (EditBuilder builder) { (builder as DartEditBuilderImpl).writeTypes(null); @@ -2214,13 +2242,13 @@ } test_writeTypes_prefix() async { - String path = provider.convertPath('/test.dart'); + String path = convertPath('/test.dart'); String content = 'class A {} class B {}'; addSource(path, content); DartType typeA = await _getType(path, 'A'); DartType typeB = await _getType(path, 'B'); - DartChangeBuilderImpl builder = new DartChangeBuilder(session); + DartChangeBuilderImpl builder = newBuilder(); await builder.addFileEdit(path, (FileEditBuilder builder) { builder.addInsertion(content.length - 1, (EditBuilder builder) { (builder as DartEditBuilderImpl) @@ -2233,9 +2261,9 @@ Future<void> _assertImportLibrary( String initialCode, List<String> newUris, String expectedCode) async { - String path = provider.convertPath('/test.dart'); + String path = convertPath('/test.dart'); addSource(path, initialCode); - DartChangeBuilderImpl builder = new DartChangeBuilder(session); + DartChangeBuilderImpl builder = newBuilder(); await builder.addFileEdit(path, (DartFileEditBuilder builder) { for (String newUri in newUris) { builder.importLibrary(Uri.parse(newUri)); @@ -2266,7 +2294,7 @@ String displayText, SourceRange selection, }) async { - String path = provider.convertPath('/test.dart'); + String path = convertPath('/test.dart'); addSource(path, content); TypeSystem typeSystem = await session.typeSystem; @@ -2279,10 +2307,10 @@ StringBuffer displayBuffer = displayText != null ? new StringBuffer() : null; - DartChangeBuilderImpl builder = new DartChangeBuilder(session); + DartChangeBuilderImpl builder = newBuilder(); await builder.addFileEdit(path, (FileEditBuilder builder) { builder.addInsertion(content.length - 2, (EditBuilder builder) { - ExecutableElement element = inherited.element; + ExecutableElement element = inherited.element as ExecutableElement; (builder as DartEditBuilder).writeOverride( inherited, displayTextBuffer: displayBuffer, @@ -2299,13 +2327,13 @@ } Future<void> _assertWriteType(String typeCode, {String declarations}) async { - String path = provider.convertPath('/test.dart'); + String path = convertPath('/test.dart'); String content = (declarations ?? '') + '$typeCode v;'; addSource(path, content); var f = await _getTopLevelAccessorElement(path, 'v'); - var builder = new DartChangeBuilder(session); + var builder = newBuilder(); await builder.addFileEdit(path, (builder) { builder.addInsertion(content.length - 1, (builder) { builder.writeType(f.returnType); @@ -2336,22 +2364,21 @@ class DartFileEditBuilderImplTest extends AbstractContextTest with BuilderTestMixin { TypeProvider get typeProvider { - AnalysisContext context = AnalysisEngine.instance.createAnalysisContext(); - context.sourceFactory = new SourceFactoryImpl([new DartUriResolver(sdk)]); - return new TestTypeProvider(context); + return new TestTypeProvider(null, driver); } test_convertFunctionFromSyncToAsync_closure() async { - String path = provider.convertPath('/test.dart'); + String path = convertPath('/test.dart'); addSource(path, '''var f = () {}'''); CompilationUnit unit = (await driver.getResult(path))?.unit; - TopLevelVariableDeclaration variable = unit.declarations[0]; + TopLevelVariableDeclaration variable = + unit.declarations[0] as TopLevelVariableDeclaration; FunctionBody body = (variable.variables.variables[0].initializer as FunctionExpression) .body; - DartChangeBuilderImpl builder = new DartChangeBuilder(session); + DartChangeBuilderImpl builder = newBuilder(); await builder.addFileEdit(path, (FileEditBuilder builder) { (builder as DartFileEditBuilder) .convertFunctionFromSyncToAsync(body, typeProvider); @@ -2362,30 +2389,28 @@ } test_convertFunctionFromSyncToAsync_topLevelFunction() async { - String path = provider.convertPath('/test.dart'); + String path = convertPath('/test.dart'); addSource(path, 'String f() {}'); CompilationUnit unit = (await driver.getResult(path))?.unit; - FunctionDeclaration function = unit.declarations[0]; + FunctionDeclaration function = unit.declarations[0] as FunctionDeclaration; FunctionBody body = function.functionExpression.body; - DartChangeBuilderImpl builder = new DartChangeBuilder(session); + DartChangeBuilderImpl builder = newBuilder(); await builder.addFileEdit(path, (FileEditBuilder builder) { (builder as DartFileEditBuilder) .convertFunctionFromSyncToAsync(body, typeProvider); }); List<SourceEdit> edits = getEdits(builder); - expect(edits, hasLength(3)); + expect(edits, hasLength(2)); expect(edits[0].replacement, equalsIgnoringWhitespace('async')); - expect( - edits[1].replacement, equalsIgnoringWhitespace("import 'dart:async';")); - expect(edits[2].replacement, equalsIgnoringWhitespace('Future<String>')); + expect(edits[1].replacement, equalsIgnoringWhitespace('Future<String>')); } test_createEditBuilder() async { - String path = provider.convertPath('/test.dart'); + String path = convertPath('/test.dart'); addSource(path, 'library test;'); - DartChangeBuilderImpl builder = new DartChangeBuilder(session); + DartChangeBuilderImpl builder = newBuilder(); await builder.addFileEdit(path, (FileEditBuilder builder) { int offset = 4; int length = 5; @@ -2400,37 +2425,35 @@ } test_replaceTypeWithFuture() async { - String path = provider.convertPath('/test.dart'); + String path = convertPath('/test.dart'); addSource(path, 'String f() {}'); CompilationUnit unit = (await driver.getResult(path))?.unit; - FunctionDeclaration function = unit.declarations[0]; + FunctionDeclaration function = unit.declarations[0] as FunctionDeclaration; TypeAnnotation type = function.returnType; - DartChangeBuilderImpl builder = new DartChangeBuilder(session); + DartChangeBuilderImpl builder = newBuilder(); await builder.addFileEdit(path, (FileEditBuilder builder) { (builder as DartFileEditBuilder) .replaceTypeWithFuture(type, typeProvider); }); List<SourceEdit> edits = getEdits(builder); - expect(edits, hasLength(2)); - expect( - edits[0].replacement, equalsIgnoringWhitespace("import 'dart:async';")); - expect(edits[1].replacement, equalsIgnoringWhitespace('Future<String>')); + expect(edits, hasLength(1)); + expect(edits[0].replacement, equalsIgnoringWhitespace('Future<String>')); } } @reflectiveTest class DartLinkedEditBuilderImplTest extends AbstractContextTest { test_addSuperTypesAsSuggestions() async { - String path = provider.convertPath('/test.dart'); + String path = convertPath('/test.dart'); addSource(path, ''' class A {} class B extends A {} class C extends B {} '''); CompilationUnit unit = (await driver.getResult(path))?.unit; - ClassDeclaration classC = unit.declarations[2]; + ClassDeclaration classC = unit.declarations[2] as ClassDeclaration; DartLinkedEditBuilderImpl builder = new DartLinkedEditBuilderImpl(null); builder.addSuperTypesAsSuggestions(classC.declaredElement.type); List<LinkedEditSuggestion> suggestions = builder.suggestions;
diff --git a/pkg/analyzer_plugin/test/src/utilities/completion/completion_target_test.dart b/pkg/analyzer_plugin/test/src/utilities/completion/completion_target_test.dart index 45c0388..241ec1f 100644 --- a/pkg/analyzer_plugin/test/src/utilities/completion/completion_target_test.dart +++ b/pkg/analyzer_plugin/test/src/utilities/completion/completion_target_test.dart
@@ -4,8 +4,8 @@ import 'dart:async'; +import 'package:analyzer/dart/analysis/results.dart'; import 'package:analyzer/dart/ast/ast.dart'; -import 'package:analyzer/src/dart/analysis/driver.dart'; import 'package:analyzer/src/generated/parser.dart' as analyzer; import 'package:analyzer/src/generated/source.dart'; import 'package:analyzer_plugin/src/utilities/completion/completion_target.dart'; @@ -36,8 +36,8 @@ expect(nextOffset, equals(-1), reason: 'too many ^'); content = content.substring(0, completionOffset) + content.substring(completionOffset + 1); - testSource = addSource(provider.convertPath('/test.dart'), content); - AnalysisResult result = await driver.getResult(testSource.fullName); + testSource = addSource('/test.dart', content); + ResolvedUnitResult result = await driver.getResult(testSource.fullName); target = new CompletionTarget.forOffset(result.unit, completionOffset); } @@ -56,7 +56,7 @@ // Assert with parsed unit assertCommon(); - AnalysisResult result = await driver.getResult(testSource.fullName); + ResolvedUnitResult result = await driver.getResult(testSource.fullName); target = new CompletionTarget.forOffset(result.unit, completionOffset); // Assert more with resolved unit assertCommon();
diff --git a/pkg/analyzer_plugin/test/src/utilities/completion/optype_test.dart b/pkg/analyzer_plugin/test/src/utilities/completion/optype_test.dart index f85cb6f..f4c2eb8 100644 --- a/pkg/analyzer_plugin/test/src/utilities/completion/optype_test.dart +++ b/pkg/analyzer_plugin/test/src/utilities/completion/optype_test.dart
@@ -4,7 +4,7 @@ import 'dart:async'; -import 'package:analyzer/src/dart/analysis/driver.dart'; +import 'package:analyzer/dart/analysis/results.dart'; import 'package:analyzer_plugin/protocol/protocol_common.dart'; import 'package:analyzer_plugin/src/utilities/completion/completion_target.dart'; import 'package:analyzer_plugin/src/utilities/completion/optype.dart'; @@ -107,11 +107,7 @@ test_AssertInitializer() async { addTestSource('class C { C() : assert(^); }'); - await assertOpType( - constructors: true, - returnValue: true, - typeNames: true, - constructorBody: true); + await assertOpType(constructors: true, returnValue: true, typeNames: true); } test_AssignmentExpression_RHS() async { @@ -427,25 +423,13 @@ methodBody: true); } - test_Block_keyword() async { - addTestSource('class C { static C get instance => null; } main() {C.in^}'); - await assertOpType( - constructors: true, - prefixed: true, - returnValue: true, - typeNames: true, - voidReturn: true, - functionBody: true); - } - - test_Block_static() async { - addTestSource('class A {static foo() {^}}'); + test_Block_in_constructor() async { + addTestSource('class A {A() {^}}'); await assertOpType( constructors: true, returnValue: true, typeNames: true, - staticMethodBody: true, - methodBody: true, + constructorBody: true, voidReturn: true); } @@ -469,13 +453,25 @@ voidReturn: true); } - test_Block_in_constructor() async { - addTestSource('class A {A() {^}}'); + test_Block_keyword() async { + addTestSource('class C { static C get instance => null; } main() {C.in^}'); + await assertOpType( + constructors: true, + prefixed: true, + returnValue: true, + typeNames: true, + voidReturn: true, + functionBody: true); + } + + test_Block_static() async { + addTestSource('class A {static foo() {^}}'); await assertOpType( constructors: true, returnValue: true, typeNames: true, - constructorBody: true, + staticMethodBody: true, + methodBody: true, voidReturn: true); } @@ -557,7 +553,6 @@ returnValue: true, typeNames: true, voidReturn: true, - methodBody: true, kind: CompletionSuggestionKind.IDENTIFIER); } @@ -611,14 +606,40 @@ methodBody: true); } + test_ConstructorFieldInitializer_name() async { + addTestSource(r''' +class C { + final int foo; + + C() : ^ +} +'''); + await assertOpType(); + } + + test_ConstructorFieldInitializer_value() async { + addTestSource(r''' +class C { + final int foo; + + C() : foo = ^ +} +'''); + await assertOpType( + constructors: true, + returnValue: true, + typeNames: true, + ); + } + test_DefaultFormalParameter_named_expression() async { // DefaultFormalParameter FormalParameterList MethodDeclaration addTestSource('class A {a(blat: ^) { }}'); await assertOpType( - constructors: true, - returnValue: true, - typeNames: true, - methodBody: true); + constructors: true, + returnValue: true, + typeNames: true, + ); } test_DoStatement() async { @@ -698,33 +719,33 @@ // FormalParameterList MethodDeclaration addTestSource('class A {a(b.^ f) { }}'); await assertOpType( - constructors: true, - returnValue: true, - typeNames: true, - prefixed: true, - methodBody: true); + constructors: true, + returnValue: true, + typeNames: true, + prefixed: true, + ); } test_FormalParameter_partialType2() async { // FormalParameterList MethodDeclaration addTestSource('class A {a(b.z^ f) { }}'); await assertOpType( - constructors: true, - returnValue: true, - typeNames: true, - prefixed: true, - methodBody: true); + constructors: true, + returnValue: true, + typeNames: true, + prefixed: true, + ); } test_FormalParameter_partialType3() async { // FormalParameterList MethodDeclaration addTestSource('class A {a(b.^) { }}'); await assertOpType( - constructors: true, - returnValue: true, - typeNames: true, - prefixed: true, - methodBody: true); + constructors: true, + returnValue: true, + typeNames: true, + prefixed: true, + ); } test_ForStatement_condition() async { @@ -1604,7 +1625,7 @@ test_FormalParameterList() async { // FormalParameterList MethodDeclaration addTestSource('class A {a(^) { }}'); - await assertOpType(typeNames: true, methodBody: true); + await assertOpType(typeNames: true); } test_ForStatement_initializer() async { @@ -1680,7 +1701,7 @@ addTestSource(''' /// some dartdoc ^ zoo(z) { } String name;'''); - await assertOpType(functionBody: true); + await assertOpType(); } test_FunctionDeclaration_inLineDocComment2() async { @@ -1688,7 +1709,7 @@ addTestSource(''' /// some ^dartdoc zoo(z) { } String name;'''); - await assertOpType(functionBody: true); + await assertOpType(); } test_FunctionDeclaration_inStarComment() async { @@ -1706,13 +1727,13 @@ test_FunctionDeclaration_inStarDocComment() async { // Comment FunctionDeclaration CompilationUnit addTestSource('/** ^ */ zoo(z) { } String name; '); - await assertOpType(functionBody: true); + await assertOpType(); } test_FunctionDeclaration_inStarDocComment2() async { // Comment FunctionDeclaration CompilationUnit addTestSource('/** *^/ zoo(z) { } String name;'); - await assertOpType(functionBody: true); + await assertOpType(); } test_FunctionDeclaration_returnType() async { @@ -1743,7 +1764,7 @@ addTestSource(''' /// some dartdoc ^ zoo(z) { } String name;'''); - await assertOpType(typeNames: true, functionBody: true); + await assertOpType(typeNames: true); } test_FunctionDeclaration_returnType_afterLineDocComment2() async { @@ -1751,7 +1772,7 @@ addTestSource(''' /// some dartdoc ^ zoo(z) { } String name;'''); - await assertOpType(typeNames: true, functionBody: true); + await assertOpType(typeNames: true); } test_FunctionDeclaration_returnType_afterStarComment() async { @@ -1769,19 +1790,19 @@ test_FunctionDeclaration_returnType_afterStarDocComment() async { // FunctionDeclaration CompilationUnit addTestSource('/** */ ^ zoo(z) { } String name;'); - await assertOpType(typeNames: true, functionBody: true); + await assertOpType(typeNames: true); } test_FunctionDeclaration_returnType_afterStarDocComment2() async { // FunctionDeclaration CompilationUnit addTestSource('/** */^ zoo(z) { } String name;'); - await assertOpType(typeNames: true, functionBody: true); + await assertOpType(typeNames: true); } test_FunctionExpression() async { // BlockFunctionBody FunctionExpression FunctionDeclaration addTestSource('main()^ { int b = 2; b++; b. }'); - await assertOpType(functionBody: true); + await assertOpType(); } test_FunctionExpressionInvocation() async { @@ -1898,7 +1919,7 @@ class C2 { /// some dartdoc ^ zoo(z) { } String name; }'''); - await assertOpType(methodBody: true); + await assertOpType(); } test_MethodDeclaration_inLineDocComment2() async { @@ -1907,7 +1928,7 @@ class C2 { /// some ^dartdoc zoo(z) { } String name; }'''); - await assertOpType(methodBody: true); + await assertOpType(); } test_MethodDeclaration_inStarComment() async { @@ -1925,13 +1946,13 @@ test_MethodDeclaration_inStarDocComment() async { // Comment MethodDeclaration ClassDeclaration CompilationUnit addTestSource('class C2 {/** ^ */ zoo(z) { } String name; }'); - await assertOpType(methodBody: true); + await assertOpType(); } test_MethodDeclaration_inStarDocComment2() async { // Comment MethodDeclaration ClassDeclaration CompilationUnit addTestSource('class C2 {/** *^/ zoo(z) { } String name; }'); - await assertOpType(methodBody: true); + await assertOpType(); } test_MethodDeclaration_returnType() async { @@ -1965,7 +1986,7 @@ class C2 { /// some dartdoc ^ zoo(z) { } String name; }'''); - await assertOpType(typeNames: true, methodBody: true); + await assertOpType(typeNames: true); } test_MethodDeclaration_returnType_afterLineDocComment2() async { @@ -1974,7 +1995,7 @@ class C2 { /// some dartdoc ^ zoo(z) { } String name; }'''); - await assertOpType(typeNames: true, methodBody: true); + await assertOpType(typeNames: true); } test_MethodDeclaration_returnType_afterStarComment() async { @@ -1992,13 +2013,13 @@ test_MethodDeclaration_returnType_afterStarDocComment() async { // MethodDeclaration ClassDeclaration CompilationUnit addTestSource('class C2 {/** */ ^ zoo(z) { } String name; }'); - await assertOpType(typeNames: true, methodBody: true); + await assertOpType(typeNames: true); } test_MethodDeclaration_returnType_afterStarDocComment2() async { // MethodDeclaration ClassDeclaration CompilationUnit addTestSource('class C2 {/** */^ zoo(z) { } String name; }'); - await assertOpType(typeNames: true, methodBody: true); + await assertOpType(typeNames: true); } test_NamedExpression() async { @@ -2043,49 +2064,49 @@ test_SimpleFormalParameter_name1() async { // SimpleIdentifier SimpleFormalParameter FormalParameterList addTestSource('m(String na^) {}'); - await assertOpType(typeNames: false, functionBody: true); + await assertOpType(typeNames: false); } test_SimpleFormalParameter_name2() async { // SimpleIdentifier SimpleFormalParameter FormalParameterList addTestSource('m(int first, String na^) {}'); - await assertOpType(typeNames: false, functionBody: true); + await assertOpType(typeNames: false); } test_SimpleFormalParameter_type_optionalNamed() async { // SimpleIdentifier DefaultFormalParameter FormalParameterList addTestSource('m({Str^}) {}'); - await assertOpType(typeNames: true, functionBody: true); + await assertOpType(typeNames: true); } test_SimpleFormalParameter_type_optionalPositional() async { // SimpleIdentifier DefaultFormalParameter FormalParameterList addTestSource('m([Str^]) {}'); - await assertOpType(typeNames: true, functionBody: true); + await assertOpType(typeNames: true); } test_SimpleFormalParameter_type_withName() async { // SimpleIdentifier SimpleFormalParameter FormalParameterList addTestSource('m(Str^ name) {}'); - await assertOpType(typeNames: true, functionBody: true); + await assertOpType(typeNames: true); } test_SimpleFormalParameter_type_withoutName1() async { // SimpleIdentifier SimpleFormalParameter FormalParameterList addTestSource('m(Str^) {}'); - await assertOpType(typeNames: true, functionBody: true); + await assertOpType(typeNames: true); } test_SimpleFormalParameter_type_withoutName2() async { // FormalParameterList addTestSource('m(^) {}'); - await assertOpType(typeNames: true, functionBody: true); + await assertOpType(typeNames: true); } test_SimpleFormalParameter_type_withoutName3() async { // SimpleIdentifier SimpleFormalParameter FormalParameterList addTestSource('m(int first, Str^) {}'); - await assertOpType(typeNames: true, functionBody: true); + await assertOpType(typeNames: true); } test_SwitchCase_before() async { @@ -2112,7 +2133,7 @@ class A implements I { A(this.^) {} }'''); - await assertOpType(prefixed: true, constructorBody: true); + await assertOpType(prefixed: true); } test_ThisExpression_constructor_param2() async { @@ -2121,7 +2142,7 @@ class A implements I { A(this.f^) {} }'''); - await assertOpType(prefixed: true, constructorBody: true); + await assertOpType(prefixed: true); } test_ThisExpression_constructor_param3() async { @@ -2130,7 +2151,7 @@ class A implements I { A(this.^f) {} }'''); - await assertOpType(prefixed: true, constructorBody: true); + await assertOpType(prefixed: true); } test_ThisExpression_constructor_param4() async { @@ -2139,7 +2160,7 @@ class A implements I { A(Str^ this.foo) {} }'''); - await assertOpType(typeNames: true, constructorBody: true); + await assertOpType(typeNames: true); } test_TopLevelVariableDeclaration_typed_name() async { @@ -2221,7 +2242,7 @@ /// Common test methods to Dart1/Dart2 versions of OpType tests. class OpTypeTestCommon extends AbstractContextTest { - String testpath; + String testPath; int completionOffset; OpType visitor; @@ -2232,7 +2253,7 @@ expect(nextOffset, equals(-1), reason: 'too many ^'); content = content.substring(0, completionOffset) + content.substring(completionOffset + 1); - super.addSource(testpath, content); + super.addSource(testPath, content); } Future<void> assertOpType( @@ -2251,10 +2272,10 @@ bool voidReturn: false, CompletionSuggestionKind kind: CompletionSuggestionKind.INVOCATION}) async { - AnalysisResult analysisResult = await driver.getResult(testpath); + ResolvedUnitResult resolvedUnit = await driver.getResult(testPath); CompletionTarget completionTarget = - new CompletionTarget.forOffset(analysisResult.unit, completionOffset); + new CompletionTarget.forOffset(resolvedUnit.unit, completionOffset); visitor = new OpType.forCompletion(completionTarget, completionOffset); expect(visitor.includeCaseLabelSuggestions, caseLabel, reason: 'caseLabel'); @@ -2283,6 +2304,6 @@ @override void setUp() { super.setUp(); - testpath = provider.convertPath('/completionTest.dart'); + testPath = convertPath('/completionTest.dart'); } }
diff --git a/pkg/analyzer_plugin/test/src/utilities/visitors/local_declaration_visitor_test.dart b/pkg/analyzer_plugin/test/src/utilities/visitors/local_declaration_visitor_test.dart index 3811ea4..fd96c31 100644 --- a/pkg/analyzer_plugin/test/src/utilities/visitors/local_declaration_visitor_test.dart +++ b/pkg/analyzer_plugin/test/src/utilities/visitors/local_declaration_visitor_test.dart
@@ -42,9 +42,9 @@ '''); NodeList<CompilationUnitMember> declarations = unit.declarations; expect(declarations, hasLength(2)); - FunctionDeclaration f = declarations[1]; + FunctionDeclaration f = declarations[1] as FunctionDeclaration; expect(f, isNotNull); - BlockFunctionBody body = f.functionExpression.body; + BlockFunctionBody body = f.functionExpression.body as BlockFunctionBody; Statement statement = body.block.statements[0]; expect(statement, const TypeMatcher<ForEachStatement>()); statement.accept(new TestVisitor(statement.offset)); @@ -70,6 +70,9 @@ void declaredFunctionTypeAlias(FunctionTypeAlias declaration) {} @override + void declaredGenericTypeAlias(GenericTypeAlias declaration) {} + + @override void declaredLabel(Label label, bool isCaseLabel) {} @override
diff --git a/pkg/analyzer_plugin/test/support/abstract_context.dart b/pkg/analyzer_plugin/test/support/abstract_context.dart index 8c7cdaf..9c14f2b 100644 --- a/pkg/analyzer_plugin/test/support/abstract_context.dart +++ b/pkg/analyzer_plugin/test/support/abstract_context.dart
@@ -10,7 +10,6 @@ import 'package:analyzer/dart/element/visitor.dart'; import 'package:analyzer/exception/exception.dart'; import 'package:analyzer/file_system/file_system.dart'; -import 'package:analyzer/file_system/memory_file_system.dart'; import 'package:analyzer/src/dart/analysis/byte_store.dart'; import 'package:analyzer/src/dart/analysis/driver.dart'; import 'package:analyzer/src/dart/analysis/file_state.dart'; @@ -22,8 +21,8 @@ import 'package:analyzer/src/generated/source_io.dart'; import 'package:analyzer/src/generated/testing/element_search.dart'; import 'package:analyzer/src/source/package_map_resolver.dart'; - -import 'mock_sdk.dart'; +import 'package:analyzer/src/test_utilities/mock_sdk.dart'; +import 'package:analyzer/src/test_utilities/resource_provider_mixin.dart'; /** * Finds an [Element] with the given [name]. @@ -47,8 +46,7 @@ */ typedef void _ElementVisitorFunction(Element element); -class AbstractContextTest { - MemoryResourceProvider provider; +class AbstractContextTest with ResourceProviderMixin { DartSdk sdk; Map<String, List<Folder>> packageMap; UriResolver resourceResolver; @@ -64,7 +62,8 @@ */ AnalysisSession get session => driver.currentSession; - Source addMetaPackageSource() => addPackageSource('meta', 'meta.dart', r''' + void addMetaPackage() { + addPackageFile('meta', 'meta.dart', r''' library meta; const Required required = const Required(); @@ -74,21 +73,20 @@ const Required([this.reason]); } '''); + } - Source addPackageSource(String packageName, String filePath, String content) { - packageMap[packageName] = [(newFolder('/pubcache/$packageName'))]; - File file = newFile('/pubcache/$packageName/$filePath', content); - return file.createSource(); + File addPackageFile(String packageName, String pathInLib, String content) { + var packageLibPath = '/.pub-cache/$packageName/lib'; + packageMap[packageName] = [newFolder(packageLibPath)]; + return newFile('$packageLibPath/$pathInLib', content: content); } Source addSource(String path, String content, [Uri uri]) { - if (path.startsWith('/')) { - path = provider.convertPath(path); - } + path = convertPath(path); driver.addFile(path); driver.changeFile(path); _fileContentOverlay[path] = content; - return provider.getFile(path).createSource(); + return getFile(path).createSource(); } Element findElementInUnit(CompilationUnit unit, String name, @@ -98,28 +96,16 @@ .single; } - File newFile(String path, [String content]) => - provider.newFile(provider.convertPath(path), content ?? ''); - - Folder newFolder(String path) => - provider.newFolder(provider.convertPath(path)); - - void processRequiredPlugins() { - AnalysisEngine.instance.processRequiredPlugins(); - } - Future<CompilationUnit> resolveLibraryUnit(Source source) async { return (await driver.getResult(source.fullName))?.unit; } void setUp() { - processRequiredPlugins(); - setupResourceProvider(); - sdk = new MockSdk(resourceProvider: provider); - resourceResolver = new ResourceUriResolver(provider); + sdk = new MockSdk(resourceProvider: resourceProvider); + resourceResolver = new ResourceUriResolver(resourceProvider); packageMap = new Map<String, List<Folder>>(); PackageMapUriResolver packageResolver = - new PackageMapUriResolver(provider, packageMap); + new PackageMapUriResolver(resourceProvider, packageMap); SourceFactory sourceFactory = new SourceFactory( [new DartUriResolver(sdk), packageResolver, resourceResolver]); PerformanceLog log = new PerformanceLog(_logBuffer); @@ -128,7 +114,7 @@ _driver = new AnalysisDriver( scheduler, log, - provider, + resourceProvider, new MemoryByteStore(), _fileContentOverlay, null, @@ -138,12 +124,7 @@ AnalysisEngine.instance.logger = PrintLogger.instance; } - void setupResourceProvider() { - provider = new MemoryResourceProvider(); - } - void tearDown() { - provider = null; AnalysisEngine.instance.clearCaches(); AnalysisEngine.instance.logger = null; }
diff --git a/pkg/analyzer_plugin/test/support/abstract_single_unit.dart b/pkg/analyzer_plugin/test/support/abstract_single_unit.dart index 7a3b6bc..0b14065 100644 --- a/pkg/analyzer_plugin/test/support/abstract_single_unit.dart +++ b/pkg/analyzer_plugin/test/support/abstract_single_unit.dart
@@ -49,7 +49,7 @@ AstNode findNodeAtOffset(int offset, [Predicate<AstNode> predicate]) { AstNode result = new NodeLocator(offset).searchWithin(testUnit); if (result != null && predicate != null) { - result = result.getAncestor(predicate); + result = result.thisOrAncestorMatching(predicate); } return result; } @@ -117,6 +117,6 @@ @override void setUp() { super.setUp(); - testFile = provider.convertPath('/test.dart'); + testFile = convertPath('/test.dart'); } }
diff --git a/pkg/analyzer_plugin/test/utilities/analyzer_converter_test.dart b/pkg/analyzer_plugin/test/utilities/analyzer_converter_test.dart index 3d17d82..775e9a6 100644 --- a/pkg/analyzer_plugin/test/utilities/analyzer_converter_test.dart +++ b/pkg/analyzer_plugin/test/utilities/analyzer_converter_test.dart
@@ -63,10 +63,8 @@ @override void setUp() { super.setUp(); - source = provider - .newFile(provider.convertPath('/foo/bar.dart'), '') - .createSource(); - testFile = provider.convertPath('/test.dart'); + source = newFile('/foo/bar.dart').createSource(); + testFile = convertPath('/test.dart'); } test_convertAnalysisError_lineInfo_noSeverity() { @@ -187,7 +185,8 @@ class B<K, V> {}'''); analyzer.CompilationUnit unit = await resolveLibraryUnit(source); { - analyzer.ClassElement engineElement = findElementInUnit(unit, '_A'); + analyzer.ClassElement engineElement = + findElementInUnit(unit, '_A') as analyzer.ClassElement; // create notification Element plugin.Element element = converter.convertElement(engineElement); expect(element.kind, plugin.ElementKind.CLASS); @@ -209,7 +208,8 @@ plugin.Element.FLAG_PRIVATE); } { - analyzer.ClassElement engineElement = findElementInUnit(unit, 'B'); + analyzer.ClassElement engineElement = + findElementInUnit(unit, 'B') as analyzer.ClassElement; // create notification Element plugin.Element element = converter.convertElement(engineElement); expect(element.kind, plugin.ElementKind.CLASS); @@ -226,7 +226,7 @@ }'''); analyzer.CompilationUnit unit = await resolveLibraryUnit(source); analyzer.ConstructorElement engineElement = - findElementInUnit(unit, 'myConstructor'); + findElementInUnit(unit, 'myConstructor') as analyzer.ConstructorElement; // create notification Element plugin.Element element = converter.convertElement(engineElement); expect(element.kind, plugin.ElementKind.CONSTRUCTOR); @@ -264,7 +264,8 @@ enum E2 { three, four }'''); analyzer.CompilationUnit unit = await resolveLibraryUnit(source); { - analyzer.ClassElement engineElement = findElementInUnit(unit, '_E1'); + analyzer.ClassElement engineElement = + findElementInUnit(unit, '_E1') as analyzer.ClassElement; expect(engineElement.hasDeprecated, isTrue); // create notification Element plugin.Element element = converter.convertElement(engineElement); @@ -286,7 +287,8 @@ plugin.Element.FLAG_PRIVATE); } { - analyzer.ClassElement engineElement = findElementInUnit(unit, 'E2'); + analyzer.ClassElement engineElement = + findElementInUnit(unit, 'E2') as analyzer.ClassElement; // create notification Element plugin.Element element = converter.convertElement(engineElement); expect(element.kind, plugin.ElementKind.ENUM); @@ -303,7 +305,8 @@ enum E2 { three, four }'''); analyzer.CompilationUnit unit = await resolveLibraryUnit(source); { - analyzer.FieldElement engineElement = findElementInUnit(unit, 'one'); + analyzer.FieldElement engineElement = + findElementInUnit(unit, 'one') as analyzer.FieldElement; // create notification Element plugin.Element element = converter.convertElement(engineElement); expect(element.kind, plugin.ElementKind.ENUM_CONSTANT); @@ -327,7 +330,8 @@ plugin.Element.FLAG_CONST | plugin.Element.FLAG_STATIC); } { - analyzer.FieldElement engineElement = findElementInUnit(unit, 'three'); + analyzer.FieldElement engineElement = + findElementInUnit(unit, 'three') as analyzer.FieldElement; // create notification Element plugin.Element element = converter.convertElement(engineElement); expect(element.kind, plugin.ElementKind.ENUM_CONSTANT); @@ -393,7 +397,8 @@ static const myField = 42; }'''); analyzer.CompilationUnit unit = await resolveLibraryUnit(source); - analyzer.FieldElement engineElement = findElementInUnit(unit, 'myField'); + analyzer.FieldElement engineElement = + findElementInUnit(unit, 'myField') as analyzer.FieldElement; // create notification Element plugin.Element element = converter.convertElement(engineElement); expect(element.kind, plugin.ElementKind.FIELD); @@ -418,7 +423,7 @@ '''); analyzer.CompilationUnit unit = await resolveLibraryUnit(source); analyzer.FunctionTypeAliasElement engineElement = - findElementInUnit(unit, 'F'); + findElementInUnit(unit, 'F') as analyzer.FunctionTypeAliasElement; // create notification Element plugin.Element element = converter.convertElement(engineElement); expect(element.kind, plugin.ElementKind.FUNCTION_TYPE_ALIAS); @@ -437,6 +442,31 @@ expect(element.flags, 0); } + test_convertElement_genericTypeAlias_function() async { + analyzer.Source source = addSource(testFile, ''' +typedef F<T> = int Function(String x); +'''); + analyzer.CompilationUnit unit = await resolveLibraryUnit(source); + analyzer.FunctionTypeAliasElement engineElement = + findElementInUnit(unit, 'F') as analyzer.FunctionTypeAliasElement; + // create notification Element + plugin.Element element = converter.convertElement(engineElement); + expect(element.kind, plugin.ElementKind.FUNCTION_TYPE_ALIAS); + expect(element.name, 'F'); + expect(element.typeParameters, '<T>'); + { + plugin.Location location = element.location; + expect(location.file, testFile); + expect(location.offset, 8); + expect(location.length, 'F'.length); + expect(location.startLine, 1); + expect(location.startColumn, 9); + } + expect(element.parameters, '(String x)'); + expect(element.returnType, 'int'); + expect(element.flags, 0); + } + test_convertElement_getter() async { analyzer.Source source = addSource(testFile, ''' class A { @@ -444,7 +474,8 @@ }'''); analyzer.CompilationUnit unit = await resolveLibraryUnit(source); analyzer.PropertyAccessorElement engineElement = - findElementInUnit(unit, 'myGetter', analyzer.ElementKind.GETTER); + findElementInUnit(unit, 'myGetter', analyzer.ElementKind.GETTER) + as analyzer.PropertyAccessorElement; // create notification Element plugin.Element element = converter.convertElement(engineElement); expect(element.kind, plugin.ElementKind.GETTER); @@ -470,7 +501,8 @@ } }'''); analyzer.CompilationUnit unit = await resolveLibraryUnit(source); - analyzer.MethodElement engineElement = findElementInUnit(unit, 'myMethod'); + analyzer.MethodElement engineElement = + findElementInUnit(unit, 'myMethod') as analyzer.MethodElement; // create notification Element plugin.Element element = converter.convertElement(engineElement); expect(element.kind, plugin.ElementKind.METHOD); @@ -495,7 +527,8 @@ }'''); analyzer.CompilationUnit unit = await resolveLibraryUnit(source); analyzer.PropertyAccessorElement engineElement = - findElementInUnit(unit, 'mySetter', analyzer.ElementKind.SETTER); + findElementInUnit(unit, 'mySetter', analyzer.ElementKind.SETTER) + as analyzer.PropertyAccessorElement; // create notification Element plugin.Element element = converter.convertElement(engineElement); expect(element.kind, plugin.ElementKind.SETTER); @@ -572,7 +605,8 @@ } }'''); analyzer.CompilationUnit unit = await resolveLibraryUnit(source); - analyzer.LabelElement engineElement = findElementInUnit(unit, 'myLabel'); + analyzer.LabelElement engineElement = + findElementInUnit(unit, 'myLabel') as analyzer.LabelElement; // create notification Element plugin.Element element = converter.convertElement(engineElement); expect(element.kind, plugin.ElementKind.LABEL);
diff --git a/pkg/analyzer_plugin/test/utilities/completion/completion_contributor_util.dart b/pkg/analyzer_plugin/test/utilities/completion/completion_contributor_util.dart index b8a4aef..6fe32fb 100644 --- a/pkg/analyzer_plugin/test/utilities/completion/completion_contributor_util.dart +++ b/pkg/analyzer_plugin/test/utilities/completion/completion_contributor_util.dart
@@ -446,18 +446,15 @@ return cs; } - /** - * Return a [Future] that completes with the containing library information - * after it is accessible via [context.getLibrariesContaining]. - */ Future<void> computeLibrariesContaining() { return driver.getResult(testFile).then((result) => null); } Future computeSuggestions() async { - ResolveResult result = await driver.getResult(testFile); + ResolvedUnitResult result = await driver.getResult(testFile); testSource = result.unit.declaredElement.source; - request = new DartCompletionRequestImpl(provider, completionOffset, result); + request = new DartCompletionRequestImpl( + resourceProvider, completionOffset, result); CompletionTarget target = new CompletionTarget.forOffset(request.result.unit, request.offset); @@ -478,13 +475,16 @@ */ void configureFlutterPkg(Map<String, String> pathToCode) { pathToCode.forEach((path, code) { - provider.newFile('$flutterPkgLibPath/$path', code); + newFile('$flutterPkgLibPath/$path', content: code); }); // configure SourceFactory - Folder myPkgFolder = provider.getResource(flutterPkgLibPath); - UriResolver pkgResolver = new PackageMapUriResolver(provider, { - 'flutter': [myPkgFolder] - }); + Folder myPkgFolder = getFolder(flutterPkgLibPath); + UriResolver pkgResolver = new PackageMapUriResolver( + resourceProvider, + { + 'flutter': [myPkgFolder] + }, + ); SourceFactory sourceFactory = new SourceFactory( [new DartUriResolver(sdk), pkgResolver, resourceResolver]); driver.configure(sourceFactory: sourceFactory); @@ -561,7 +561,7 @@ @override void setUp() { super.setUp(); - testFile = provider.convertPath('/completionTest.dart'); + testFile = convertPath('/completionTest.dart'); contributor = createContributor(); } }
diff --git a/pkg/analyzer_plugin/test/utilities/completion/completion_target_test.dart b/pkg/analyzer_plugin/test/utilities/completion/completion_target_test.dart index 8e1674e..9b44141 100644 --- a/pkg/analyzer_plugin/test/utilities/completion/completion_target_test.dart +++ b/pkg/analyzer_plugin/test/utilities/completion/completion_target_test.dart
@@ -2,7 +2,6 @@ // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. -import 'package:analyzer/analyzer.dart'; import 'package:analyzer/dart/ast/ast.dart'; import 'package:analyzer/dart/ast/standard_ast_factory.dart'; import 'package:analyzer/dart/ast/token.dart'; @@ -26,6 +25,17 @@ @reflectiveTest class CompletionTargetTest { + /// Parse a dangling expression (no parent node). The angular plugin, for + /// instance, does this. + Expression parseDanglingDart(String code) { + final reader = new CharSequenceReader(code); + final scanner = new Scanner(null, reader, null); + final source = new StringSource(code, 'test.dart'); + final listener = new _ErrorCollector(); + + return new Parser(source, listener).parseExpression(scanner.tokenize()); + } + test_danglingExpressionCompletionIsValid() { // Test that users can parse dangling expressions of dart and autocomplete // them without crash/with the correct offset information. @@ -39,17 +49,6 @@ expect(replacementRange.length, 'identifier'.length); } - /// Parse a dangling expression (no parent node). The angular plugin, for - /// instance, does this. - Expression parseDanglingDart(String code) { - final reader = new CharSequenceReader(code); - final scanner = new Scanner(null, reader, null); - final source = new StringSource(code, 'test.dart'); - final listener = new _ErrorCollector(); - - return new Parser(source, listener).parseExpression(scanner.tokenize()); - } - Expression wrapForCompliance(Expression expression) { // TODO(mfairhurst) This should be performed for clients or the need should // be dropped. It's a fairly valid invariant that all autocompletion target @@ -69,10 +68,6 @@ _ErrorCollector(); - /// The group of errors collected. - AnalyzerErrorGroup get group => - new AnalyzerErrorGroup.fromAnalysisErrors(_errors); - /// Whether any errors where collected. bool get hasErrors => !_errors.isEmpty;
diff --git a/pkg/analyzer_plugin/test/utilities/completion/inherited_reference_contributor_test.dart b/pkg/analyzer_plugin/test/utilities/completion/inherited_reference_contributor_test.dart index 9ac962d..b710466 100644 --- a/pkg/analyzer_plugin/test/utilities/completion/inherited_reference_contributor_test.dart +++ b/pkg/analyzer_plugin/test/utilities/completion/inherited_reference_contributor_test.dart
@@ -28,7 +28,7 @@ /// Sanity check. Permutations tested in local_ref_contributor. test_ArgDefaults_inherited_method_with_required_named() async { - addMetaPackageSource(); + addMetaPackage(); resolveSource('/testB.dart', ''' import 'package:meta/meta.dart'; @@ -71,7 +71,7 @@ assertNotSuggested('B'); assertNotSuggested('A'); assertNotSuggested('Object'); - assertSuggestMethod('y', 'A', 'dynamic'); + assertSuggestMethod('y', 'A', 'Future<dynamic>'); } test_Block_inherited_imported() async {
diff --git a/pkg/analyzer_plugin/test/utilities/completion/type_member_contributor_test.dart b/pkg/analyzer_plugin/test/utilities/completion/type_member_contributor_test.dart index 8b3178c..3bb0120 100644 --- a/pkg/analyzer_plugin/test/utilities/completion/type_member_contributor_test.dart +++ b/pkg/analyzer_plugin/test/utilities/completion/type_member_contributor_test.dart
@@ -82,7 +82,7 @@ } test_ArgDefaults_method_with_optional_positional() async { - addMetaPackageSource(); + addMetaPackage(); addTestSource(''' import 'package:meta/meta.dart'; @@ -97,7 +97,7 @@ } test_ArgDefaults_method_with_required_named() async { - addMetaPackageSource(); + addMetaPackage(); addTestSource(''' import 'package:meta/meta.dart'; @@ -1086,10 +1086,10 @@ } test_Block_unimported() async { - addPackageSource('myBar', 'bar.dart', 'class Foo2 { Foo2() { } }'); + addPackageFile('myBar', 'bar.dart', 'class Foo2 { Foo2() { } }'); addSource( '/proj/testAB.dart', 'import "package:myBar/bar.dart"; class Foo { }'); - testFile = provider.convertPath('/proj/completionTest.dart'); + testFile = convertPath('/proj/completionTest.dart'); addTestSource('class C {foo(){F^}}'); await computeSuggestions(); expect(replacementOffset, completionOffset - 1);
diff --git a/pkg/analyzer_plugin/test/utilities/navigation_test.dart b/pkg/analyzer_plugin/test/utilities/navigation_test.dart index fdafcd3..80ec0db 100644 --- a/pkg/analyzer_plugin/test/utilities/navigation_test.dart +++ b/pkg/analyzer_plugin/test/utilities/navigation_test.dart
@@ -3,7 +3,7 @@ // BSD-style license that can be found in the LICENSE file. import 'package:analyzer/dart/analysis/results.dart'; -import 'package:analyzer/file_system/memory_file_system.dart'; +import 'package:analyzer/src/test_utilities/resource_provider_mixin.dart'; import 'package:analyzer_plugin/src/utilities/navigation/navigation.dart'; import 'package:analyzer_plugin/utilities/generator.dart'; import 'package:analyzer_plugin/utilities/navigation/navigation.dart'; @@ -17,15 +17,13 @@ } @reflectiveTest -class NavigationGeneratorTest { - MemoryResourceProvider provider = new MemoryResourceProvider(); - - ResolveResult resolveResult = new MockAnalysisResult(path: 'a.dart'); +class NavigationGeneratorTest with ResourceProviderMixin { + ResolvedUnitResult resolvedUnit = new MockResolvedUnitResult(path: 'a.dart'); test_none() { NavigationGenerator generator = new NavigationGenerator([]); NavigationRequest request = - new DartNavigationRequestImpl(provider, 0, 100, resolveResult); + new DartNavigationRequestImpl(resourceProvider, 0, 100, resolvedUnit); GeneratorResult result = generator.generateNavigationNotification(request); expect(result.notifications, hasLength(1)); } @@ -34,7 +32,7 @@ TestContributor contributor = new TestContributor(); NavigationGenerator generator = new NavigationGenerator([contributor]); NavigationRequest request = - new DartNavigationRequestImpl(provider, 0, 100, resolveResult); + new DartNavigationRequestImpl(resourceProvider, 0, 100, resolvedUnit); GeneratorResult result = generator.generateNavigationNotification(request); expect(result.notifications, hasLength(1)); expect(contributor.count, 1); @@ -53,7 +51,7 @@ NavigationGenerator generator = new NavigationGenerator( [contributor1, contributor2, contributor3, contributor4]); NavigationRequest request = - new DartNavigationRequestImpl(provider, 0, 100, resolveResult); + new DartNavigationRequestImpl(resourceProvider, 0, 100, resolvedUnit); GeneratorResult result = generator.generateNavigationNotification(request); expect(result.notifications, hasLength(3)); expect(
diff --git a/pkg/analyzer_plugin/test/utilities/range_factory_test.dart b/pkg/analyzer_plugin/test/utilities/range_factory_test.dart index af79bc1..105ae6f 100644 --- a/pkg/analyzer_plugin/test/utilities/range_factory_test.dart +++ b/pkg/analyzer_plugin/test/utilities/range_factory_test.dart
@@ -29,7 +29,8 @@ test_endEnd() async { await resolveTestUnit('main() {}'); - FunctionDeclaration mainFunction = testUnit.declarations[0]; + FunctionDeclaration mainFunction = + testUnit.declarations[0] as FunctionDeclaration; SimpleIdentifier mainName = mainFunction.name; FunctionBody mainBody = mainFunction.functionExpression.body; expect(range.endEnd(mainName, mainBody), new SourceRange(4, 5)); @@ -37,14 +38,16 @@ test_endLength() async { await resolveTestUnit('main() {}'); - FunctionDeclaration mainFunction = testUnit.declarations[0]; + FunctionDeclaration mainFunction = + testUnit.declarations[0] as FunctionDeclaration; SimpleIdentifier mainName = mainFunction.name; expect(range.endLength(mainName, 3), new SourceRange(4, 3)); } test_endStart() async { await resolveTestUnit('main() {}'); - FunctionDeclaration mainFunction = testUnit.declarations[0]; + FunctionDeclaration mainFunction = + testUnit.declarations[0] as FunctionDeclaration; SimpleIdentifier mainName = mainFunction.name; FunctionBody mainBody = mainFunction.functionExpression.body; expect(range.endStart(mainName, mainBody), new SourceRange(4, 3)); @@ -58,14 +61,16 @@ test_node() async { await resolveTestUnit('main() {}'); - FunctionDeclaration mainFunction = testUnit.declarations[0]; + FunctionDeclaration mainFunction = + testUnit.declarations[0] as FunctionDeclaration; SimpleIdentifier mainName = mainFunction.name; expect(range.node(mainName), new SourceRange(0, 4)); } test_nodes() async { await resolveTestUnit(' main() {}'); - FunctionDeclaration mainFunction = testUnit.declarations[0]; + FunctionDeclaration mainFunction = + testUnit.declarations[0] as FunctionDeclaration; SimpleIdentifier mainName = mainFunction.name; FunctionBody mainBody = mainFunction.functionExpression.body; expect(range.nodes([mainName, mainBody]), new SourceRange(1, 9)); @@ -82,7 +87,8 @@ test_startEnd_nodeNode() async { await resolveTestUnit(' main() {}'); - FunctionDeclaration mainFunction = testUnit.declarations[0]; + FunctionDeclaration mainFunction = + testUnit.declarations[0] as FunctionDeclaration; SimpleIdentifier mainName = mainFunction.name; FunctionBody mainBody = mainFunction.functionExpression.body; expect(range.startEnd(mainName, mainBody), new SourceRange(1, 9)); @@ -90,7 +96,8 @@ test_startLength_node() async { await resolveTestUnit(' main() {}'); - FunctionDeclaration mainFunction = testUnit.declarations[0]; + FunctionDeclaration mainFunction = + testUnit.declarations[0] as FunctionDeclaration; SimpleIdentifier mainName = mainFunction.name; expect(range.startLength(mainName, 10), new SourceRange(1, 10)); } @@ -101,7 +108,8 @@ test_startStart_nodeNode() async { await resolveTestUnit('main() {}'); - FunctionDeclaration mainFunction = testUnit.declarations[0]; + FunctionDeclaration mainFunction = + testUnit.declarations[0] as FunctionDeclaration; SimpleIdentifier mainName = mainFunction.name; FunctionBody mainBody = mainFunction.functionExpression.body; expect(range.startStart(mainName, mainBody), new SourceRange(0, 7)); @@ -109,7 +117,8 @@ test_token() async { await resolveTestUnit(' main() {}'); - FunctionDeclaration mainFunction = testUnit.declarations[0]; + FunctionDeclaration mainFunction = + testUnit.declarations[0] as FunctionDeclaration; SimpleIdentifier mainName = mainFunction.name; expect(range.token(mainName.beginToken), new SourceRange(1, 4)); }
diff --git a/pkg/dev_compiler/lib/src/analyzer/code_generator.dart b/pkg/dev_compiler/lib/src/analyzer/code_generator.dart index 32f7d96..ae1d5ef 100644 --- a/pkg/dev_compiler/lib/src/analyzer/code_generator.dart +++ b/pkg/dev_compiler/lib/src/analyzer/code_generator.dart
@@ -5718,6 +5718,10 @@ () => _emitConstList(elementType, _visitExpressionList(node.elements))); } + @override + JS.Expression visitSetLiteral(SetLiteral node) => + throw new UnsupportedError('literal sets are not yet supported'); + JS.Expression _emitConstList( DartType elementType, List<JS.Expression> elements) { // dart.constList helper internally depends on _interceptors.JSArray.
diff --git a/pkg/dev_compiler/lib/src/analyzer/driver.dart b/pkg/dev_compiler/lib/src/analyzer/driver.dart index 63d1223..ea9db64 100644 --- a/pkg/dev_compiler/lib/src/analyzer/driver.dart +++ b/pkg/dev_compiler/lib/src/analyzer/driver.dart
@@ -15,6 +15,7 @@ import 'package:analyzer/src/dart/analysis/file_state.dart'; import 'package:analyzer/src/dart/analysis/library_analyzer.dart'; import 'package:analyzer/src/dart/analysis/performance_logger.dart'; +import 'package:analyzer/src/dart/element/inheritance_manager2.dart'; import 'package:analyzer/src/generated/engine.dart'; import 'package:analyzer/src/generated/sdk.dart'; import 'package:analyzer/src/generated/source.dart'; @@ -324,8 +325,8 @@ (uri) => _isLibraryUri('$uri'), context, resynthesizer, - libraryFile, - _fsState.resourceProvider); + InheritanceManager2(context.typeSystem), + libraryFile); // TODO(jmesserly): ideally we'd use the existing public `analyze()` method, // but it's async. We can't use `async` here because it would break our // developer tools extension (see web/web_command.dart). We should be able
diff --git a/pkg/dev_compiler/lib/src/kernel/analyzer_to_kernel.dart b/pkg/dev_compiler/lib/src/kernel/analyzer_to_kernel.dart index a94f7f6..e7f7da5 100644 --- a/pkg/dev_compiler/lib/src/kernel/analyzer_to_kernel.dart +++ b/pkg/dev_compiler/lib/src/kernel/analyzer_to_kernel.dart
@@ -869,7 +869,7 @@ a.SummaryDataStore summaryData, String dartSdkPath) { var context = _createContextForSummaries(summaryData, dartSdkPath); return a.StoreBasedSummaryResynthesizer( - context, context.sourceFactory, /*strongMode*/ true, summaryData); + context, null, context.sourceFactory, /*strongMode*/ true, summaryData); } /// Creates a dummy Analyzer context so we can use summary resynthesizer.
diff --git a/pkg/front_end/lib/src/fasta/scanner.dart b/pkg/front_end/lib/src/fasta/scanner.dart index 8e24f03..f276eda 100644 --- a/pkg/front_end/lib/src/fasta/scanner.dart +++ b/pkg/front_end/lib/src/fasta/scanner.dart
@@ -83,12 +83,16 @@ /// Scan/tokenize the given [source]. /// If [recover] is null, then the [defaultRecoveryStrategy] is used. ScannerResult scanString(String source, - {bool includeComments: false, + {bool enableGtGtGt: false, + bool includeComments: false, bool scanLazyAssignmentOperators: false, Recover recover}) { + // TODO(brianwilkerson): Remove the parameter `enableGtGtGt` after the feature + // has been anabled by default. assert(source != null, 'source must not be null'); StringScanner scanner = new StringScanner(source, includeComments: includeComments); + scanner.enableGtGtGt = enableGtGtGt; return _tokenizeAndRecover(scanner, recover, source: source); }
diff --git a/pkg/front_end/pubspec.yaml b/pkg/front_end/pubspec.yaml index 97934cb..ad2abeb 100644 --- a/pkg/front_end/pubspec.yaml +++ b/pkg/front_end/pubspec.yaml
@@ -1,7 +1,7 @@ name: front_end # Currently, front_end API is not stable and users should not # depend on semver semantics when depending on this package. -version: 0.1.6+8 +version: 0.1.7 author: Dart Team <misc@dartlang.org> description: Front end for compilation of Dart code. homepage: https://github.com/dart-lang/sdk/tree/master/pkg/front_end @@ -11,14 +11,14 @@ charcode: '^1.1.1' convert: '^2.0.1' crypto: '^2.0.2' - kernel: 0.3.6+8 + kernel: 0.3.7 meta: '^1.1.1' package_config: '^1.0.1' path: '^1.3.9' source_span: '^1.2.3' yaml: '^2.1.12' dev_dependencies: - analyzer: '^0.33.6' + analyzer: 0.34.0 args: '>=0.13.0 <2.0.0' build_integration: path: ../build_integration
diff --git a/pkg/kernel/pubspec.yaml b/pkg/kernel/pubspec.yaml index 0be2276..04f64a9 100644 --- a/pkg/kernel/pubspec.yaml +++ b/pkg/kernel/pubspec.yaml
@@ -1,7 +1,7 @@ name: kernel # Currently, kernel API is not stable and users should # not depend on semver semantics when depending on this package. -version: 0.3.6+8 +version: 0.3.7 author: Dart Team <misc@dartlang.org> description: Dart IR (Intermediate Representation) homepage: https://github.com/dart-lang/sdk/tree/master/pkg/kernel @@ -11,7 +11,7 @@ path: ^1.3.9 args: '>=0.13.4 <2.0.0' dev_dependencies: - front_end: 0.1.6+8 + front_end: 0.1.7 test: ^1.3.4 stack_trace: ^1.6.6 test_reflective_loader: ^0.1.0
diff --git a/tests/co19_2/co19_2-analyzer.status b/tests/co19_2/co19_2-analyzer.status index a13758c..c111847 100644 --- a/tests/co19_2/co19_2-analyzer.status +++ b/tests/co19_2/co19_2-analyzer.status
@@ -174,11 +174,9 @@ LanguageFeatures/Set-literals/non_constant_set_literals_A01_t01: CompileTimeError # This feature is not implemented yet LanguageFeatures/Set-literals/non_constant_set_literals_A02_t01: CompileTimeError # This feature is not implemented yet LanguageFeatures/Set-literals/semantics_A04_t01: CompileTimeError # This feature is not implemented yet -LanguageFeatures/Set-literals/semantics_A05_t01: CompileTimeError # This feature is not implemented yet LanguageFeatures/Set-literals/set_literals_A01_t01: CompileTimeError # This feature is not implemented yet LanguageFeatures/Set-literals/set_literals_A02_t01: CompileTimeError # This feature is not implemented yet LanguageFeatures/Set-literals/set_literals_A04_t01: CompileTimeError # This feature is not implemented yet -LanguageFeatures/Simple-bounds/dynamic/class_typedef_l1_t02: CompileTimeError LanguageFeatures/Simple-bounds/static/class_typedef_l1_t01/none: CompileTimeError LanguageFeatures/Simple-bounds/static/class_typedef_l1_t02/none: CompileTimeError LanguageFeatures/Simple-bounds/static/class_typedef_l1_t03/none: CompileTimeError @@ -199,7 +197,6 @@ LanguageFeatures/Super-mixins/covariance_t03: MissingCompileTimeError # Issue 35111 LanguageFeatures/Super-mixins/covariance_t06: MissingCompileTimeError # Issue 35111 LanguageFeatures/Super-mixins/covariance_t07: MissingCompileTimeError # Issue 35111 -LanguageFeatures/Super-mixins/super_invocation_t19: CompileTimeError # Issue 35090 LanguageFeatures/regression/33585_t01: MissingCompileTimeError # Please triage this failure LanguageFeatures/regression/33585_t02: MissingCompileTimeError # Please triage this failure LanguageFeatures/regression/33597_t01: MissingCompileTimeError # Please triage this failure
diff --git a/tests/language_2/issue34489_test.dart b/tests/language_2/issue34489_test.dart new file mode 100644 index 0000000..59553a3 --- /dev/null +++ b/tests/language_2/issue34489_test.dart
@@ -0,0 +1,11 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +class C<T> { + var field = T; +} + +main() { + new C().field = 'bad'; //# 01: compile-time error +}
diff --git a/tests/language_2/issue34495_test.dart b/tests/language_2/issue34495_test.dart new file mode 100644 index 0000000..e599403 --- /dev/null +++ b/tests/language_2/issue34495_test.dart
@@ -0,0 +1,7 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +final foo = A<B>.foo(); //# 01: compile-time error + +main() {}
diff --git a/tests/language_2/issue35043_test.dart b/tests/language_2/issue35043_test.dart new file mode 100644 index 0000000..95c5f13 --- /dev/null +++ b/tests/language_2/issue35043_test.dart
@@ -0,0 +1,7 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +final foo = Map<int>(); //# 01: compile-time error + +main() {}
diff --git a/tests/language_2/issue35090_test.dart b/tests/language_2/issue35090_test.dart new file mode 100644 index 0000000..3e3c564 --- /dev/null +++ b/tests/language_2/issue35090_test.dart
@@ -0,0 +1,32 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import "package:expect/expect.dart"; + +class A { + int get g => 0; +} + +class C implements A { + noSuchMethod(Invocation i) { + return 1; + } +} + +mixin M on A { + int test() { + return super.g; + } + + noSuchMethod(Invocation i) { + return 2; + } +} + +class MA extends C with M {} + +main() { + Expect.equals(new MA().g, 2); + Expect.equals(new MA().test(), 2); +}
diff --git a/tests/language_2/language_2_analyzer.status b/tests/language_2/language_2_analyzer.status index a1c001a..e48117e 100644 --- a/tests/language_2/language_2_analyzer.status +++ b/tests/language_2/language_2_analyzer.status
@@ -11,7 +11,6 @@ accessor_conflict_import_prefixed2_test: CompileTimeError # Issue 25626 accessor_conflict_import_prefixed_test: CompileTimeError # Issue 25626 accessor_conflict_import_test: CompileTimeError # Issue 25626 -additional_interface_adds_optional_args_test: CompileTimeError # Issue #30568 cascaded_forwarding_stubs_test: CompileTimeError # Issue 34329 config_import_corelib_test: CompileTimeError, StaticWarning, OK # failing-by-design: Will never pass, see Issue #34332 const_cast2_test/01: CompileTimeError # failing-by-design: Not a const expression, see Issue #34334 @@ -72,12 +71,10 @@ large_class_declaration_test: Slow, Pass malformed2_test: Pass, MissingCompileTimeError # Flaky: issue 31056. mixin_declaration/mixin_declaration_factory_test/02: Crash # Issue 34809 -mixin_declaration/mixin_declaration_invalid_superinvocation_test/10: CompileTimeError # Issue 30552 mixin_method_override_test/01: MissingCompileTimeError mixin_super_2_test: CompileTimeError mixin_super_use_test: CompileTimeError mock_writable_final_private_field_test: CompileTimeError # failing-by-design, see Issue #34377 -multiple_interface_inheritance_test: CompileTimeError # Issue 30552 nested_generic_closure_test: CompileTimeError # Issue #28515 no_main_test/01: Fail # failing-by-design, the analyzer has no restriction that a library include a main function. no_such_constructor2_test: StaticWarning @@ -94,16 +91,13 @@ regress_29025_test: CompileTimeError # Issue 29081 regress_29405_test: CompileTimeError # Issue 29421 regress_29784_test/02: MissingCompileTimeError # Issue 29784 -regress_30121_test: CompileTimeError # Issue 31087 regress_30339_test: CompileTimeError regress_33479_test/01: Crash # Issue #33479 set_literals/*: Skip setter3_test/01: CompileTimeError # Invalid test, see https://github.com/dart-lang/sdk/issues/33837 setter3_test/02: CompileTimeError # Invalid test, see https://github.com/dart-lang/sdk/issues/33837 super_bound_closure_test/none: CompileTimeError -super_no_such_method1_test: CompileTimeError # Invalid test, probably, see https://github.com/dart-lang/sdk/issues/33963 -super_no_such_method2_test: CompileTimeError # Invalid test, probably, see https://github.com/dart-lang/sdk/issues/33963 -super_no_such_method3_test: CompileTimeError # Invalid test, probably, see https://github.com/dart-lang/sdk/issues/33963 +super_call4_test/01: MissingCompileTimeError super_setter_test: CompileTimeError # Invalid test, see https://github.com/dart-lang/sdk/issues/33837 syntax_test/60: MissingCompileTimeError syntax_test/61: MissingCompileTimeError
diff --git a/tests/language_2/language_2_dartdevc.status b/tests/language_2/language_2_dartdevc.status index f8c2bfc..3816f84 100644 --- a/tests/language_2/language_2_dartdevc.status +++ b/tests/language_2/language_2_dartdevc.status
@@ -10,7 +10,6 @@ accessor_conflict_import_prefixed2_test: CompileTimeError # Issue 25626 accessor_conflict_import_prefixed_test: CompileTimeError # Issue 25626 accessor_conflict_import_test: CompileTimeError # Issue 25626 -additional_interface_adds_optional_args_test: CompileTimeError # Issue #30568 assertion_test: RuntimeError # Issue 30326; Expect.equals(expected: <1>, actual: <0>) fails. async_star_test/01: RuntimeError async_star_test/03: RuntimeError @@ -84,7 +83,7 @@ invalid_returns/sync_invalid_return_03_test/none: CompileTimeError # issue #34319 invalid_returns/sync_invalid_return_04_test/none: CompileTimeError # issue #34319 invalid_returns/sync_invalid_return_05_test/none: CompileTimeError # issue #34319 -issue31596_implement_covariant_test: CompileTimeError +issue31596_implement_covariant_test: CompileTimeError # Issue #31596 issue31596_override_test/01: CompileTimeError issue31596_override_test/02: CompileTimeError issue31596_override_test/03: CompileTimeError @@ -102,12 +101,10 @@ large_class_declaration_test: Slow, Pass left_shift_test: RuntimeError # Ints and doubles are unified. mixin_declaration/mixin_declaration_factory_test/02: Crash -mixin_declaration/mixin_declaration_invalid_superinvocation_test/10: CompileTimeError # Analyzer chooses wrong(?) super method. mixin_method_override_test/01: MissingCompileTimeError mixin_super_2_test: CompileTimeError # Issue 34806 mixin_super_use_test: CompileTimeError # Issue 34806 mock_writable_final_private_field_test: CompileTimeError # Issue 30848 -multiple_interface_inheritance_test: CompileTimeError # Issue 30552 nested_generic_closure_test: CompileTimeError override_inheritance_field_test/42: CompileTimeError part_of_multiple_libs_test/01: MissingCompileTimeError @@ -122,7 +119,6 @@ regress_29405_test: CompileTimeError # Issue 29421 regress_29784_test/02: Crash # assert initializers not implemented regress_29784_test/02: MissingCompileTimeError -regress_30121_test: CompileTimeError # Issue 31087 regress_30339_test: CompileTimeError # As expected. Should we make this a multi test? regress_33479_test/01: Crash # Issue #33479 set_literals/*: Skip @@ -130,9 +126,7 @@ setter3_test/02: CompileTimeError # Invalid test, see https://github.com/dart-lang/sdk/issues/33837 stacktrace_test: RuntimeError # Issue 29920 super_bound_closure_test/none: CompileTimeError -super_no_such_method1_test: CompileTimeError # Invalid test, probably, see https://github.com/dart-lang/sdk/issues/33963 -super_no_such_method2_test: CompileTimeError # Invalid test, probably, see https://github.com/dart-lang/sdk/issues/33963 -super_no_such_method3_test: CompileTimeError # Invalid test, probably, see https://github.com/dart-lang/sdk/issues/33963 +super_call4_test/01: MissingCompileTimeError super_operator_index5_test: RuntimeError # 33470 super_operator_index7_test: RuntimeError # 33470 super_operator_index8_test: RuntimeError # 33470
diff --git a/tools/FAKE_COMMITS b/tools/FAKE_COMMITS index fbe07a6..14748a9 100644 --- a/tools/FAKE_COMMITS +++ b/tools/FAKE_COMMITS
@@ -24,3 +24,6 @@ Trigger mirroring of github repository Force build after DEPS format revert Force build while trybots are broken, to check builders for brokenness. + +Analyzer branch commits: +Force build on new analyzer-branch linux build with new workflow \ No newline at end of file
diff --git a/tools/bots/test_matrix.json b/tools/bots/test_matrix.json index b2d6139..e2ac026 100644 --- a/tools/bots/test_matrix.json +++ b/tools/bots/test_matrix.json
@@ -1375,7 +1375,11 @@ "builders": [ "analyzer-linux-release", "analyzer-mac-release", - "analyzer-win-release" + "analyzer-win-release", + "analyzer-linux-release-analyzer", + "analyzer-linux-release-analyzer-new", + "analyzer-mac-release-analyzer", + "analyzer-win-release-analyzer" ], "meta": { "description": "This configuration is used by the analyzer builders." @@ -1440,7 +1444,10 @@ ] }, { - "builders": ["analyzer-analysis-server-linux"], + "builders": [ + "analyzer-analysis-server-linux", + "analyzer-analysis-server-linux-analyzer" + ], "meta": { "description": "Analyze analyzer related packages." },
diff --git a/tools/testing/dart/options.dart b/tools/testing/dart/options.dart index 7bd82b8..e9b648c 100644 --- a/tools/testing/dart/options.dart +++ b/tools/testing/dart/options.dart
@@ -634,7 +634,7 @@ // Expand compilers. for (var compiler in compilers) { // Expand modes. - String modes = data["mode"] ?? compiler.defaultMode.name; + String modes = (data["mode"] as String) ?? compiler.defaultMode.name; if (modes == "all") modes = "debug,release,product"; for (var modeName in modes.split(",")) { var mode = Mode.find(modeName);
diff --git a/tools/testing/dart/test_suite.dart b/tools/testing/dart/test_suite.dart index 0666aff..cb2ca1e 100644 --- a/tools/testing/dart/test_suite.dart +++ b/tools/testing/dart/test_suite.dart
@@ -896,7 +896,7 @@ compilationArtifact); Map<String, String> environment = environmentOverrides; - Map<String, String> extraEnv = info.optionsFromFile['environment']; + var extraEnv = info.optionsFromFile['environment'] as Map<String, String>; if (extraEnv != null) { environment = new Map.from(environment)..addAll(extraEnv); }