OLD | NEW |
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 library location; | 5 library location; |
6 | 6 |
7 import 'package:observe/observe.dart'; | 7 import 'package:observe/observe.dart'; |
8 | 8 |
9 // These regular expressions are not strictly accurate for picking Dart | 9 // These regular expressions are not strictly accurate for picking Dart |
10 // identifiers out of arbitrary text, e.g. identifiers must start with an | 10 // identifiers out of arbitrary text, e.g. identifiers must start with an |
(...skipping 20 matching lines...) Expand all Loading... |
31 /// link which is to a method on the same page as its class. So, e.g. | 31 /// link which is to a method on the same page as its class. So, e.g. |
32 /// in `dart-core.Object@id_noSuchMethod,invocation` this separates | 32 /// in `dart-core.Object@id_noSuchMethod,invocation` this separates |
33 /// the method `noSuchMethod` from the parameter `invocation`. | 33 /// the method `noSuchMethod` from the parameter `invocation`. |
34 const PARAMETER_SEPARATOR = ","; | 34 const PARAMETER_SEPARATOR = ","; |
35 | 35 |
36 /// The character used to separate the class name from the constructor | 36 /// The character used to separate the class name from the constructor |
37 /// name, e.g. `Future.Future-delayed`. Will occur by itself for | 37 /// name, e.g. `Future.Future-delayed`. Will occur by itself for |
38 /// an unnamed constructor. e.g. `Future.Future-` | 38 /// an unnamed constructor. e.g. `Future.Future-` |
39 const CONSTRUCTOR_SEPARATOR = "-"; | 39 const CONSTRUCTOR_SEPARATOR = "-"; |
40 | 40 |
| 41 /// The prefix to be used for anchors. This is here so that we can easily |
| 42 /// factor it out into being #! and use the _escaped_fragment_ scheme |
| 43 /// for providing static versions of pages if we get them. See |
| 44 /// https://developers.google.com/webmasters/ajax-crawling/ |
| 45 const AJAX_LOCATION_PREFIX = "#!"; |
| 46 const BASIC_LOCATION_PREFIX = "#"; |
| 47 |
| 48 // Prefix the string with the separator we are using between the main |
| 49 // URL and the location. |
| 50 locationPrefixed(String s) => "$BASIC_LOCATION_PREFIX$s"; |
| 51 |
| 52 // Remove the anchor prefix from [s] if it's present. |
| 53 locationDeprefixed(String s) { |
| 54 if (s.startsWith(AJAX_LOCATION_PREFIX)) { |
| 55 return s.substring(AJAX_LOCATION_PREFIX.length, s.length); |
| 56 } else if (s.startsWith(BASIC_LOCATION_PREFIX)) { |
| 57 return s.substring(BASIC_LOCATION_PREFIX.length, s.length); |
| 58 } else { |
| 59 return s; |
| 60 } |
| 61 } |
| 62 |
41 // This represents a component described by a URI and can give us | 63 // This represents a component described by a URI and can give us |
42 // the URI given the component or vice versa. | 64 // the URI given the component or vice versa. |
43 class DocsLocation { | 65 class DocsLocation { |
44 String packageName; | 66 String packageName; |
45 String libraryName; | 67 String libraryName; |
46 String memberName; | 68 String memberName; |
47 String subMemberName; | 69 String subMemberName; |
48 String anchor; | 70 String anchor; |
49 | 71 |
50 // TODO(alanknight): These might be nicer to work with as immutable value | 72 // TODO(alanknight): These might be nicer to work with as immutable value |
(...skipping 30 matching lines...) Expand all Loading... |
81 } | 103 } |
82 | 104 |
83 /// This isn't a particularly good hash code, but we don't really hash | 105 /// This isn't a particularly good hash code, but we don't really hash |
84 /// these very much. Just XOR together all the fields. | 106 /// these very much. Just XOR together all the fields. |
85 int get hashCode => packageName.hashCode ^ libraryName.hashCode ^ | 107 int get hashCode => packageName.hashCode ^ libraryName.hashCode ^ |
86 memberName.hashCode ^ subMemberName.hashCode ^ anchor.hashCode; | 108 memberName.hashCode ^ subMemberName.hashCode ^ anchor.hashCode; |
87 | 109 |
88 void _extractPieces(String uri) { | 110 void _extractPieces(String uri) { |
89 | 111 |
90 if (uri == null || uri.length == 0) return; | 112 if (uri == null || uri.length == 0) return; |
91 var position = (uri[0] == "#") ? 1 : 0; | 113 var position = uri.startsWith(AJAX_LOCATION_PREFIX) ? |
| 114 AJAX_LOCATION_PREFIX.length : 0; |
92 | 115 |
93 _check(regex) { | 116 _check(regex) { |
94 var match = regex.matchAsPrefix(uri, position); | 117 var match = regex.matchAsPrefix(uri, position); |
95 if (match != null) { | 118 if (match != null) { |
96 var matchedString = match.group(1); | 119 var matchedString = match.group(1); |
97 position = position + match.group(0).length; | 120 position = position + match.group(0).length; |
98 return matchedString; | 121 return matchedString; |
99 } | 122 } |
100 } | 123 } |
101 | 124 |
102 packageName = _check(packageMatch); | 125 packageName = _check(packageMatch); |
103 libraryName = _check(libraryMatch); | 126 libraryName = _check(libraryMatch); |
104 memberName = _check(memberMatch); | 127 memberName = _check(memberMatch); |
105 subMemberName = _check(subMemberMatch); | 128 subMemberName = _check(subMemberMatch); |
106 anchor = _check(anchorMatch); | 129 anchor = _check(anchorMatch); |
107 if (position < uri.length && anchor == null) { | 130 if (position < uri.length && anchor == null) { |
108 // allow an anchor that's just dotted, not @ if we don't find an @ | 131 // allow an anchor that's just dotted, not @ if we don't find an @ |
109 // form and we haven't reached the end. | 132 // form and we haven't reached the end. |
110 anchor = uri.substring(position + 1, uri.length); | 133 anchor = uri.substring(position + 1, uri.length); |
111 } | 134 } |
112 } | 135 } |
113 | 136 |
114 /// The URI hash string without its leading hash | 137 /// The URI hash string without its leading hash |
115 /// and without any trailing anchor portion, e.g. for | 138 /// and without any trailing anchor portion, e.g. for |
116 /// http://site/#args/args.ArgParser#id_== it would return args/argsArgParser | 139 /// http://site/#args/args.ArgParser@id_== it would return args/argsArgParser |
117 @reflectable String get withoutAnchor => | 140 @reflectable String get withoutAnchor => |
118 [packagePlus, libraryPlus, memberPlus, subMemberPlus].join(""); | 141 [packagePlus, libraryPlus, memberPlus, subMemberPlus].join(""); |
119 | 142 |
120 /// The URI hash for just the library portion of this location. | 143 /// The URI hash for just the library portion of this location. |
121 @reflectable String get libraryQualifiedName => "$packagePlus$libraryPlus"; | 144 @reflectable String get libraryQualifiedName => "$packagePlus$libraryPlus"; |
122 | 145 |
123 /// The full URI hash string without the leading hash character. | 146 /// The full URI hash string without the leading hash character. |
124 /// e.g. for | 147 /// e.g. for |
125 /// http://site/#args/args.ArgParser#id_== | 148 /// http://site/#args/args.ArgParser@id_== |
126 /// it would return args/argsArgParser#id_== | 149 /// it would return args/argsArgParser@id_== |
127 @reflectable String get withAnchor => withoutAnchor + anchorPlus; | 150 @reflectable String get withAnchor => withoutAnchor + anchorPlus; |
128 | 151 |
129 @reflectable DocsLocation get locationWithoutAnchor => | 152 @reflectable DocsLocation get locationWithoutAnchor => |
130 new DocsLocation.clone(this)..anchor = null; | 153 new DocsLocation.clone(this)..anchor = null; |
131 | 154 |
132 /// The package name with the trailing / separator, or the empty | 155 /// The package name with the trailing / separator, or the empty |
133 /// string if the package name is not set. | 156 /// string if the package name is not set. |
134 @reflectable get packagePlus => packageName == null | 157 @reflectable get packagePlus => packageName == null |
135 ? '' | 158 ? '' |
136 : libraryName == null | 159 : libraryName == null |
(...skipping 195 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
332 if (anchor != null) return anchor; | 355 if (anchor != null) return anchor; |
333 if (subMemberName != null) return subMemberName; | 356 if (subMemberName != null) return subMemberName; |
334 if (memberName != null) return memberName; | 357 if (memberName != null) return memberName; |
335 if (libraryName != null) return libraryName; | 358 if (libraryName != null) return libraryName; |
336 if (packageName != null) return packageName; | 359 if (packageName != null) return packageName; |
337 return null; | 360 return null; |
338 } | 361 } |
339 | 362 |
340 @reflectable toString() => 'DocsLocation($withAnchor)'; | 363 @reflectable toString() => 'DocsLocation($withAnchor)'; |
341 } | 364 } |
OLD | NEW |