Skip to content

Commit c4b8764

Browse files
committed
use origin libraries if public
Use pkg/resource to load assets Closes #1089
1 parent 2d943ca commit c4b8764

File tree

73 files changed

+3044
-203
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

73 files changed

+3044
-203
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ packages
1010
.packages
1111
.settings/
1212
.DS_Store
13+
.atom
1314
*.iml
1415

1516
pub.dartlang.org/

lib/src/html/resource_loader.dart

Lines changed: 3 additions & 135 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,8 @@ library dartdoc.resource_loader;
1212

1313
import 'dart:async' show Future;
1414
import 'dart:convert' show UTF8;
15-
import 'dart:io' show Platform, File, Directory;
16-
import 'dart:typed_data' show Uint8List;
1715

18-
import 'package:http/http.dart' as http;
19-
import 'package:path/path.dart' as p;
20-
import 'package:pub_cache/pub_cache.dart';
16+
import 'package:resource/resource.dart';
2117

2218
/// Loads a `package:` resource as a String.
2319
Future<String> loadAsString(String path) async {
@@ -32,135 +28,7 @@ Future<List<int>> loadAsBytes(String path) async {
3228
throw new ArgumentError('path must begin with package:');
3329
}
3430

35-
// TODO: Remove once https://github.com/dart-lang/pub/issues/22 is fixed.
36-
try {
37-
return await _doLoad(path);
38-
} catch (_) {
39-
return new Resource(path).readAsBytes();
40-
}
41-
}
42-
43-
/// Determine how to do the load. HTTP? Snapshotted? From source?
44-
Future<Uint8List> _doLoad(final String path) {
45-
var scriptUri = Platform.script;
46-
if (scriptUri.toString().startsWith('http')) {
47-
return _doLoadOverHttp(path);
48-
} else if (scriptUri.toString().endsWith('.snapshot')) {
49-
return _doLoadWhenSnapshot(path);
50-
} else {
51-
return _doLoadFromFileFromPackagesDir(path);
52-
}
53-
}
54-
55-
Future<Uint8List> _doLoadWhenSnapshot(final String resourcePath) {
56-
var scriptFilePath = Platform.script.toFilePath();
57-
// Check if we're running as a pub globally installed package
58-
// Jump back out to where our source is
59-
var cacheDirPath = PubCache.getSystemCacheLocation().path;
60-
if (scriptFilePath.startsWith(cacheDirPath)) {
61-
// find packages installed with pub
62-
var appName = _appNameWhenGloballyInstalled();
63-
var installedApplication = new PubCache()
64-
.getGlobalApplications()
65-
.firstWhere((app) => app.name == appName);
66-
if (installedApplication == null) {
67-
throw new StateError(
68-
'Could not find globally installed app $appName. Are you running as a snapshot from the global_packages directory?');
69-
}
70-
var resourcePackageName = _packageNameForResource(resourcePath);
71-
var resourcePackageRef = installedApplication
72-
.getPackageRefs()
73-
.firstWhere((ref) => ref.name == resourcePackageName);
74-
if (resourcePackageRef == null) {
75-
throw new StateError(
76-
'Could not find package dependency for $resourcePackageName');
77-
}
78-
var resourcePackage = resourcePackageRef.resolve();
79-
var resourcePackageDir = resourcePackage.location;
80-
var fullPath = resourcePackageDir.path;
81-
return _doLoadOverFileFromLocation(resourcePath, p.join(fullPath, "lib"));
82-
} else {
83-
// maybe we're a snapshot next to a packages/ dir?
84-
return _doLoadFromFileFromPackagesDir(resourcePath);
85-
}
86-
}
87-
88-
Future<Uint8List> _doLoadOverHttp(final String resourcePath) {
89-
var scriptUri = Platform.script;
90-
var convertedResourcePath = _convertPackageSchemeToPackagesDir(resourcePath);
91-
// strip file name from script uri, append path to resource
92-
var segmentsToResource = scriptUri.pathSegments
93-
.sublist(0, scriptUri.pathSegments.length - 1)
94-
..addAll(p.split(convertedResourcePath));
95-
var fullPath = scriptUri.replace(pathSegments: segmentsToResource);
96-
97-
return http.readBytes(fullPath);
98-
}
99-
100-
Future<Uint8List> _doLoadOverFileFromLocation(
101-
final String resourcePath, final String baseDir) {
102-
var convertedPath = _convertPackageSchemeToPackagesDir(resourcePath);
103-
// remove 'packages' and package name
104-
var pathInsideLib = p.split(convertedPath).sublist(2);
105-
// put the baseDir in front
106-
pathInsideLib.insert(0, baseDir);
107-
// put it all back together
108-
var fullPath = p.joinAll(pathInsideLib);
109-
return _readFile(resourcePath, fullPath);
110-
}
111-
112-
/// First, try a packages/ dir next to the entry point (Platform.script).
113-
/// If that doesn't exist, try a packages/ dir inside of the current
114-
/// working directory.
115-
Future<Uint8List> _doLoadFromFileFromPackagesDir(final String resourcePath) {
116-
var convertedPath = _convertPackageSchemeToPackagesDir(resourcePath);
117-
var scriptFile = new File(Platform.script.toFilePath());
118-
String baseDir = p.dirname(scriptFile.path);
119-
120-
if (!new Directory(p.join(baseDir, 'packages')).existsSync()) {
121-
// try CWD
122-
baseDir = Directory.current.path;
123-
}
124-
125-
var fullPath = p.join(baseDir, convertedPath);
126-
return _readFile(resourcePath, fullPath);
127-
}
128-
129-
Future<Uint8List> _readFile(
130-
final String resourcePath, final String fullPath) async {
131-
var file = new File(fullPath);
132-
if (!file.existsSync()) {
133-
throw new ArgumentError('$resourcePath does not exist, tried $fullPath');
134-
}
135-
var bytes = await file.readAsBytes();
136-
return new Uint8List.fromList(bytes);
137-
}
138-
139-
String _convertPackageSchemeToPackagesDir(String resourcePath) {
140-
var withoutScheme = _removePackageScheme(resourcePath);
141-
return p.join('packages', withoutScheme);
142-
}
143-
144-
String _removePackageScheme(final String resourcePath) {
145-
return resourcePath.substring('package:'.length, resourcePath.length);
146-
}
147-
148-
/// Tries to determine the app name, which is the same as the directory
149-
/// name when globally installed.
150-
///
151-
/// Only call this if your app is globally installed.
152-
String _appNameWhenGloballyInstalled() {
153-
var parts = p.split(Platform.script.toFilePath());
154-
var marker = parts.indexOf('global_packages');
155-
if (marker < 0) {
156-
throw new StateError(
157-
'${Platform.script.toFilePath()} does not include global_packages');
158-
}
159-
return parts[marker + 1];
160-
}
31+
var uri = Uri.parse(path);
16132

