diff --git a/lib/dartdoc.dart b/lib/dartdoc.dart index 063ff6e896..7d09769975 100644 --- a/lib/dartdoc.dart +++ b/lib/dartdoc.dart @@ -73,7 +73,7 @@ class DartdocFileWriter implements FileWriter { var file = resourceProvider .getFile(resourceProvider.pathContext.join(outputDir, outFile)); - var parent = file.parent; + var parent = file.parent2; if (!parent.exists) { parent.create(); } diff --git a/lib/src/dartdoc_options.dart b/lib/src/dartdoc_options.dart index ee6ae5180b..e775bcc18a 100644 --- a/lib/src/dartdoc_options.dart +++ b/lib/src/dartdoc_options.dart @@ -1094,12 +1094,11 @@ abstract class _DartdocFileOption implements DartdocOption { /// Searches all dartdoc_options files through parent directories, starting at /// [dir], for the option and returns one once found. - _OptionValueWithContext _valueAtFromFilesFirstFound(Folder dir) { + _OptionValueWithContext _valueAtFromFilesFirstFound(Folder folder) { _OptionValueWithContext value; - while (true) { + for (var dir in folder.withAncestors) { value = _valueAtFromFile(dir); - if (value != null || dir.parent == null) break; - dir = dir.parent; + if (value != null) break; } return value; } @@ -1107,13 +1106,11 @@ abstract class _DartdocFileOption implements DartdocOption { /// Searches all dartdoc_options files for the option, and returns the value /// in the top-most parent directory `dartdoc_options.yaml` file it is /// mentioned in. - _OptionValueWithContext _valueAtFromFilesLastFound(Folder dir) { + _OptionValueWithContext _valueAtFromFilesLastFound(Folder folder) { _OptionValueWithContext value; - while (true) { + for (var dir in folder.withAncestors) { var tmpValue = _valueAtFromFile(dir); if (tmpValue != null) value = tmpValue; - dir = dir.parent; - if (dir == null) break; } return value; } @@ -1179,35 +1176,32 @@ abstract class _DartdocFileOption implements DartdocOption { definingFile: 'dartdoc_options.yaml'); } - _YamlFileData _yamlAtDirectory(Folder dir) { - var canonicalPaths = [ - resourceProvider.pathContext.canonicalize(dir.path) - ]; - if (!_yamlAtCanonicalPathCache.containsKey(canonicalPaths.first)) { - var yamlData = _YamlFileData({}, _directoryCurrentPath); + _YamlFileData _yamlAtDirectory(Folder folder) { + var canonicalPaths = []; + var yamlData = _YamlFileData({}, _directoryCurrentPath); + + for (var dir in folder.withAncestors) { + var canonicalPath = + resourceProvider.pathContext.canonicalize(folder.path); + if (_yamlAtCanonicalPathCache.containsKey(canonicalPath)) { + yamlData = _yamlAtCanonicalPathCache[canonicalPath]; + break; + } + canonicalPaths.add(canonicalPath); if (dir.exists) { - File dartdocOptionsFile; - - while (true) { - dartdocOptionsFile = resourceProvider.getFile(resourceProvider - .pathContext - .join(dir.path, 'dartdoc_options.yaml')); - if (dartdocOptionsFile.exists || dir.parent == null) { - break; - } - dir = dir.parent; - canonicalPaths - .add(resourceProvider.pathContext.canonicalize(dir.path)); - } + var dartdocOptionsFile = resourceProvider.getFile(resourceProvider + .pathContext + .join(dir.path, 'dartdoc_options.yaml')); if (dartdocOptionsFile.exists) { yamlData = _YamlFileData( loadYaml(dartdocOptionsFile.readAsStringSync()), resourceProvider.pathContext.canonicalize(dir.path)); + break; } } - canonicalPaths.forEach((p) => _yamlAtCanonicalPathCache[p] = yamlData); } - return _yamlAtCanonicalPathCache[canonicalPaths.first]; + canonicalPaths.forEach((p) => _yamlAtCanonicalPathCache[p] = yamlData); + return yamlData; } } @@ -1402,7 +1396,7 @@ class DartdocOptionContext extends DartdocOptionContextBase } else { context = resourceProvider.getFolder(resourceProvider.pathContext .canonicalize( - resource is File ? resource.parent.path : resource.path)); + resource is File ? resource.parent2.path : resource.path)); } } diff --git a/lib/src/element_type.dart b/lib/src/element_type.dart index 78f0d0d318..7b0bb21da0 100644 --- a/lib/src/element_type.dart +++ b/lib/src/element_type.dart @@ -34,11 +34,7 @@ abstract class ElementType extends Privacy { } else { var element = ModelElement.fromElement(f.element, packageGraph); assert(f is ParameterizedType || f is TypeParameterType); - // TODO(jcollins-g): Remove reference to f.element.enclosingElement after - // analyzer 0.41. - var isGenericTypeAlias = - f.element.enclosingElement is FunctionTypeAliasElement || - f.element is FunctionTypeAliasElement; + var isGenericTypeAlias = f.aliasElement != null; if (f is FunctionType) { assert(f is ParameterizedType); if (isGenericTypeAlias) { @@ -366,13 +362,13 @@ abstract class CallableElementTypeMixin implements ParameterizedElementType { Iterable dartTypeArguments; if (returnedFrom is FunctionTypeElementType) { if (type.typeFormals.isEmpty) { - dartTypeArguments = type.typeArguments; + dartTypeArguments = type.aliasArguments; } else { dartTypeArguments = type.typeFormals.map(_legacyTypeParameterType); } } else { if (type.typeFormals.isEmpty) { - dartTypeArguments = type.typeArguments; + dartTypeArguments = type.aliasArguments; } else if (returnedFrom != null && returnedFrom.type.element is GenericFunctionTypeElement) { _typeArguments = (returnedFrom as DefinedElementType).typeArguments; @@ -447,8 +443,8 @@ class CallableGenericTypeAliasElementType extends ParameterizedElementType ModelElement _returnElement; @override ModelElement get returnElement { - _returnElement ??= - ModelElement.fromElement(type.element.enclosingElement, packageGraph); + _returnElement ??= ModelElement.fromElement( + type.aliasElement.enclosingElement, packageGraph); return _returnElement; } diff --git a/lib/src/model/model_element.dart b/lib/src/model/model_element.dart index 809b8df559..e908dd780b 100644 --- a/lib/src/model/model_element.dart +++ b/lib/src/model/model_element.dart @@ -330,7 +330,7 @@ abstract class ModelElement extends Canonicalization if (e is FunctionElement) { return ModelFunction(e, library, packageGraph); } else if (e is GenericFunctionTypeElement) { - assert(e.enclosingElement is FunctionTypeAliasElement); + assert(e.enclosingElement is TypeAliasElement); assert(e.enclosingElement.name != ''); return ModelFunctionTypedef(e, library, packageGraph); } @@ -547,8 +547,11 @@ abstract class ModelElement extends Canonicalization return allFeatures.join(', '); } + // True if this is a function, or if it is an type alias to a function. bool get isCallable => - element is FunctionTypedElement || element is FunctionTypeAliasElement; + element is FunctionTypedElement || + (element is TypeAliasElement && + (element as TypeAliasElement).aliasedElement is FunctionTypedElement); ModelElement buildCanonicalModelElement() { Container preferredClass; @@ -1079,28 +1082,31 @@ abstract class ModelElement extends Canonicalization if (_parameters == null) { List params; - if (element is ExecutableElement) { - if (_originalMember != null) { - assert(_originalMember is ExecutableMember); - params = (_originalMember as ExecutableMember).parameters; - } else { - params = (element as ExecutableElement).parameters; + if (element is TypeAliasElement) { + _parameters = ModelElement.fromElement( + (element as TypeAliasElement).aliasedElement, packageGraph) + .parameters; + } else { + if (element is ExecutableElement) { + if (_originalMember != null) { + assert(_originalMember is ExecutableMember); + params = (_originalMember as ExecutableMember).parameters; + } else { + params = (element as ExecutableElement).parameters; + } } - } - if (params == null && element is FunctionTypedElement) { - if (_originalMember != null) { - params = (_originalMember as dynamic).parameters; - } else { - params = (element as FunctionTypedElement).parameters; + if (params == null && element is FunctionTypedElement) { + if (_originalMember != null) { + params = (_originalMember as dynamic).parameters; + } else { + params = (element as FunctionTypedElement).parameters; + } } + _parameters = UnmodifiableListView(params + .map( + (p) => ModelElement.from(p, library, packageGraph) as Parameter) + .toList(growable: false)); } - if (params == null && element is FunctionTypeAliasElement) { - params = (element as FunctionTypeAliasElement).function.parameters; - } - - _parameters = UnmodifiableListView(params - .map((p) => ModelElement.from(p, library, packageGraph) as Parameter) - .toList(growable: false)); } return _parameters; } diff --git a/lib/src/model/package_graph.dart b/lib/src/model/package_graph.dart index 4d147a85d6..db9640b2bc 100644 --- a/lib/src/model/package_graph.dart +++ b/lib/src/model/package_graph.dart @@ -972,7 +972,7 @@ class PackageGraph { // might not be where the element was defined, which is what's important // for nodoc's semantics. Looking up the defining element just to pull // a context is again, slow. - List globs = config.optionSet['nodoc'].valueAt(file.parent); + List globs = config.optionSet['nodoc'].valueAt(file.parent2); _configSetsNodocFor[fullName] = matchGlobs(globs, fullName); } return _configSetsNodocFor[fullName]; diff --git a/lib/src/model/typedef.dart b/lib/src/model/typedef.dart index d49bfca6b8..07f10bfd2f 100644 --- a/lib/src/model/typedef.dart +++ b/lib/src/model/typedef.dart @@ -70,7 +70,7 @@ class FunctionTypedef extends Typedef { @override List get genericTypeParameters { - var aliasedTypeElement = aliasedType.element; + var aliasedTypeElement = aliasedType.aliasElement; if (aliasedTypeElement is FunctionTypedElement) { return aliasedTypeElement.typeParameters; } diff --git a/lib/src/mustachio/renderer_base.dart b/lib/src/mustachio/renderer_base.dart index e3096db45d..c7640f9e0e 100644 --- a/lib/src/mustachio/renderer_base.dart +++ b/lib/src/mustachio/renderer_base.dart @@ -74,7 +74,7 @@ class Template { partialResolver = (String path) async { var partialPath = pathContext.isAbsolute(path) ? path - : pathContext.join(file.parent.path, path); + : pathContext.join(file.parent2.path, path); var partialFile = file.provider.getFile(pathContext.normalize(partialPath)); return partialFile; diff --git a/lib/src/package_meta.dart b/lib/src/package_meta.dart index 8c87ca59d5..8f414e50f8 100644 --- a/lib/src/package_meta.dart +++ b/lib/src/package_meta.dart @@ -42,8 +42,8 @@ final PackageMetaProvider pubPackageMetaProvider = PackageMetaProvider( PhysicalResourceProvider.INSTANCE .getFile(PhysicalResourceProvider.INSTANCE.pathContext .absolute(Platform.resolvedExecutable)) - .parent - .parent); + .parent2 + .parent2); /// Sets the supported way of constructing [PackageMeta] objects. /// @@ -177,14 +177,14 @@ abstract class PubPackageMeta extends PackageMeta { static final _sdkDirParent = {}; - /// If [dir] is inside a Dart SDK, returns the directory of the SDK, and `null` + /// If [folder] is inside a Dart SDK, returns the directory of the SDK, and `null` /// otherwise. - static Folder sdkDirParent(Folder dir, ResourceProvider resourceProvider) { + static Folder sdkDirParent(Folder folder, ResourceProvider resourceProvider) { var pathContext = resourceProvider.pathContext; - var dirPathCanonical = pathContext.canonicalize(dir.path); + var dirPathCanonical = pathContext.canonicalize(folder.path); if (!_sdkDirParent.containsKey(dirPathCanonical)) { _sdkDirParent[dirPathCanonical] = null; - while (dir.exists) { + for (var dir in folder.withAncestors) { if (_sdkDirFilePaths.every((List l) { return l.any((f) => resourceProvider.getFile(pathContext.join(dir.path, f)).exists); @@ -192,8 +192,6 @@ abstract class PubPackageMeta extends PackageMeta { _sdkDirParent[dirPathCanonical] = dir; break; } - dir = dir.parent; - if (dir == null) break; } } return _sdkDirParent[dirPathCanonical]; @@ -210,54 +208,50 @@ abstract class PubPackageMeta extends PackageMeta { resourceProvider .getFile(resourceProvider.pathContext .canonicalize(libraryElement.source.fullName)) - .parent, + .parent2, resourceProvider); } static PubPackageMeta fromFilename( String filename, ResourceProvider resourceProvider) { return PubPackageMeta.fromDir( - resourceProvider.getFile(filename).parent, resourceProvider); + resourceProvider.getFile(filename).parent2, resourceProvider); } /// This factory is guaranteed to return the same object for any given /// [dir.absolute.path]. Multiple [dir.absolute.path]s will resolve to the /// same object if they are part of the same package. Returns null /// if the directory is not part of a known package. - static PubPackageMeta fromDir(Folder dir, ResourceProvider resourceProvider) { + static PubPackageMeta fromDir( + Folder folder, ResourceProvider resourceProvider) { var pathContext = resourceProvider.pathContext; - var original = resourceProvider.getFolder(pathContext.absolute(dir.path)); - dir = original; + var original = + resourceProvider.getFolder(pathContext.absolute(folder.path)); + folder = original; if (!original.exists) { throw PackageMetaFailure( 'fatal error: unable to locate the input directory at ${original.path}.'); } - if (!_packageMetaCache.containsKey(dir.path)) { + if (!_packageMetaCache.containsKey(folder.path)) { PackageMeta packageMeta; // There are pubspec.yaml files inside the SDK. Ignore them. - var parentSdkDir = sdkDirParent(dir, resourceProvider); + var parentSdkDir = sdkDirParent(folder, resourceProvider); if (parentSdkDir != null) { packageMeta = _SdkMeta(parentSdkDir, resourceProvider); } else { - while (dir.exists) { + for (var dir in folder.withAncestors) { var pubspec = resourceProvider .getFile(pathContext.join(dir.path, 'pubspec.yaml')); if (pubspec.exists) { packageMeta = _FilePackageMeta(dir, resourceProvider); break; } - // Allow a package to be at root (possible in a Windows setting with - // drive letter mappings). - if (dir.parent == null) break; - // TODO(srawlins): or just... `.parent`? - dir = - resourceProvider.getFolder(pathContext.absolute(dir.parent.path)); } } - _packageMetaCache[pathContext.absolute(dir.path)] = packageMeta; + _packageMetaCache[pathContext.absolute(folder.path)] = packageMeta; } - return _packageMetaCache[pathContext.absolute(dir.path)]; + return _packageMetaCache[pathContext.absolute(folder.path)]; } @override @@ -317,10 +311,11 @@ class _FilePackageMeta extends PubPackageMeta { // a pub library to do this. // People could have a pub cache at root with Windows drive mappings. if (pathContext.split(pathContext.canonicalize(dir.path)).length >= 3) { - var pubCacheRoot = dir.parent.parent.parent?.path; - if (pubCacheRoot != null) { - var hosted = pathContext.canonicalize(dir.parent.parent.path); - var hostname = pathContext.canonicalize(dir.parent.path); + var pubCacheRoot = dir.parent2.parent2.parent2.path; + // Check for directory structure too close to root. + if (pubCacheRoot != dir.parent2.parent2.path) { + var hosted = pathContext.canonicalize(dir.parent2.parent2.path); + var hostname = pathContext.canonicalize(dir.parent2.path); if (pathContext.basename(hosted) == 'hosted' && resourceProvider .getFolder(pathContext.join(pubCacheRoot, '_temp')) diff --git a/test/end2end/model_test.dart b/test/end2end/model_test.dart index 6a4659ace3..a0293bdb84 100644 --- a/test/end2end/model_test.dart +++ b/test/end2end/model_test.dart @@ -3650,13 +3650,14 @@ String topLevelFunction(int param1, bool param2, Cool coolBeans, }); group('Typedef', () { - Typedef t; + Typedef processMessage; Typedef generic; Typedef aComplexTypedef; Class TypedefUsingClass; setUpAll(() { - t = exLibrary.typedefs.firstWhere((t) => t.name == 'processMessage'); + processMessage = + exLibrary.typedefs.firstWhere((t) => t.name == 'processMessage'); generic = fakeLibrary.typedefs.firstWhere((t) => t.name == 'NewGenericTypedef'); @@ -3700,23 +3701,23 @@ String topLevelFunction(int param1, bool param2, Cool coolBeans, }); test('has a fully qualified name', () { - expect(t.fullyQualifiedName, 'ex.processMessage'); + expect(processMessage.fullyQualifiedName, 'ex.processMessage'); expect(generic.fullyQualifiedName, 'fake.NewGenericTypedef'); }); test('has enclosing element', () { - expect(t.enclosingElement.name, equals(exLibrary.name)); + expect(processMessage.enclosingElement.name, equals(exLibrary.name)); expect(generic.enclosingElement.name, equals(fakeLibrary.name)); }); test('docs', () { - expect(t.documentation, equals('')); + expect(processMessage.documentation, equals('')); expect(generic.documentation, equals('A typedef with the new style generic function syntax.')); }); test('linked return type', () { - expect(t.linkedReturnType, equals('String')); + expect(processMessage.linkedReturnType, equals('String')); expect( generic.linkedReturnType, equals( @@ -3725,7 +3726,7 @@ String topLevelFunction(int param1, bool param2, Cool coolBeans, test('name with generics', () { expect( - t.nameWithGenerics, + processMessage.nameWithGenerics, equals( 'processMessage<T>')); expect( @@ -3738,7 +3739,8 @@ String topLevelFunction(int param1, bool param2, Cool coolBeans, // inspects its element member. Find a better way when we start to isolate // renderer tests. test('TypedefRendererHtml renders genericParameters', () { - expect(TypedefRendererHtml().renderGenericParameters(t), equals('')); + expect(TypedefRendererHtml().renderGenericParameters(processMessage), + equals('<T>')); expect(TypedefRendererHtml().renderGenericParameters(generic), equals('<S>')); });