Skip to content

Canonicalization overhaul #1368

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 42 commits into from
Apr 13, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
47966ee
fix key for _implementors, stop overwriting files all the time
jcollins-g Mar 7, 2017
3bc180e
Intermediate attempt to resolve duplicates and add some debugging.
jcollins-g Mar 13, 2017
3016e8b
Implemented by and a few other things still broken, but closer.
jcollins-g Mar 15, 2017
a7a9ce6
Fixed Implemented By again with a refactor. Still need to condense c…
jcollins-g Mar 15, 2017
6154a18
Some duplicate libraries or something going on here.
jcollins-g Mar 16, 2017
687cf72
Things are working better now. Edge cases with fields and dart:_inte…
jcollins-g Mar 22, 2017
5c03e6d
Field inheritance still broken for getters/setters. May have to fix …
jcollins-g Mar 27, 2017
531a559
Fix up brokenness from merges
jcollins-g Mar 27, 2017
add09d1
fix key for _implementors, stop overwriting files all the time
jcollins-g Mar 7, 2017
692b727
Intermediate attempt to resolve duplicates and add some debugging.
jcollins-g Mar 13, 2017
9d4ebf9
Implemented by and a few other things still broken, but closer.
jcollins-g Mar 15, 2017
ab1da77
Fixed Implemented By again with a refactor. Still need to condense c…
jcollins-g Mar 15, 2017
ed7af68
Some duplicate libraries or something going on here.
jcollins-g Mar 16, 2017
c9dc37f
Things are working better now. Edge cases with fields and dart:_inte…
jcollins-g Mar 22, 2017
a8e7a18
Field inheritance still broken for getters/setters. May have to fix …
jcollins-g Mar 27, 2017
8a80a18
Fix up brokenness from merges
jcollins-g Mar 27, 2017
8edf848
Another incremental step; field inheritance canonicalization seems co…
jcollins-g Mar 30, 2017
aecb075
merge fixups
jcollins-g Mar 30, 2017
34b0645
Fix enclosingCanonicalElement detection on deep inheritance trees, up…
jcollins-g Mar 30, 2017
06f65ba
More bugs fixed with a new inheritance chain builder in Class.inherit…
jcollins-g Mar 31, 2017
da0b42a
Generating test package docs with no broken links and everything seem…
jcollins-g Mar 31, 2017
55b6c8a
all the tests pass. but we still can't build SDK docs.
jcollins-g Mar 31, 2017
8cb927e
Down to one broken sdk link
jcollins-g Apr 1, 2017
88a5bc2
Reintroduce workaround for missing names in some instances
jcollins-g Apr 3, 2017
167bffd
Fix linkage for class members
jcollins-g Apr 5, 2017
1a5c085
Merge branch 'master' of github.com:dart-lang/dartdoc into 1334-imple…
jcollins-g Apr 5, 2017
91bfdbe
Display warnings and re-fix Implemented By tracking
jcollins-g Apr 5, 2017
f31199a
Clean up generated test package docs. New semantics for --auto-inclu…
jcollins-g Apr 6, 2017
c3b1ee9
And add back all the missing hashCode, etc now that we're hiding the …
jcollins-g Apr 6, 2017
189b069
dartfmt
jcollins-g Apr 6, 2017
738dce3
Cleanup, add comments, only thing left is Inheritance
jcollins-g Apr 6, 2017
0784d76
Fix a few more edge case behaviors
jcollins-g Apr 6, 2017
46c9f04
Dynamics can have no name, that's legit
jcollins-g Apr 6, 2017
5b53b58
Fix all analysis warnings (excepting deprecation)
jcollins-g Apr 6, 2017
f8898f3
Update version to 0.10.0, add CHANGELOG entries
jcollins-g Apr 7, 2017
22da575
Typo in changelog, drop more of my persistent breakpoints
jcollins-g Apr 7, 2017
c79c0e7
Remove breakpoints
jcollins-g Apr 10, 2017
6cdf4f6
Update changelog to reflect additional bugs this fixes
jcollins-g Apr 10, 2017
4179bf9
First wave review comments
jcollins-g Apr 11, 2017
849a3ec
dartfmt
jcollins-g Apr 11, 2017
3d0ee6e
Drop null check that can't happen for library
jcollins-g Apr 12, 2017
edd9f07
Rename one of the library find methods for clarity, add some comments
jcollins-g Apr 13, 2017
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 34 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,37 @@
## 0.10.0

