Version 2.11.0-193.0.dev
Merge commit '2a649d3ef03870308ea945c1c7a873dfe19c54a1' into 'dev'
diff --git a/pkg/_fe_analyzer_shared/test/flow_analysis/flow_analysis_test.dart b/pkg/_fe_analyzer_shared/test/flow_analysis/flow_analysis_test.dart
index b7b9be9..f90a68a 100644
--- a/pkg/_fe_analyzer_shared/test/flow_analysis/flow_analysis_test.dart
+++ b/pkg/_fe_analyzer_shared/test/flow_analysis/flow_analysis_test.dart
@@ -2954,7 +2954,7 @@
var unreachable = reachable.setUnreachable();
expect(reachable.restrict(h, reachable, Set()), same(reachable));
expect(reachable.restrict(h, unreachable, Set()), same(unreachable));
- expect(unreachable.restrict(h, unreachable, Set()), same(unreachable));
+ expect(unreachable.restrict(h, reachable, Set()), same(unreachable));
expect(unreachable.restrict(h, unreachable, Set()), same(unreachable));
});
diff --git a/pkg/analysis_server/lib/src/cider/completion.dart b/pkg/analysis_server/lib/src/cider/completion.dart
index 26e9582..7864fa2 100644
--- a/pkg/analysis_server/lib/src/cider/completion.dart
+++ b/pkg/analysis_server/lib/src/cider/completion.dart
@@ -107,7 +107,7 @@
});
performance.getDataInt('count').add(result.length);
- return result;
+ return result.toList();
},
);
diff --git a/pkg/analyzer/lib/error/error.dart b/pkg/analyzer/lib/error/error.dart
index 70db8db..8cd4882 100644
--- a/pkg/analyzer/lib/error/error.dart
+++ b/pkg/analyzer/lib/error/error.dart
@@ -493,6 +493,7 @@
HintCode.INFERENCE_FAILURE_ON_UNTYPED_PARAMETER,
HintCode.INVALID_ANNOTATION_TARGET,
HintCode.INVALID_EXPORT_OF_INTERNAL_ELEMENT,
+ HintCode.INVALID_EXPORT_OF_INTERNAL_ELEMENT_INDIRECTLY,
HintCode.INVALID_FACTORY_ANNOTATION,
HintCode.INVALID_FACTORY_METHOD_DECL,
HintCode.INVALID_FACTORY_METHOD_IMPL,
diff --git a/pkg/analyzer/lib/src/dart/element/element.dart b/pkg/analyzer/lib/src/dart/element/element.dart
index 77c0646..a87e07a 100644
--- a/pkg/analyzer/lib/src/dart/element/element.dart
+++ b/pkg/analyzer/lib/src/dart/element/element.dart
@@ -42,6 +42,7 @@
import 'package:analyzer/src/generated/utilities_dart.dart';
import 'package:analyzer/src/generated/utilities_general.dart';
import 'package:analyzer/src/summary/idl.dart';
+import 'package:analyzer/src/summary2/linked_element_builder.dart';
import 'package:analyzer/src/summary2/linked_unit_context.dart';
import 'package:analyzer/src/summary2/reference.dart';
import 'package:analyzer/src/util/comment.dart';
@@ -1297,16 +1298,15 @@
if (_enums != null) return _enums;
if (linkedNode != null) {
- var containerRef = reference.getChild('@enum');
CompilationUnit linkedNode = this.linkedNode;
- _enums = linkedNode.declarations.whereType<EnumDeclaration>().map((node) {
- var name = node.name.name;
- var reference = containerRef.getChild(name);
- if (reference.hasElementFor(node)) {
- return reference.element as EnumElementImpl;
+ _enums = <ClassElement>[];
+ for (var node in linkedNode.declarations) {
+ if (node is EnumDeclaration) {
+ var element = _elementBuilder.enumDeclaration(node);
+ _enums.add(element);
}
- return EnumElementImpl.forLinkedNode(this, reference, node);
- }).toList();
+ }
+ return _enums;
}
return _enums ??= const <ClassElement>[];
@@ -1328,19 +1328,11 @@
if (linkedNode != null) {
CompilationUnit linkedNode = this.linkedNode;
- var containerRef = reference.getChild('@extension');
_extensions = <ExtensionElement>[];
for (var node in linkedNode.declarations) {
if (node is ExtensionDeclaration) {
- var refName = linkedContext.getExtensionRefName(node);
- var reference = containerRef.getChild(refName);
- if (reference.hasElementFor(node)) {
- _extensions.add(reference.element);
- } else {
- _extensions.add(
- ExtensionElementImpl.forLinkedNode(this, reference, node),
- );
- }
+ var element = _elementBuilder.extensionDeclaration(node);
+ _extensions.add(element);
}
}
return _extensions;
@@ -1363,18 +1355,14 @@
if (linkedNode != null) {
CompilationUnit linkedNode = this.linkedNode;
- var containerRef = reference.getChild('@function');
- return _functions = linkedNode.declarations
- .whereType<FunctionDeclaration>()
- .where((node) => !node.isGetter && !node.isSetter)
- .map((node) {
- var name = node.name.name;
- var reference = containerRef.getChild(name);
- if (reference.hasElementFor(node)) {
- return reference.element as FunctionElementImpl;
+ _functions = <FunctionElement>[];
+ for (var node in linkedNode.declarations) {
+ if (node is FunctionDeclaration && node.propertyKeyword == null) {
+ var element = _elementBuilder.functionDeclaration(node);
+ _functions.add(element as FunctionElement);
}
- return FunctionElementImpl.forLinkedNode(this, reference, node);
- }).toList();
+ }
+ return _functions;
}
return _functions ?? const <FunctionElement>[];
}
@@ -1394,23 +1382,17 @@
if (linkedNode != null) {
CompilationUnit linkedNode = this.linkedNode;
- var containerRef = reference.getChild('@typeAlias');
- return _typeAliases = linkedNode.declarations.where((node) {
- return node is FunctionTypeAlias || node is GenericTypeAlias;
- }).map((node) {
- String name;
+ _typeAliases = <FunctionTypeAliasElement>[];
+ for (var node in linkedNode.declarations) {
if (node is FunctionTypeAlias) {
- name = node.name.name;
- } else {
- name = (node as GenericTypeAlias).name.name;
+ var element = _elementBuilder.functionTypeAlias(node);
+ _typeAliases.add(element);
+ } else if (node is GenericTypeAlias) {
+ var element = _elementBuilder.genericTypeAlias(node);
+ _typeAliases.add(element);
}
-
- var reference = containerRef.getChild(name);
- if (reference.hasElementFor(node)) {
- return reference.element as GenericTypeAliasElementImpl;
- }
- return GenericTypeAliasElementImpl.forLinkedNode(this, reference, node);
- }).toList();
+ }
+ return _typeAliases;
}
return _typeAliases ?? const <FunctionTypeAliasElement>[];
@@ -1442,16 +1424,14 @@
if (linkedNode != null) {
CompilationUnit linkedNode = this.linkedNode;
- var containerRef = reference.getChild('@mixin');
- var declarations = linkedNode.declarations;
- return _mixins = declarations.whereType<MixinDeclaration>().map((node) {
- var name = node.name.name;
- var reference = containerRef.getChild(name);
- if (reference.hasElementFor(node)) {
- return reference.element as MixinElementImpl;
+ _mixins = <ClassElement>[];
+ for (var node in linkedNode.declarations) {
+ if (node is MixinDeclaration) {
+ var element = _elementBuilder.mixinDeclaration(node);
+ _mixins.add(element);
}
- return MixinElementImpl.forLinkedNode(this, reference, node);
- }).toList();
+ }
+ return _mixins;
}
return _mixins ?? const <ClassElement>[];
@@ -1503,24 +1483,14 @@
if (linkedNode != null) {
CompilationUnit linkedNode = this.linkedNode;
- var containerRef = reference.getChild('@class');
_types = <ClassElement>[];
for (var node in linkedNode.declarations) {
- String name;
if (node is ClassDeclaration) {
- name = node.name.name;
+ var element = _elementBuilder.classDeclaration(node);
+ _types.add(element);
} else if (node is ClassTypeAlias) {
- name = node.name.name;
- } else {
- continue;
- }
- var reference = containerRef.getChild(name);
- if (reference.hasElementFor(node)) {
- _types.add(reference.element);
- } else {
- _types.add(
- ClassElementImpl.forLinkedNode(this, reference, node),
- );
+ var element = _elementBuilder.classTypeAlias(node);
+ _types.add(element);
}
}
return _types;
@@ -1653,18 +1623,13 @@
var variableList = <TopLevelVariableElement>[];
variableMap[unit] = variableList;
+ var elementBuilder = unit._elementBuilder;
var unitNode = unit.linkedContext.unit_withDeclarations;
var unitDeclarations = unitNode.declarations;
var variables = context.topLevelVariables(unitNode);
for (var variable in variables) {
- var name = variable.name.name;
- var reference = unit.reference.getChild('@variable').getChild(name);
- var variableElement = TopLevelVariableElementImpl.forLinkedNodeFactory(
- unit,
- reference,
- variable,
- );
+ var variableElement = elementBuilder.topLevelVariable(variable);
variableList.add(variableElement);
accessorList.add(variableElement.getter);
@@ -1680,15 +1645,9 @@
if (!isGetter && !isSetter) continue;
var name = node.name.name;
- var containerRef = isGetter
- ? unit.reference.getChild('@getter')
- : unit.reference.getChild('@setter');
- var accessorElement = PropertyAccessorElementImpl.forLinkedNode(
- unit,
- containerRef.getChild(name),
- node,
- );
+ var accessorElement = elementBuilder.functionDeclaration(node)
+ as PropertyAccessorElementImpl;
accessorList.add(accessorElement);
var fieldRef = unit.reference.getChild('@field').getChild(name);
@@ -3029,6 +2988,10 @@
return _enclosingElement?.typeParameterContext;
}
+ LinkedElementBuilder get _elementBuilder {
+ return linkedContext.elementBuilder;
+ }
+
NullabilitySuffix get _noneOrStarSuffix {
return library?.isNonNullableByDefault == true
? NullabilitySuffix.none
diff --git a/pkg/analyzer/lib/src/dart/error/hint_codes.dart b/pkg/analyzer/lib/src/dart/error/hint_codes.dart
index 1e0761f..1d0e15f4 100644
--- a/pkg/analyzer/lib/src/dart/error/hint_codes.dart
+++ b/pkg/analyzer/lib/src/dart/error/hint_codes.dart
@@ -590,6 +590,19 @@
correction: "Try using a hide clause to hide '{0}'.");
/**
+ * This hint is generated anywhere where an element annotated with `@internal`
+ * is exported indirectly as a part of a package's public API.
+ *
+ * Parameters:
+ * 0: the name of the element
+ */
+ static const HintCode INVALID_EXPORT_OF_INTERNAL_ELEMENT_INDIRECTLY = HintCode(
+ 'INVALID_EXPORT_OF_INTERNAL_ELEMENT_INDIRECTLY',
+ "The member '{0}' can't be exported as a part of a package's public "
+ "API, but is indirectly exported as part of the signature of '{1}'.",
+ correction: "Try using a hide clause to hide '{0}'.");
+
+ /**
* This hint is generated anywhere a @factory annotation is associated with
* anything other than a method.
*/
diff --git a/pkg/analyzer/lib/src/dart/micro/resolve_file.dart b/pkg/analyzer/lib/src/dart/micro/resolve_file.dart
index 4b12e9d..1547218 100644
--- a/pkg/analyzer/lib/src/dart/micro/resolve_file.dart
+++ b/pkg/analyzer/lib/src/dart/micro/resolve_file.dart
@@ -153,9 +153,7 @@
// Remove libraries represented by removed files.
// If we need these libraries later, we will relink and reattach them.
if (libraryContext != null) {
- libraryContext.elementFactory.removeLibraries(
- removedFiles.map((e) => e.uriStr).toList(),
- );
+ libraryContext.remove(removedFiles);
}
}
@@ -591,8 +589,11 @@
this.contextObjects,
this.librariesLog,
) {
- // TODO(scheglov) remove it?
- _createElementFactory();
+ elementFactory = LinkedElementFactory(
+ contextObjects.analysisContext,
+ contextObjects.analysisSession,
+ Reference.root(),
+ );
}
/// Load data required to access elements of the given [targetLibrary].
@@ -693,8 +694,9 @@
// the element factory - it is empty anyway.
if (!elementFactory.hasDartCore) {
contextObjects.analysisContext.clearTypeProvider();
- _createElementFactory();
+ elementFactory.declareDartCoreDynamicNever();
}
+
var cBundle = CiderLinkedLibraryCycle.fromBuffer(bytes);
inputBundles.add(cBundle.bundle);
elementFactory.addBundle(
@@ -722,29 +724,19 @@
'[librariesLinkedTimer: ${librariesLinkedTimer.elapsedMilliseconds} ms]',
);
});
-
- // There might be a rare (and wrong) situation, when the external summaries
- // already include the [targetLibrary]. When this happens, [loadBundle]
- // exists without doing any work. But the type provider must be created.
- _createElementFactoryTypeProvider();
}
- void _createElementFactory() {
- elementFactory = LinkedElementFactory(
- contextObjects.analysisContext,
- contextObjects.analysisSession,
- Reference.root(),
+ /// Remove libraries represented by the [removed] files.
+ /// If we need these libraries later, we will relink and reattach them.
+ void remove(List<FileState> removed) {
+ elementFactory.removeLibraries(
+ removed.map((e) => e.uriStr).toList(),
);
- }
- /// Ensure that type provider is created.
- void _createElementFactoryTypeProvider() {
- var analysisContext = contextObjects.analysisContext;
- if (analysisContext.typeProviderNonNullableByDefault == null) {
- var dartCore = elementFactory.libraryOfUri('dart:core');
- var dartAsync = elementFactory.libraryOfUri('dart:async');
- elementFactory.createTypeProviders(dartCore, dartAsync);
- }
+ var removedSet = removed.toSet();
+ loadedBundles.removeWhere((cycle) {
+ return cycle.libraries.any(removedSet.contains);
+ });
}
static CiderLinkedLibraryCycleBuilder serializeBundle(
diff --git a/pkg/analyzer/lib/src/error/best_practices_verifier.dart b/pkg/analyzer/lib/src/error/best_practices_verifier.dart
index 66e0d5c..7b3407fd 100644
--- a/pkg/analyzer/lib/src/error/best_practices_verifier.dart
+++ b/pkg/analyzer/lib/src/error/best_practices_verifier.dart
@@ -1072,6 +1072,22 @@
HintCode.INVALID_EXPORT_OF_INTERNAL_ELEMENT,
node,
[element.displayName]);
+ } else if (element is FunctionElement) {
+ var signatureTypes = [
+ ...element.parameters.map((p) => p.type),
+ element.returnType,
+ ...element.typeParameters.map((tp) => tp.bound),
+ ];
+ for (var type in signatureTypes) {
+ var typeElement = type?.element?.enclosingElement;
+ if (typeElement is GenericTypeAliasElement &&
+ typeElement.hasInternal) {
+ _errorReporter.reportErrorForNode(
+ HintCode.INVALID_EXPORT_OF_INTERNAL_ELEMENT_INDIRECTLY,
+ node,
+ [typeElement.name, element.displayName]);
+ }
+ }
}
});
}
diff --git a/pkg/analyzer/lib/src/summary2/linked_element_builder.dart b/pkg/analyzer/lib/src/summary2/linked_element_builder.dart
new file mode 100644
index 0000000..fcfc0d3
--- /dev/null
+++ b/pkg/analyzer/lib/src/summary2/linked_element_builder.dart
@@ -0,0 +1,198 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. 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/ast/ast.dart';
+import 'package:analyzer/src/dart/element/element.dart';
+import 'package:analyzer/src/summary2/linked_unit_context.dart';
+import 'package:analyzer/src/summary2/reference.dart';
+
+class LinkedElementBuilder {
+ final CompilationUnitElementImpl _unitElement;
+ final Reference _classRef;
+ final Reference _enumRef;
+ final Reference _extensionRef;
+ final Reference _functionRef;
+ final Reference _getterRef;
+ final Reference _mixinRef;
+ final Reference _setterRef;
+ final Reference _typeAliasRef;
+ final Reference _variableRef;
+
+ var _nextUnnamedExtensionId = 0;
+
+ LinkedElementBuilder(LinkedUnitContext unitContext)
+ : _unitElement = unitContext.reference.element,
+ _classRef = unitContext.reference.getChild('@class'),
+ _enumRef = unitContext.reference.getChild('@enum'),
+ _extensionRef = unitContext.reference.getChild('@extension'),
+ _functionRef = unitContext.reference.getChild('@function'),
+ _getterRef = unitContext.reference.getChild('@getter'),
+ _mixinRef = unitContext.reference.getChild('@mixin'),
+ _setterRef = unitContext.reference.getChild('@setter'),
+ _typeAliasRef = unitContext.reference.getChild('@typeAlias'),
+ _variableRef = unitContext.reference.getChild('@variable');
+
+ ClassElementImpl classDeclaration(ClassDeclaration node) {
+ var element = node.declaredElement as ClassElementImpl;
+ if (element != null) {
+ return element;
+ }
+
+ var nameNode = node.name;
+ element = ClassElementImpl.forLinkedNode(
+ _unitElement,
+ _classRef.getChild(nameNode.name),
+ node,
+ );
+ nameNode.staticElement = element;
+ return element;
+ }
+
+ ClassElementImpl classTypeAlias(ClassTypeAlias node) {
+ var element = node.declaredElement as ClassElementImpl;
+ if (element != null) {
+ return element;
+ }
+
+ var nameNode = node.name;
+ element = ClassElementImpl.forLinkedNode(
+ _unitElement,
+ _classRef.getChild(nameNode.name),
+ node,
+ );
+ nameNode.staticElement = element;
+ return element;
+ }
+
+ EnumElementImpl enumDeclaration(EnumDeclaration node) {
+ var element = node.declaredElement as EnumElementImpl;
+ if (element != null) {
+ return element;
+ }
+
+ var nameNode = node.name;
+ element = EnumElementImpl.forLinkedNode(
+ _unitElement,
+ _enumRef.getChild(nameNode.name),
+ node,
+ );
+ nameNode.staticElement = element;
+ return element;
+ }
+
+ ExtensionElementImpl extensionDeclaration(ExtensionDeclarationImpl node) {
+ var element = node.declaredElement as ExtensionElementImpl;
+ if (element != null) {
+ return element;
+ }
+
+ var name = node.name?.name;
+ var refName = name ?? 'extension-${_nextUnnamedExtensionId++}';
+ element = ExtensionElementImpl.forLinkedNode(
+ _unitElement,
+ _extensionRef.getChild(refName),
+ node,
+ );
+ node.declaredElement = element;
+ return element;
+ }
+
+ ExecutableElementImpl functionDeclaration(FunctionDeclaration node) {
+ var element = node.declaredElement as ExecutableElementImpl;
+ if (element != null) {
+ return element;
+ }
+
+ var nameNode = node.name;
+ var name = nameNode.name;
+
+ if (node.isGetter) {
+ element = PropertyAccessorElementImpl.forLinkedNode(
+ _unitElement,
+ _getterRef.getChild(name),
+ node,
+ );
+ } else if (node.isSetter) {
+ element = PropertyAccessorElementImpl.forLinkedNode(
+ _unitElement,
+ _setterRef.getChild(name),
+ node,
+ );
+ } else {
+ element = FunctionElementImpl.forLinkedNode(
+ _unitElement,
+ _functionRef.getChild(name),
+ node,
+ );
+ }
+
+ nameNode.staticElement = element;
+ return element;
+ }
+
+ GenericTypeAliasElementImpl functionTypeAlias(FunctionTypeAlias node) {
+ var element = node.declaredElement as GenericTypeAliasElementImpl;
+ if (element != null) {
+ return element;
+ }
+
+ var nameNode = node.name;
+ element = GenericTypeAliasElementImpl.forLinkedNode(
+ _unitElement,
+ _typeAliasRef.getChild(nameNode.name),
+ node,
+ );
+ nameNode.staticElement = element;
+ return element;
+ }
+
+ GenericTypeAliasElementImpl genericTypeAlias(GenericTypeAlias node) {
+ var element = node.declaredElement as GenericTypeAliasElementImpl;
+ if (element != null) {
+ return element;
+ }
+
+ var nameNode = node.name;
+ element = GenericTypeAliasElementImpl.forLinkedNode(
+ _unitElement,
+ _typeAliasRef.getChild(nameNode.name),
+ node,
+ );
+ nameNode.staticElement = element;
+ return element;
+ }
+
+ MixinElementImpl mixinDeclaration(MixinDeclaration node) {
+ var element = node.declaredElement as MixinElementImpl;
+ if (element != null) {
+ return element;
+ }
+
+ var nameNode = node.name;
+ element = MixinElementImpl.forLinkedNode(
+ _unitElement,
+ _mixinRef.getChild(nameNode.name),
+ node,
+ );
+ nameNode.staticElement = element;
+ return element;
+ }
+
+ TopLevelVariableElementImpl topLevelVariable(VariableDeclaration node) {
+ var element = node.declaredElement as TopLevelVariableElementImpl;
+ if (element != null) {
+ return element;
+ }
+
+ var nameNode = node.name;
+ element = TopLevelVariableElementImpl.forLinkedNodeFactory(
+ _unitElement,
+ _variableRef.getChild(nameNode.name),
+ node,
+ );
+ nameNode.staticElement = element;
+ return element;
+ }
+}
diff --git a/pkg/analyzer/lib/src/summary2/linked_element_factory.dart b/pkg/analyzer/lib/src/summary2/linked_element_factory.dart
index caeb168..b47435a 100644
--- a/pkg/analyzer/lib/src/summary2/linked_element_factory.dart
+++ b/pkg/analyzer/lib/src/summary2/linked_element_factory.dart
@@ -31,9 +31,7 @@
) {
ArgumentError.checkNotNull(analysisContext, 'analysisContext');
ArgumentError.checkNotNull(analysisSession, 'analysisSession');
- var dartCoreRef = rootReference.getChild('dart:core');
- dartCoreRef.getChild('dynamic').element = DynamicElementImpl.instance;
- dartCoreRef.getChild('Never').element = NeverElementImpl.instance;
+ declareDartCoreDynamicNever();
}
CoreTypes get coreTypes {
@@ -104,6 +102,12 @@
}
}
+ void declareDartCoreDynamicNever() {
+ var dartCoreRef = rootReference.getChild('dart:core');
+ dartCoreRef.getChild('dynamic').element = DynamicElementImpl.instance;
+ dartCoreRef.getChild('Never').element = NeverElementImpl.instance;
+ }
+
Element elementOfReference(Reference reference) {
if (reference.element != null) {
return reference.element;
@@ -333,8 +337,14 @@
_indexUnitElementDeclarations(unit);
assert(reference.node != null, '$reference');
}
- ClassElementImpl.forLinkedNode(unit, reference, reference.node);
- return reference.element;
+
+ var elementBuilder = unit.linkedContext.elementBuilder;
+ var node = reference.node;
+ if (node is ClassDeclaration) {
+ return elementBuilder.classDeclaration(node);
+ } else {
+ return elementBuilder.classTypeAlias(node);
+ }
}
ConstructorElementImpl _constructor(
@@ -410,8 +420,8 @@
_indexUnitElementDeclarations(unit);
assert(reference.node != null, '$reference');
}
- EnumElementImpl.forLinkedNode(unit, reference, reference.node);
- return reference.element;
+ var elementBuilder = unit.linkedContext.elementBuilder;
+ return elementBuilder.enumDeclaration(reference.node);
}
ExtensionElementImpl _extension(
@@ -420,8 +430,8 @@
_indexUnitElementDeclarations(unit);
assert(reference.node != null, '$reference');
}
- ExtensionElementImpl.forLinkedNode(unit, reference, reference.node);
- return reference.element;
+ var elementBuilder = unit.linkedContext.elementBuilder;
+ return elementBuilder.extensionDeclaration(reference.node);
}
FieldElementImpl _field(ClassElementImpl enclosing, Reference reference) {
@@ -463,8 +473,8 @@
_indexUnitElementDeclarations(unit);
assert(reference.node != null, '$reference');
}
- MixinElementImpl.forLinkedNode(unit, reference, reference.node);
- return reference.element;
+ var elementBuilder = unit.linkedContext.elementBuilder;
+ return elementBuilder.mixinDeclaration(reference.node);
}
Element _parameter(ExecutableElementImpl enclosing, Reference reference) {
@@ -487,8 +497,14 @@
_indexUnitElementDeclarations(unit);
assert(reference.node != null, '$reference');
}
- GenericTypeAliasElementImpl.forLinkedNode(unit, reference, reference.node);
- return reference.element;
+
+ var elementBuilder = unit.linkedContext.elementBuilder;
+ var node = reference.node;
+ if (node is FunctionTypeAlias) {
+ return elementBuilder.functionTypeAlias(node);
+ } else {
+ return elementBuilder.genericTypeAlias(node);
+ }
}
/// Index nodes for which we choose to create elements individually,
diff --git a/pkg/analyzer/lib/src/summary2/linked_unit_context.dart b/pkg/analyzer/lib/src/summary2/linked_unit_context.dart
index 24a749f..73c1f77 100644
--- a/pkg/analyzer/lib/src/summary2/linked_unit_context.dart
+++ b/pkg/analyzer/lib/src/summary2/linked_unit_context.dart
@@ -19,6 +19,7 @@
import 'package:analyzer/src/summary2/ast_binary_reader.dart';
import 'package:analyzer/src/summary2/lazy_ast.dart';
import 'package:analyzer/src/summary2/linked_bundle_context.dart';
+import 'package:analyzer/src/summary2/linked_element_builder.dart';
import 'package:analyzer/src/summary2/reference.dart';
import 'package:analyzer/src/summary2/type_builder.dart';
@@ -38,6 +39,8 @@
AstBinaryReader _astReader;
+ LinkedElementBuilder _elementBuilder;
+
CompilationUnit _unit;
bool _hasDirectivesRead = false;
@@ -66,6 +69,10 @@
_hasDirectivesRead = _unit != null;
}
+ LinkedElementBuilder get elementBuilder {
+ return _elementBuilder ??= LinkedElementBuilder(this);
+ }
+
bool get hasPartOfDirective {
for (var directive in unit_withDirectives.directives) {
if (directive is PartOfDirective) {
diff --git a/pkg/analyzer/test/src/diagnostics/invalid_export_of_internal_element_test.dart b/pkg/analyzer/test/src/diagnostics/invalid_export_of_internal_element_test.dart
index 542262d..b960a44 100644
--- a/pkg/analyzer/test/src/diagnostics/invalid_export_of_internal_element_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/invalid_export_of_internal_element_test.dart
@@ -375,6 +375,88 @@
]);
}
+ void test_indirectlyViaFunction_parameter() async {
+ newFile(testPackageImplementationFilePath, content: r'''
+import 'package:meta/meta.dart';
+@internal typedef int IntFunc(int x);
+int func(IntFunc f, int x) => f(x);
+''');
+
+ await assertErrorsInCode(r'''
+export 'src/foo.dart' show func;
+''', [
+ error(HintCode.INVALID_EXPORT_OF_INTERNAL_ELEMENT_INDIRECTLY, 0, 32),
+ ]);
+ }
+
+ void test_indirectlyViaFunction_parameter_generic() async {
+ newFile(testPackageImplementationFilePath, content: r'''
+import 'package:meta/meta.dart';
+@internal typedef IntFunc = int Function(int);
+int func(IntFunc f, int x) => f(x);
+''');
+
+ await assertErrorsInCode(r'''
+export 'src/foo.dart' show func;
+''', [
+ error(HintCode.INVALID_EXPORT_OF_INTERNAL_ELEMENT_INDIRECTLY, 0, 32),
+ ]);
+ }
+
+ void test_indirectlyViaFunction_parameter_generic_typeArg() async {
+ newFile(testPackageImplementationFilePath, content: r'''
+import 'package:meta/meta.dart';
+@internal typedef IntFunc<T> = int Function(T);
+int func(IntFunc<num> f, int x) => f(x);
+''');
+
+ await assertErrorsInCode(r'''
+export 'src/foo.dart' show func;
+''', [
+ error(HintCode.INVALID_EXPORT_OF_INTERNAL_ELEMENT_INDIRECTLY, 0, 32),
+ ]);
+ }
+
+ void test_indirectlyViaFunction_returnType() async {
+ newFile(testPackageImplementationFilePath, content: r'''
+import 'package:meta/meta.dart';
+@internal typedef int IntFunc(int x);
+IntFunc func() => (int x) => x;
+''');
+
+ await assertErrorsInCode(r'''
+export 'src/foo.dart' show func;
+''', [
+ error(HintCode.INVALID_EXPORT_OF_INTERNAL_ELEMENT_INDIRECTLY, 0, 32),
+ ]);
+ }
+
+ void test_indirectlyViaFunction_typeArgument_bounded() async {
+ newFile(testPackageImplementationFilePath, content: r'''
+import 'package:meta/meta.dart';
+@internal typedef int IntFunc(int x);
+void func<T extends IntFunc>() {}
+''');
+
+ await assertErrorsInCode(r'''
+export 'src/foo.dart' show func;
+''', [
+ error(HintCode.INVALID_EXPORT_OF_INTERNAL_ELEMENT_INDIRECTLY, 0, 32),
+ ]);
+ }
+
+ void test_indirectlyViaFunction_typeArgument_unbounded() async {
+ newFile(testPackageImplementationFilePath, content: r'''
+import 'package:meta/meta.dart';
+@internal typedef int IntFunc(int x);
+void func<T>() {}
+''');
+
+ await assertNoErrorsInCode(r'''
+export 'src/foo.dart' show func;
+''');
+ }
+
void test_noCombinators() async {
newFile(testPackageImplementationFilePath, content: r'''
import 'package:meta/meta.dart';
diff --git a/pkg/compiler/README.md b/pkg/compiler/README.md
index f4e2a49..6c9621a 100644
--- a/pkg/compiler/README.md
+++ b/pkg/compiler/README.md
@@ -327,36 +327,14 @@
AI: consider deleting this file.
-* Constants: the compiler has a constant system that delays evaluation of
- constants and provides different semantics depending on the embedder, this
- abstraction was especially necessary when dart2js was used as a front-end for
- non-JS systems like dart2dart and dartino.
+* Constants: the compiler has a constant system that evaluates constant
+ expressions based on JS semantics.
* `lib/src/constants/value.dart`: this is the represented value of a constant
- after it has been evaluated. The resulting value is specific to the target
- of the compiler and will no longer have environment placeholders. For
- example, when the target is Dart (dart2dart) `1 == 1.0` is evaluated to
- `false`, and when the target is JavaScript it is evaluated to `true`. This
- specific example is a result of the way dart2js compiles numbers as
- JavaScript Numbers.
+ after it has been evaluated.
- * `lib/src/constants/constant_system.dart`: an abstraction that defines how
- expressions may be folded. Different implementations of the constant system
- are used to target Dart or JavaScript.
-
- * `lib/src/compile_time_constants.dart`: defines how constant expressions are
- created from a parsed AST.
-
- * `lib/src/constant_system_dart.dart`: defines an implementation of a constant
- system with the Dart semantics (where `1 == 1.0` is true).
-
- * `lib/src/js_backend/constant_system_javascript.dart`: defines an
- implementation of a constant system with the JavaScript semantics (where
- `1 == 1.0` is false).
-
- AI: consider deleting `constant_system_dart.dart` now that it is no longer
- used, or move under testing, if it might be used for unittests of the constant
- expressions.
+ * `lib/src/constants/constant_system.dart`: implements evaluating constant
+ Dart expressions and produces values.
* Common elements: the compiler often refers to certain elements during
compilation either because they are first-class in the language or because
diff --git a/pkg/dev_compiler/lib/src/kernel/compiler.dart b/pkg/dev_compiler/lib/src/kernel/compiler.dart
index 31522ce..153240b 100644
--- a/pkg/dev_compiler/lib/src/kernel/compiler.dart
+++ b/pkg/dev_compiler/lib/src/kernel/compiler.dart
@@ -560,7 +560,10 @@
var body = <js_ast.Statement>[];
_emitSuperHelperSymbols(body);
- var deferredSupertypes = <js_ast.Statement>[];
+ // Deferred supertypes must be evaluated lazily while emitting classes to
+ // prevent evaluating a JS expression for a deferred type from influencing
+ // class declaration order (such as when calling 'emitDeferredType').
+ var deferredSupertypes = <js_ast.Statement Function()>[];
// Emit the class, e.g. `core.Object = class Object { ... }`
_defineClass(c, className, jsMethods, body, deferredSupertypes);
@@ -591,11 +594,13 @@
var classDef = js_ast.Statement.from(body);
var typeFormals = c.typeParameters;
+ var evaluatedDeferredSupertypes =
+ deferredSupertypes.map<js_ast.Statement>((f) => f()).toList();
if (typeFormals.isNotEmpty) {
classDef = _defineClassTypeArguments(
- c, typeFormals, classDef, className, deferredSupertypes);
+ c, typeFormals, classDef, className, evaluatedDeferredSupertypes);
} else {
- afterClassDefItems.addAll(deferredSupertypes);
+ afterClassDefItems.addAll(evaluatedDeferredSupertypes);
}
body = [classDef];
@@ -745,7 +750,7 @@
js_ast.Expression className,
List<js_ast.Method> methods,
List<js_ast.Statement> body,
- List<js_ast.Statement> deferredSupertypes) {
+ List<js_ast.Statement Function()> deferredSupertypes) {
if (c == _coreTypes.objectClass) {
body.add(_emitClassStatement(c, className, null, methods));
return;
@@ -884,10 +889,14 @@
// Unroll mixins.
if (shouldDefer(supertype)) {
- deferredSupertypes.add(runtimeStatement('setBaseClass(#, #)', [
- getBaseClass(isMixinAliasClass(c) ? 0 : mixinApplications.length),
- emitDeferredType(supertype),
- ]));
+ var originalSupertype = supertype;
+ deferredSupertypes.add(() => runtimeStatement('setBaseClass(#, #)', [
+ getBaseClass(isMixinAliasClass(c) ? 0 : mixinApplications.length),
+ emitDeferredType(originalSupertype),
+ ]));
+ // Refers to 'supertype' without type parameters. We remove these from
+ // the 'extends' clause for generics for cyclic dependencies and append
+ // them later with 'setBaseClass'.
supertype =
_coreTypes.rawType(supertype.classNode, _currentLibrary.nonNullable);
}
@@ -903,12 +912,16 @@
var m = c.mixedInType.asInterfaceType;
var deferMixin = shouldDefer(m);
- var mixinBody = deferMixin ? deferredSupertypes : body;
var mixinClass = deferMixin ? emitDeferredType(m) : emitClassRef(m);
var classExpr = deferMixin ? getBaseClass(0) : className;
- mixinBody
- .add(runtimeStatement('applyMixin(#, #)', [classExpr, mixinClass]));
+ var mixinApplication =
+ runtimeStatement('applyMixin(#, #)', [classExpr, mixinClass]);
+ if (deferMixin) {
+ deferredSupertypes.add(() => mixinApplication);
+ } else {
+ body.add(mixinApplication);
+ }
if (methods.isNotEmpty) {
// However we may need to add some methods to this class that call
@@ -917,11 +930,16 @@
// We do this with the following pattern:
//
// applyMixin(C, class C$ extends M { <methods> });
- mixinBody.add(runtimeStatement('applyMixin(#, #)', [
+ var mixinApplicationWithMethods = runtimeStatement('applyMixin(#, #)', [
classExpr,
js_ast.ClassExpression(
_emitTemporaryId(getLocalClassName(c)), mixinClass, methods)
- ]));
+ ]);
+ if (deferMixin) {
+ deferredSupertypes.add(() => mixinApplicationWithMethods);
+ } else {
+ body.add(mixinApplicationWithMethods);
+ }
}
emitMixinConstructors(className, m);
@@ -964,10 +982,10 @@
hasUnnamedSuper = hasUnnamedSuper || _hasUnnamedConstructor(mixinClass);
if (shouldDefer(mixinType)) {
- deferredSupertypes.add(runtimeStatement('applyMixin(#, #)', [
- getBaseClass(mixinApplications.length - i),
- emitDeferredType(mixinType)
- ]));
+ deferredSupertypes.add(() => runtimeStatement('applyMixin(#, #)', [
+ getBaseClass(mixinApplications.length - i),
+ emitDeferredType(mixinType)
+ ]));
} else {
body.add(runtimeStatement(
'applyMixin(#, #)', [mixinId, emitClassRef(mixinType)]));
diff --git a/tests/language/mixin/regress_flutter_66859_1_test.dart b/tests/language/mixin/regress_flutter_66859_1_test.dart
new file mode 100644
index 0000000..544da53
--- /dev/null
+++ b/tests/language/mixin/regress_flutter_66859_1_test.dart
@@ -0,0 +1,31 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Verifies that mixin supertypes are properly maintained even if marked as
+// deferred (e.g., in a circular hierarchy).
+// Regression test for: https://github.com/flutter/flutter/issues/66859
+
+import "package:expect/expect.dart";
+
+mixin M {}
+
+mixin N {}
+
+class A extends B<C> with M, N {}
+
+class B<T> {}
+
+class C extends A {}
+
+class Z extends B<Z> with M {}
+
+main() {
+ var z = Z();
+ Expect.isTrue(z is B<Z>);
+ Expect.isTrue(z is M);
+ var a = A();
+ Expect.isTrue(a is M);
+ Expect.isTrue(a is N);
+ Expect.isTrue(a is B<C>);
+}
diff --git a/tests/language/mixin/regress_flutter_66859_2_test.dart b/tests/language/mixin/regress_flutter_66859_2_test.dart
new file mode 100644
index 0000000..7a3ee64
--- /dev/null
+++ b/tests/language/mixin/regress_flutter_66859_2_test.dart
@@ -0,0 +1,37 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Verifies that mixin supertypes are properly maintained even if marked as
+// deferred (e.g., in a circular hierarchy).
+// Regression test for: https://github.com/flutter/flutter/issues/66859
+
+import "package:expect/expect.dart";
+
+mixin X {}
+mixin Y {}
+mixin Z {}
+
+class A extends B<C> with X {}
+
+class C extends A with Z {}
+
+class B<T> extends Object with Y {}
+
+main() {
+ var a = A();
+ var b = B();
+ var c = C();
+ Expect.isTrue(a is A);
+ Expect.isTrue(a is B<C>);
+ Expect.isTrue(a is X);
+ Expect.isTrue(a is Y);
+ Expect.isTrue(c is C);
+ Expect.isTrue(c is A);
+ Expect.isTrue(c is B<C>);
+ Expect.isTrue(c is X);
+ Expect.isTrue(c is Y);
+ Expect.isTrue(c is Z);
+ Expect.isTrue(b is B);
+ Expect.isTrue(b is Y);
+}
diff --git a/tests/language_2/mixin/regress_flutter_66859_1_test.dart b/tests/language_2/mixin/regress_flutter_66859_1_test.dart
new file mode 100644
index 0000000..544da53
--- /dev/null
+++ b/tests/language_2/mixin/regress_flutter_66859_1_test.dart
@@ -0,0 +1,31 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Verifies that mixin supertypes are properly maintained even if marked as
+// deferred (e.g., in a circular hierarchy).
+// Regression test for: https://github.com/flutter/flutter/issues/66859
+
+import "package:expect/expect.dart";
+
+mixin M {}
+
+mixin N {}
+
+class A extends B<C> with M, N {}
+
+class B<T> {}
+
+class C extends A {}
+
+class Z extends B<Z> with M {}
+
+main() {
+ var z = Z();
+ Expect.isTrue(z is B<Z>);
+ Expect.isTrue(z is M);
+ var a = A();
+ Expect.isTrue(a is M);
+ Expect.isTrue(a is N);
+ Expect.isTrue(a is B<C>);
+}
diff --git a/tests/language_2/mixin/regress_flutter_66859_2_test.dart b/tests/language_2/mixin/regress_flutter_66859_2_test.dart
new file mode 100644
index 0000000..7a3ee64
--- /dev/null
+++ b/tests/language_2/mixin/regress_flutter_66859_2_test.dart
@@ -0,0 +1,37 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Verifies that mixin supertypes are properly maintained even if marked as
+// deferred (e.g., in a circular hierarchy).
+// Regression test for: https://github.com/flutter/flutter/issues/66859
+
+import "package:expect/expect.dart";
+
+mixin X {}
+mixin Y {}
+mixin Z {}
+
+class A extends B<C> with X {}
+
+class C extends A with Z {}
+
+class B<T> extends Object with Y {}
+
+main() {
+ var a = A();
+ var b = B();
+ var c = C();
+ Expect.isTrue(a is A);
+ Expect.isTrue(a is B<C>);
+ Expect.isTrue(a is X);
+ Expect.isTrue(a is Y);
+ Expect.isTrue(c is C);
+ Expect.isTrue(c is A);
+ Expect.isTrue(c is B<C>);
+ Expect.isTrue(c is X);
+ Expect.isTrue(c is Y);
+ Expect.isTrue(c is Z);
+ Expect.isTrue(b is B);
+ Expect.isTrue(b is Y);
+}
diff --git a/tools/VERSION b/tools/VERSION
index cc68fb0..ac97587 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
MAJOR 2
MINOR 11
PATCH 0
-PRERELEASE 192
+PRERELEASE 193
PRERELEASE_PATCH 0
\ No newline at end of file