162-
String _packageNameForResource(final String resourcePath) {
163-
var parts = p.split(_convertPackageSchemeToPackagesDir(resourcePath));
164-
// first part is 'packages', second part is the package name
165-
return parts[1];
33+
return await ResourceLoader.defaultLoader.readAsBytes(uri);
16634
}

lib/src/model.dart

Lines changed: 64 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,9 @@ class Class extends ModelElement implements EnclosedElement {
217217
}
218218

219219
/// Returns the library that encloses this element.
220+
///
221+
/// If this class is exported by a library, this returns
222+
/// the exporting library.
220223
ModelElement get enclosingElement => library;
221224

222225
String get fileName => "${name}-class.html";
@@ -320,7 +323,7 @@ class Class extends ModelElement implements EnclosedElement {
320323
isPublic(value) &&
321324
!value.isOperator &&
322325
value.enclosingElement != null) {
323-
if (!package.isDocumented(value.enclosingElement)) {
326+
if (!package.isInLibraryAndExported(value.enclosingElement)) {
324327
Method m = new Method.inherited(value, this, library);
325328
_inheritedMethods.add(m);
326329
_genPageMethods.add(m);
@@ -375,7 +378,7 @@ class Class extends ModelElement implements EnclosedElement {
375378
}
376379

377380
for (ExecutableElement value in vs.values) {
378-
if (!package.isDocumented(value.enclosingElement)) {
381+
if (!package.isInLibraryAndExported(value.enclosingElement)) {
379382
Operator o = new Operator.inherited(value, this, library);
380383
_inheritedOperators.add(o);
381384
_genPageOperators.add(o);
@@ -437,7 +440,7 @@ class Class extends ModelElement implements EnclosedElement {
437440
if (_inheritedProperties.any((f) => f.element == e)) {
438441
continue;
439442
}
440-
if (!package.isDocumented(value.enclosingElement)) {
443+
if (!package.isInLibraryAndExported(value.enclosingElement)) {
441444
Field f = new Field.inherited(e, this, library);
442445
_inheritedProperties.add(f);
443446
_genPageProperties.add(f);
@@ -681,6 +684,8 @@ class Dynamic extends ModelElement {
681684
///
682685
/// Libraries are not enclosed.
683686
abstract class EnclosedElement {
687+
/// Returns the enclosing element, or null
688+
/// if this is a library.
684689
ModelElement get enclosingElement;
685690
}
686691

@@ -986,7 +991,13 @@ class Library extends ModelElement {
986991
.where((element) => element is FunctionElement));
987992

988993
_functions = elements.where(isPublic).map((e) {
989-
return new ModelFunction(e, this);
994+
// TODO: port this logic to all names that come from exported libraries
995+
if (e.library == this._library ||
996+
!package._libraryElements.contains(e.library)) {
997+
return new ModelFunction(e, this);
998+
} else {
999+
return new ModelFunction(e, new Library(e.library, this.package));
1000+
}
9901001
}).toList(growable: false)..sort(byName);
9911002

9921003
return _functions;
@@ -1061,12 +1072,19 @@ class Library extends ModelElement {
10611072
elements.addAll(cu.functionTypeAliases);
10621073
}
10631074

1064-
elements.addAll(_exportedNamespace.definedNames.values
1065-
.where((element) => element is FunctionTypeAliasElement));
1066-
elements..removeWhere(isPrivate);
1067-
_typeDefs = elements
1068-
.map((e) => new Typedef(e, this))
1069-
.toList(growable: false)..sort(byName);
1075+
elements
1076+
..addAll(_exportedNamespace.definedNames.values
1077+
.where((element) => element is FunctionTypeAliasElement))
1078+
..removeWhere(isPrivate);
1079+
_typeDefs = elements.map((e) {
1080+
// TODO: port this logic to all names that come from exported libraries
1081+
if (e.library == this._library ||
1082+
!package._libraryElements.contains(e.library)) {
1083+
return new Typedef(e, this);
1084+
} else {
1085+
return new Typedef(e, new Library(e.library, this.package));
1086+
}
1087+
}).toList(growable: false)..sort(byName);
10701088

10711089
return _typeDefs;
10721090
}
@@ -1080,18 +1098,23 @@ class Library extends ModelElement {
10801098
types.addAll(cu.types);
10811099
}
10821100
for (LibraryElement le in _library.exportedLibraries) {
1083-
types.addAll(le.definingCompilationUnit.types
1084-
.where((t) => _exportedNamespace.definedNames.values.contains(t.name))
1085-
.toList());
1101+
types.addAll(le.definingCompilationUnit.types.where(
1102+
(t) => _exportedNamespace.definedNames.values.contains(t.name)));
10861103
}
10871104

1105+
// TODO: does this code duplicate the above loop through exportedLibraries?
10881106
types.addAll(_exportedNamespace.definedNames.values
10891107
.where((element) => element is ClassElement && !element.isEnum));
10901108

1091-
_classes = types
1092-
.where(isPublic)
1093-
.map((e) => new Class(e, this))
1094-
.toList(growable: false)..sort(byName);
1109+
_classes = types.where(isPublic).map((e) {
1110+
// TODO: port this logic to all names that come from exported libraries
1111+
if (e.library == this._library ||
1112+
!package._libraryElements.contains(e.library)) {
1113+
return new Class(e, this);
1114+
} else {
1115+
return new Class(e, new Library(e.library, this.package));
1116+
}
1117+
}).toList(growable: false)..sort(byName);
10951118

10961119
return _classes;
10971120
}
@@ -1105,13 +1128,15 @@ class Library extends ModelElement {
11051128
bool hasInExportedNamespace(Element element) {
11061129
Element found = _exportedNamespace.get(element.name);
11071130
if (found == null) return false;
1108-
if (found == element) return true; // this checks more than just the name
11091131

11101132
// Fix for #587, comparison between elements isn't reliable on windows.
11111133
// for some reason. sigh.
11121134

1113-
return found.runtimeType == element.runtimeType &&
1114-
found.nameOffset == element.nameOffset;
1135+
bool isSame = (found == element) ||
1136+
found.runtimeType == element.runtimeType &&
1137+
found.nameOffset == element.nameOffset;
1138+
1139+
return isSame;
11151140
}
11161141

11171142
List<TopLevelVariable> _getVariables() {
@@ -1125,10 +1150,15 @@ class Library extends ModelElement {
11251150
_exportedNamespace.definedNames.values.forEach((element) {
11261151
if (element is PropertyAccessorElement) elements.add(element.variable);
11271152
});
1128-
_variables = elements
1129-
.where(isPublic)
1130-
.map((e) => new TopLevelVariable(e, this))
1131-
.toList(growable: false)..sort(byName);
1153+
_variables = elements.where(isPublic).map((e) {
1154+
// TODO: port this logic to all names that come from exported libraries
1155+
if (e.library == this._library ||
1156+
!package._libraryElements.contains(e.library)) {
1157+
return new TopLevelVariable(e, this);
1158+
} else {
1159+
return new TopLevelVariable(e, new Library(e.library, this.package));
1160+
}
1161+
}).toList(growable: false)..sort(byName);
11321162

11331163
return _variables;
11341164
}
@@ -1539,15 +1569,17 @@ abstract class ModelElement implements Comparable, Nameable, Documentable {
15391569
if (name.startsWith('_')) {
15401570
return HTML_ESCAPE.convert(name);
15411571
}
1542-
if (!(this is Method || this is Field) && !package.isDocumented(element)) {
1572+
if (!(this is Method || this is Field) &&
1573+
!package.isInLibraryAndExported(element)) {
15431574
return HTML_ESCAPE.convert(name);
15441575
}
15451576

1577+
// TODO: get the library that is exporting this class, not just containing it
15461578
ModelElement c = (this is EnclosedElement)
15471579
? (this as EnclosedElement).enclosingElement
15481580
: null;
15491581
if (c != null) {
1550-
if (!package.isDocumented(c.element)) {
1582+
if (!package.isInLibraryAndExported(c.element)) {
15511583
return HTML_ESCAPE.convert(name);
15521584
}
15531585
if (c.name.startsWith('_')) {
@@ -1651,12 +1683,14 @@ class Operator extends Method {
16511683
}
16521684

16531685
class Package implements Nameable, Documentable {
1686+
final List<LibraryElement> _libraryElements = [];
16541687
final List<Library> _libraries = [];
16551688
final PackageMeta packageMeta;
16561689
final Map<String, Library> elementLibaryMap = {};
16571690
String _docsAsHtml;
16581691

16591692
Package(Iterable<LibraryElement> libraryElements, this.packageMeta) {
1693+
_libraryElements.addAll(libraryElements);
16601694
libraryElements.forEach((element) {
16611695
// add only if the element should be included in the public api
16621696
if (isPublic(element)) {
@@ -1740,11 +1774,14 @@ class Package implements Nameable, Documentable {
17401774
} else {
17411775
el = element;
17421776
}
1777+
17431778
return _libraries.firstWhere((lib) => lib.hasInExportedNamespace(el),
17441779
orElse: () => null);
17451780
}
17461781

1747-
bool isDocumented(Element element) => findLibraryFor(element) != null;
1782+
/// Returns true if element is found in a library in this package.
1783+
bool isInLibraryAndExported(Element element) =>
1784+
findLibraryFor(element) != null;
17481785

17491786
String toString() => isSdk ? 'SDK' : 'Package $name';
17501787

0 commit comments

Comments
 (0)