* fix canonicalization problems and related issues introduced or not addressed
in 0.9.11, including:
* (#1361), (#1232), (#1239 (partial))- Broken links in enums
* (#1345) and (#1090)- Reexports have wrong links in many places
* (#1341), (#1197 (partial)) - Duplicate docs still in some cases
* (#1334) - Some classes don't list their subclasses
* Inheritable class members had incorrect canonicalization in many cases
* ... and many other unfiled bugs relating to inheritance and duplicate files.
* Dartdoc no longer creates documentation for a given identifier more than once.
This means dartdoc is 20-30% faster on complex packages.
* --auto-include-dependencies is now recursive past one layer (#589) It now drills
all the way down and will dive into the SDK and other packages.
* Change display of warnings to be more consistent; warnings now always
go to stderr and are printed on their own line.
* Dartdoc now warns when it is unable to find a canonical object to link to
* Dartdoc now warns if a package exports an identifier so that it is
ambiguous which one should be treated as canonical
* Dartdoc now has a number of asserts in checked mode for issues solved
and as-yet-unsolved, including (#1367) or canonicalization problems; try
running in checked mode if you see structural problems in generated docs and
see if an assert fires.
* Dartdoc internals have changed significantly:
* Package now owns the calculation of recursive dependencies with a factory
constructor, Package.withAutoincludedDependencies.
* ModelElements and Libraries now have Package-scoped caches.
* ModelElements and their subclasses now must be constructed from a single
factory, ModelElements.from
* Package has new methods to assist canonicalization, including
findCanonicalLibraryFor and findCanonicalModelElementFor.
* New mixin "Inheritable" helps class members calculate canonicalization
for inheritable members

## 0.9.13

* fix grind check-links and check-sdk-links (#1360)
Expand Down
15 changes: 9 additions & 6 deletions bin/dartdoc.dart
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ main(List<String> arguments) async {

Directory sdkDir = getSdkDir();
if (sdkDir == null) {
print("Error: unable to locate the Dart SDK.");
stderr.write(" Error: unable to locate the Dart SDK.");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1 to using stderr here

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

exit(1);
}

Expand All @@ -56,13 +56,15 @@ main(List<String> arguments) async {

var readme = args['sdk-readme'];
if (readme != null && !(new File(readme).existsSync())) {
print("Error: unable to locate the SDK description file at $readme.");
stderr
.write(" Error: unable to locate the SDK description file at $readme.");
exit(1);
}

Directory inputDir = new Directory(args['input']);
if (!inputDir.existsSync()) {
print("Error: unable to locate the input directory at ${inputDir.path}.");
stderr.write(
" Error: unable to locate the input directory at ${inputDir.path}.");
exit(1);
}

Expand All @@ -75,15 +77,15 @@ main(List<String> arguments) async {
args['footer'].map(_resolveTildePath).toList() as List<String>;
for (String footerFilePath in footerFilePaths) {
if (!new File(footerFilePath).existsSync()) {
print("Error: unable to locate footer file: ${footerFilePath}.");
stderr.write(" Error: unable to locate footer file: ${footerFilePath}.");
exit(1);
}
}
List<String> headerFilePaths =
args['header'].map(_resolveTildePath).toList() as List<String>;
for (String headerFilePath in footerFilePaths) {
if (!new File(headerFilePath).existsSync()) {
print("Error: unable to locate header file: ${headerFilePath}.");
stderr.write(" Error: unable to locate header file: ${headerFilePath}.");
exit(1);
}
}
Expand All @@ -96,7 +98,8 @@ main(List<String> arguments) async {

if (args.rest.isNotEmpty) {
var unknownArgs = args.rest.join(' ');
print('Error: detected unknown command-line argument(s): $unknownArgs');
stderr.write(
'Error: detected unknown command-line argument(s): $unknownArgs');
_printUsageAndExit(parser, exitCode: 1);
}

Expand Down
88 changes: 48 additions & 40 deletions lib/dartdoc.dart
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ export 'src/package_meta.dart';

const String name = 'dartdoc';
// Update when pubspec version changes.
const String version = '0.9.13';
const String version = '0.10.0';

final String defaultOutDir = path.join('doc', 'api');

Expand Down Expand Up @@ -134,6 +134,7 @@ class DartDoc {
? const []
: findFilesToDocumentInPackage(rootDir.path).toList();

// TODO(jcollins-g): seems like most of this belongs in the Package constructor
List<LibraryElement> libraries = _parseLibraries(files, includeExternals);

if (includes != null && includes.isNotEmpty) {
Expand All @@ -154,21 +155,27 @@ class DartDoc {
});
}

if (includes.isNotEmpty || excludes.isNotEmpty) {
print('generating docs for libraries ${libraries.join(', ')}\n');
}

Package package = new Package(libraries, packageMeta);

Package package;
if (config != null && config.autoIncludeDependencies) {
final newLibraryElements =
_buildLibrariesWithAutoincludedDependencies(package);
Library.clearLibraryMap();
package = new Package(newLibraryElements, packageMeta);
package = Package.withAutoIncludedDependencies(libraries, packageMeta);
libraries = package.libraries.map((l) => l.element).toList();
// remove excluded libraries again, in case they are picked up through
// dependencies.
excludes.forEach((pattern) {
libraries.removeWhere((lib) {
return lib.name.startsWith(pattern) || lib.name == pattern;
});
});
}
package = new Package(libraries, packageMeta);

print(
'generating docs for libraries ${package.libraries.map((Library l) => l.name).join(', ')}\n');

// Go through docs of every model element in package to prebuild the macros index
package.allModelElements.forEach((m) => m.documentation);
// TODO(jcollins-g): move index building into a cached-on-demand generation
// like most other bits in [Package].
package.allCanonicalModelElements.forEach((m) => m.documentation);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Eliminates repeats? Were we looking at documentation for elements that were not documented?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right.


// Create the out directory.
if (!outputDir.existsSync()) outputDir.createSync(recursive: true);
Expand All @@ -179,11 +186,11 @@ class DartDoc {

double seconds = _stopwatch.elapsedMilliseconds / 1000.0;
print(
"\nDocumented ${libraries.length} librar${libraries.length == 1 ? 'y' : 'ies'} "
"\nDocumented ${package.libraries.length} librar${package.libraries.length == 1 ? 'y' : 'ies'} "
"in ${seconds.toStringAsFixed(1)} seconds.");

if (libraries.isEmpty) {
print(
if (package.libraries.isEmpty) {
stderr.write(
"\ndartdoc could not find any libraries to document. Run `pub get` and try again.");
}

Expand All @@ -192,7 +199,7 @@ class DartDoc {

List<LibraryElement> _parseLibraries(
List<String> files, List<String> includeExternals) {
List<LibraryElement> libraries = [];
Set<LibraryElement> libraries = new Set();
DartSdk sdk = new FolderBasedDartSdk(PhysicalResourceProvider.INSTANCE,
PhysicalResourceProvider.INSTANCE.getFolder(sdkDir.path));
List<UriResolver> resolvers = [];
Expand Down Expand Up @@ -257,7 +264,7 @@ class DartDoc {
sources.add(source);
if (context.computeKindOf(source) == SourceKind.LIBRARY) {
LibraryElement library = context.computeLibraryElement(source);
libraries.add(library);
if (!isPrivate(library)) libraries.add(library);
}
}

Expand All @@ -281,11 +288,35 @@ class DartDoc {
LibraryElement library = context.computeLibraryElement(source);
String libraryName = Library.getLibraryName(library);
var fullPath = source.fullName;

if (includeExternals.any((string) => fullPath.endsWith(string))) {
if (libraries.map(Library.getLibraryName).contains(libraryName)) {
continue;
}
libraries.add(library);
} else if (config != null &&
config.autoIncludeDependencies &&
libraryName != '') {
File searchFile = new File(fullPath);
searchFile =
new File(path.join(searchFile.parent.path, 'pubspec.yaml'));
bool foundLibSrc = false;
while (!foundLibSrc && searchFile.parent != null) {
if (searchFile.existsSync()) break;
List<String> pathParts = path.split(searchFile.parent.path);
// This is a pretty intensely hardcoded convention, but there seems to
// to be no other way to identify what might be a "top level" library
// here. If lib/src is in the path between the file and the pubspec,
// assume that this is supposed to be private.
if (pathParts.length < 2) break;
pathParts = pathParts.sublist(pathParts.length - 2, pathParts.length);
foundLibSrc =
path.join(pathParts[0], pathParts[1]) == path.join('lib', 'src');
searchFile = new File(
path.join(searchFile.parent.parent.path, 'pubspec.yaml'));
}
if (foundLibSrc) continue;
libraries.add(library);
}
}

Expand Down Expand Up @@ -376,26 +407,3 @@ class _Error implements Comparable<_Error> {
@override
String toString() => '[${severityName}] ${description}';
}

Iterable<LibraryElement> _buildLibrariesWithAutoincludedDependencies(
Package package) {
final List<LibraryElement> newLibraryElements = []
..addAll(package.libraries.map((l) => l.element as LibraryElement));

package.allModelElements.forEach((modelElement) {
modelElement.usedElements.forEach((used) {
if (used != null && used.modelType != null) {
final ModelElement modelTypeElement = used.modelType.element;
final library = package.findLibraryFor(modelTypeElement.element);
if (library == null && modelTypeElement.library != null) {
if (!newLibraryElements.contains(modelTypeElement.library.element) &&
!modelTypeElement.library.name.startsWith("dart:")) {
newLibraryElements.add(modelTypeElement.library.element);
}
}
}
});
});

return newLibraryElements;
}
6 changes: 5 additions & 1 deletion lib/src/element_type.dart
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,11 @@ class ElementType {
String get name => _type.name;

ModelElement get returnElement {
Element e = _returnTypeCore.element;
Element e;
if (_type is FunctionType)
e = _returnTypeCore.element;
else
e = _type.element;
if (e == null || e.library == null) {
return null;
}
Expand Down
76 changes: 0 additions & 76 deletions lib/src/export_graph.dart

This file was deleted.

Loading