Version 0.3.7.6
Merge revisions 18686 and 18715 to trunk
git-svn-id: http://dart.googlecode.com/svn/trunk@18717 260f80e4-7a28-3924-810f-c04153c831b5
diff --git a/pkg/args/test/usage_test.dart b/pkg/args/test/usage_test.dart
index b29bf95..6068f32 100644
--- a/pkg/args/test/usage_test.dart
+++ b/pkg/args/test/usage_test.dart
@@ -211,5 +211,5 @@
}
}
- return Strings.join(lines, '\n');
+ return lines.join('\n');
}
diff --git a/pkg/http/lib/src/utils.dart b/pkg/http/lib/src/utils.dart
index a70e937..739a567 100644
--- a/pkg/http/lib/src/utils.dart
+++ b/pkg/http/lib/src/utils.dart
@@ -38,7 +38,7 @@
var pairs = <List<String>>[];
map.forEach((key, value) =>
pairs.add([encodeUriComponent(key), encodeUriComponent(value)]));
- return Strings.join(pairs.map((pair) => "${pair[0]}=${pair[1]}"), "&");
+ return pairs.map((pair) => "${pair[0]}=${pair[1]}").join("&");
}
/// Adds all key/value pairs from [source] to [destination], overwriting any
diff --git a/pkg/oauth2/lib/src/authorization_code_grant.dart b/pkg/oauth2/lib/src/authorization_code_grant.dart
index b361f21..b199579 100644
--- a/pkg/oauth2/lib/src/authorization_code_grant.dart
+++ b/pkg/oauth2/lib/src/authorization_code_grant.dart
@@ -139,7 +139,7 @@
};
if (state != null) parameters['state'] = state;
- if (!scopes.isEmpty) parameters['scope'] = Strings.join(scopes, ' ');
+ if (!scopes.isEmpty) parameters['scope'] = scopes.join(' ');
return addQueryParameters(this.authorizationEndpoint, parameters);
}
diff --git a/pkg/oauth2/lib/src/credentials.dart b/pkg/oauth2/lib/src/credentials.dart
index 17cd410..26112c6 100644
--- a/pkg/oauth2/lib/src/credentials.dart
+++ b/pkg/oauth2/lib/src/credentials.dart
@@ -171,7 +171,7 @@
"client_id": identifier,
"client_secret": secret
};
- if (!scopes.isEmpty) fields["scope"] = Strings.join(scopes, ' ');
+ if (!scopes.isEmpty) fields["scope"] = scopes.join(' ');
return httpClient.post(tokenEndpoint, fields: fields);
}).then((response) {
diff --git a/pkg/oauth2/lib/src/utils.dart b/pkg/oauth2/lib/src/utils.dart
index 83fe2b7..f69ac8b 100644
--- a/pkg/oauth2/lib/src/utils.dart
+++ b/pkg/oauth2/lib/src/utils.dart
@@ -39,10 +39,10 @@
value = (value == null || value.isEmpty) ? null : encodeUriComponent(value);
pairs.add([key, value]);
});
- return Strings.join(pairs.map((pair) {
+ return pairs.map((pair) {
if (pair[1] == null) return pair[0];
return "${pair[0]}=${pair[1]}";
- }), "&");
+ }).join("&");
}
/// Add all key/value pairs from [source] to [destination], overwriting any
diff --git a/pkg/scheduled_test/test/metatest.dart b/pkg/scheduled_test/test/metatest.dart
index ff85d51..2a83015 100644
--- a/pkg/scheduled_test/test/metatest.dart
+++ b/pkg/scheduled_test/test/metatest.dart
@@ -170,7 +170,7 @@
// TODO(nweiz): Use this simpler code once issue 2980 is fixed.
// return str.replaceAll(new RegExp("^", multiLine: true), " ");
- return Strings.join(str.split("\n").map((line) => " $line"), "\n");
+ return str.split("\n").map((line) => " $line").join("\n");
}
/// Ensure that the metatest configuration is loaded.
diff --git a/pkg/unittest/lib/src/config.dart b/pkg/unittest/lib/src/config.dart
index 73de212..2cd2334 100644
--- a/pkg/unittest/lib/src/config.dart
+++ b/pkg/unittest/lib/src/config.dart
@@ -146,7 +146,7 @@
// TODO(nweiz): Use this simpler code once issue 2980 is fixed.
// return str.replaceAll(new RegExp("^", multiLine: true), " ");
- return Strings.join(str.split("\n").map((line) => " $line"), "\n");
+ return str.split("\n").map((line) => " $line").join("\n");
}
/** Handle errors that happen outside the tests. */
diff --git a/pkg/yaml/lib/model.dart b/pkg/yaml/lib/model.dart
index 7a609b9..9f1474e 100644
--- a/pkg/yaml/lib/model.dart
+++ b/pkg/yaml/lib/model.dart
@@ -90,8 +90,7 @@
return true;
}
- String toString() =>
- '$tag [${Strings.join(content.map((e) => '$e'), ', ')}]';
+ String toString() => '$tag [${content.map((e) => '$e').join(', ')}]';
int get hashCode => super.hashCode ^ _hashCode(content);
@@ -179,7 +178,7 @@
}
}
});
- return '"${Strings.join(escapedValue, '')}"';
+ return '"${escapedValue.join()}"';
}
throw new YamlException("unknown scalar value: $value");
@@ -193,7 +192,7 @@
assert(length >= str.length);
var prefix = [];
prefix.insertRange(0, length - str.length, '0');
- return '${Strings.join(prefix, '')}$str';
+ return '${prefix.join()}$str';
}
int get hashCode => super.hashCode ^ content.hashCode;
diff --git a/pkg/yaml/test/yaml_test.dart b/pkg/yaml/test/yaml_test.dart
index b939b67..901bd3d 100644
--- a/pkg/yaml/test/yaml_test.dart
+++ b/pkg/yaml/test/yaml_test.dart
@@ -1350,7 +1350,7 @@
// TODO(nweiz): enable this when we throw an error for long keys
// var dotList = [];
// dotList.insertRange(0, 1024, ' ');
- // var dots = Strings.join(dotList, '');
+ // var dots = dotList.join();
// Expect.throws(() => loadYaml('[ "foo...$dots...bar": invalid ]'));
});
});
diff --git a/runtime/lib/string_buffer_patch.dart b/runtime/lib/string_buffer_patch.dart
index ac700bf..8fadafa 100644
--- a/runtime/lib/string_buffer_patch.dart
+++ b/runtime/lib/string_buffer_patch.dart
@@ -43,7 +43,7 @@
/* patch */ String toString() {
if (_buffer.length == 0) return "";
if (_buffer.length == 1) return _buffer[0];
- String result = Strings.concatAll(_buffer);
+ String result = _StringBase.concatAll(_buffer);
_buffer.clear();
_buffer.add(result);
// Since we track the length at each add operation, there is no
diff --git a/runtime/lib/string_patch.dart b/runtime/lib/string_patch.dart
index 7157ff9..6a9cf54 100644
--- a/runtime/lib/string_patch.dart
+++ b/runtime/lib/string_patch.dart
@@ -7,13 +7,3 @@
return _StringBase.createFromCharCodes(charCodes);
}
}
-
-patch class Strings {
- /* patch */ static String join(Iterable<String> strings, String separator) {
- return _StringBase.join(strings, separator);
- }
-
- /* patch */ static String concatAll(List<String> strings) {
- return _StringBase.concatAll(strings);
- }
-}
diff --git a/sdk/lib/_internal/compiler/implementation/lib/core_patch.dart b/sdk/lib/_internal/compiler/implementation/lib/core_patch.dart
index b542b7a..b0f09ccf 100644
--- a/sdk/lib/_internal/compiler/implementation/lib/core_patch.dart
+++ b/sdk/lib/_internal/compiler/implementation/lib/core_patch.dart
@@ -202,33 +202,6 @@
}
}
-// Patch for String implementation.
-patch class Strings {
- patch static String join(Iterable<String> strings, String separator) {
- checkNull(strings);
- if (separator is !String) throw new ArgumentError(separator);
- return stringJoinUnchecked(_toJsStringArray(strings), separator);
- }
-
- patch static String concatAll(Iterable<String> strings) {
- return stringJoinUnchecked(_toJsStringArray(strings), "");
- }
-
- static List _toJsStringArray(Iterable<String> strings) {
- checkNull(strings);
- var array;
- if (!isJsArray(strings)) {
- strings = new List.from(strings);
- }
- final length = strings.length;
- for (int i = 0; i < length; i++) {
- final string = strings[i];
- if (string is !String) throw new ArgumentError(string);
- }
- return strings;
- }
-}
-
patch class RegExp {
patch factory RegExp(String pattern,
{bool multiLine: false,
diff --git a/sdk/lib/_internal/dartdoc/lib/dartdoc.dart b/sdk/lib/_internal/dartdoc/lib/dartdoc.dart
index 59ab485..e0305ab 100644
--- a/sdk/lib/_internal/dartdoc/lib/dartdoc.dart
+++ b/sdk/lib/_internal/dartdoc/lib/dartdoc.dart
@@ -691,7 +691,7 @@
for (final typeVariable in type.originalDeclaration.typeVariables) {
typeVariables.add(typeVariable.displayName);
}
- typeInfo[ARGS] = Strings.join(typeVariables, ', ');
+ typeInfo[ARGS] = typeVariables.join(', ');
}
types.add(typeInfo);
}
@@ -1766,15 +1766,14 @@
if (typeParams.isEmpty) {
return type.simpleName;
}
- final params = Strings.join(typeParams, ', ');
+ final params = typeParams.join(', ');
return '${type.simpleName}<$params>';
}
// See if it's an instantiation of a generic type.
final typeArgs = type.typeArguments;
if (typeArgs.length > 0) {
- final args =
- Strings.join(typeArgs.map((arg) => typeName(arg)), ', ');
+ final args = typeArgs.map((arg) => typeName(arg)).join(', ');
return '${type.originalDeclaration.simpleName}<$args>';
}
@@ -1793,7 +1792,7 @@
lines[i] = unindent(lines[i], column);
}
- final code = Strings.join(lines, '\n');
+ final code = lines.join('\n');
return code;
}
diff --git a/sdk/lib/_internal/dartdoc/lib/src/dartdoc/utils.dart b/sdk/lib/_internal/dartdoc/lib/src/dartdoc/utils.dart
index 79a9aa6..59e14b5 100644
--- a/sdk/lib/_internal/dartdoc/lib/src/dartdoc/utils.dart
+++ b/sdk/lib/_internal/dartdoc/lib/src/dartdoc/utils.dart
@@ -68,7 +68,7 @@
String joinWithCommas(List<String> items, [String conjunction = 'and']) {
if (items.length == 1) return items[0];
if (items.length == 2) return "${items[0]} $conjunction ${items[1]}";
- return '${Strings.join(items.getRange(0, items.length - 1), ', ')}'
+ return '${items.getRange(0, items.length - 1).join(', ')}'
', $conjunction ${items[items.length - 1]}';
}
diff --git a/sdk/lib/_internal/dartdoc/lib/src/markdown/block_parser.dart b/sdk/lib/_internal/dartdoc/lib/src/markdown/block_parser.dart
index 67109a4..a5be1a7 100644
--- a/sdk/lib/_internal/dartdoc/lib/src/markdown/block_parser.dart
+++ b/sdk/lib/_internal/dartdoc/lib/src/markdown/block_parser.dart
@@ -234,7 +234,7 @@
childLines.add('');
// Escape the code.
- final escaped = classifySource(Strings.join(childLines, '\n'));
+ final escaped = classifySource(childLines.join('\n'));
return new Element.text('pre', escaped);
}
@@ -275,7 +275,7 @@
parser.advance();
}
- return new Text(Strings.join(childLines, '\n'));
+ return new Text(childLines.join('\n'));
}
}
@@ -457,8 +457,7 @@
parser.advance();
}
- final contents = parser.document.parseInline(
- Strings.join(childLines, '\n'));
+ final contents = parser.document.parseInline(childLines.join('\n'));
return new Element('p', contents);
}
}
diff --git a/sdk/lib/_internal/dartdoc/test/markdown_test.dart b/sdk/lib/_internal/dartdoc/test/markdown_test.dart
index b786f94..bd23384 100644
--- a/sdk/lib/_internal/dartdoc/test/markdown_test.dart
+++ b/sdk/lib/_internal/dartdoc/test/markdown_test.dart
@@ -825,7 +825,7 @@
}
}
- return Strings.join(lines, '\n');
+ return lines.join('\n');
}
validate(String description, String markdown, String html,
diff --git a/sdk/lib/core/core.dart b/sdk/lib/core/core.dart
index ca88387..016d6c0 100644
--- a/sdk/lib/core/core.dart
+++ b/sdk/lib/core/core.dart
@@ -36,5 +36,4 @@
part "string.dart";
part "string_buffer.dart";
part "string_sink.dart";
-part "strings.dart";
part "type.dart";
diff --git a/sdk/lib/core/corelib_sources.gypi b/sdk/lib/core/corelib_sources.gypi
index 529d725..f85e349 100644
--- a/sdk/lib/core/corelib_sources.gypi
+++ b/sdk/lib/core/corelib_sources.gypi
@@ -31,7 +31,6 @@
'set.dart',
'stopwatch.dart',
'string.dart',
- 'strings.dart',
'string_buffer.dart',
'string_sink.dart',
'type.dart',
diff --git a/sdk/lib/core/strings.dart b/sdk/lib/core/strings.dart
deleted file mode 100644
index c8a2afc..0000000
--- a/sdk/lib/core/strings.dart
+++ /dev/null
@@ -1,24 +0,0 @@
-// Copyright (c) 2011, 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.
-
-part of dart.core;
-
-@deprecated
-abstract class Strings {
- /**
- * Joins all the given strings to create a new string.
- *
- * *Deprecated* Use `strings.join(separator)` instead.
- */
- @deprecated
- external static String join(Iterable<String> strings, String separator);
-
- /**
- * Concatenates all the given strings to create a new string.
- *
- * *Deprecated* Use `strings.join()` instead.
- */
- @deprecated
- external static String concatAll(Iterable<String> strings);
-}
diff --git a/sdk/lib/html/dart2js/html_dart2js.dart b/sdk/lib/html/dart2js/html_dart2js.dart
index 3420aff..78346e6 100644
--- a/sdk/lib/html/dart2js/html_dart2js.dart
+++ b/sdk/lib/html/dart2js/html_dart2js.dart
@@ -29753,7 +29753,7 @@
abstract class CssClassSet implements Set<String> {
String toString() {
- return Strings.join(new List.from(readClasses()), ' ');
+ return readClasses().join(' ');
}
/**
diff --git a/sdk/lib/html/dartium/html_dartium.dart b/sdk/lib/html/dartium/html_dartium.dart
index 8a3b951..017bfb3 100644
--- a/sdk/lib/html/dartium/html_dartium.dart
+++ b/sdk/lib/html/dartium/html_dartium.dart
@@ -32238,7 +32238,7 @@
abstract class CssClassSet implements Set<String> {
String toString() {
- return Strings.join(new List.from(readClasses()), ' ');
+ return readClasses().join(' ');
}
/**
diff --git a/sdk/lib/io/path_impl.dart b/sdk/lib/io/path_impl.dart
index 2ea2fea..a42a290 100644
--- a/sdk/lib/io/path_impl.dart
+++ b/sdk/lib/io/path_impl.dart
@@ -103,7 +103,7 @@
if (hasTrailingSeparator) {
segments.add('');
}
- return new Path(Strings.join(segments, '/'));
+ return new Path(segments.join('/'));
}
@@ -210,8 +210,7 @@
segmentsToJoin.add('');
}
}
- return new _Path._internal(Strings.join(segmentsToJoin, '/'),
- isWindowsShare);
+ return new _Path._internal(segmentsToJoin.join('/'), isWindowsShare);
}
String toNativePath() {
diff --git a/sdk/lib/io/process.dart b/sdk/lib/io/process.dart
index 34e0140..e146c61 100644
--- a/sdk/lib/io/process.dart
+++ b/sdk/lib/io/process.dart
@@ -242,7 +242,7 @@
int this.errorCode = 0]);
String toString() {
var msg = (message == null) ? 'OS error code: $errorCode' : message;
- var args = Strings.join(arguments, ' ');
+ var args = arguments.join(' ');
return "ProcessException: $msg\n Command: $executable $args";
}
diff --git a/sdk/lib/svg/dart2js/svg_dart2js.dart b/sdk/lib/svg/dart2js/svg_dart2js.dart
index 7543c2a..4b26804 100644
--- a/sdk/lib/svg/dart2js/svg_dart2js.dart
+++ b/sdk/lib/svg/dart2js/svg_dart2js.dart
@@ -5771,8 +5771,7 @@
}
void writeClasses(Set s) {
- List list = new List.from(s);
- _element.attributes['class'] = Strings.join(list, ' ');
+ _element.attributes['class'] = s.join(' ');
}
}
diff --git a/sdk/lib/svg/dartium/svg_dartium.dart b/sdk/lib/svg/dartium/svg_dartium.dart
index c0d430b..1c03b3a 100644
--- a/sdk/lib/svg/dartium/svg_dartium.dart
+++ b/sdk/lib/svg/dartium/svg_dartium.dart
@@ -6520,8 +6520,7 @@
}
void writeClasses(Set s) {
- List list = new List.from(s);
- _element.attributes['class'] = Strings.join(list, ' ');
+ _element.attributes['class'] = s.join(' ');
}
}
diff --git a/sdk/lib/uri/helpers.dart b/sdk/lib/uri/helpers.dart
index d17810f..2a16a47 100644
--- a/sdk/lib/uri/helpers.dart
+++ b/sdk/lib/uri/helpers.dart
@@ -25,5 +25,5 @@
}
}
if (appendSlash) output.add("");
- return Strings.join(output, "/");
+ return output.join("/");
}
diff --git a/tests/co19/co19-compiler.status b/tests/co19/co19-compiler.status
index 191148a..423a814 100644
--- a/tests/co19/co19-compiler.status
+++ b/tests/co19/co19-compiler.status
@@ -491,5 +491,16 @@
LibTest/core/Set/Set.from_A01_t01: Fail # Moved collection classes from core to collection. co19 issue 371.
+LibTest/core/RegExp/Pattern_semantics/firstMatch_CharacterClassEscape_A03_t01: Fail # Strings class has been removed. co19 issue 380
+LibTest/core/RegExp/Pattern_semantics/firstMatch_CharacterClassEscape_A04_t01: Fail # Strings class has been removed. co19 issue 380
+LibTest/core/Strings/join_A01_t01: Fail # Strings class has been removed. co19 issue 380
+LibTest/core/Strings/join_A02_t01: Fail # Strings class has been removed. co19 issue 380
+LibTest/core/Strings/join_A03_t01: Fail # Strings class has been removed. co19 issue 380
+LibTest/core/Strings/join_A04_t01: Fail # Strings class has been removed. co19 issue 380
+LibTest/core/Strings/concatAll_A01_t01: Fail # Strings class has been removed. co19 issue 380
+LibTest/core/Strings/concatAll_A02_t01: Fail # Strings class has been removed. co19 issue 380
+LibTest/core/Strings/concatAll_A03_t01: Fail # Strings class has been removed. co19 issue 380
+LibTest/core/Strings/concatAll_A04_t01: Fail # Strings class has been removed. co19 issue 380
+
[ $runtime == drt && ($compiler == none || $compiler == frog) ]
*: Skip
diff --git a/tests/co19/co19-dart2dart.status b/tests/co19/co19-dart2dart.status
index 1f87d90..8d256ea 100644
--- a/tests/co19/co19-dart2dart.status
+++ b/tests/co19/co19-dart2dart.status
@@ -654,6 +654,11 @@
LibTest/core/Set/Set.from_A01_t01: Fail # Moved collection classes from core to collection. co19 issue 371.
Language/14_Types/4_Interface_Types_A08_t06: Fail # Moved collection classes from core to collection. co19 issue 371.
+LibTest/core/Strings/join_A01_t01: Fail # Strings class has been removed. co19 issue 380
+LibTest/core/Strings/join_A04_t01: Fail # Strings class has been removed. co19 issue 380
+LibTest/core/Strings/concatAll_A01_t01: Fail # Strings class has been removed. co19 issue 380
+LibTest/core/Strings/concatAll_A04_t01: Fail # Strings class has been removed. co19 issue 380
+
# Doesn't expect null to be allowed in Set or Map keys (issue 377).
LibTest/core/Map/containsKey_A01_t02: Fail
LibTest/core/Map/operator_subscript_A01_t02: Fail
diff --git a/tests/co19/co19-dart2js.status b/tests/co19/co19-dart2js.status
index 1ba4426..41e3a33 100644
--- a/tests/co19/co19-dart2js.status
+++ b/tests/co19/co19-dart2js.status
@@ -575,6 +575,11 @@
LibTest/core/Date/operator_equality_A01_t01: Fail # DateTime.== now looks at timezone, co19 issue 379.
+LibTest/core/Strings/join_A01_t01: Fail # Strings class has been removed. co19 issue 380
+LibTest/core/Strings/join_A04_t01: Fail # Strings class has been removed. co19 issue 380
+LibTest/core/Strings/concatAll_A01_t01: Fail # Strings class has been removed. co19 issue 380
+LibTest/core/Strings/concatAll_A04_t01: Fail # Strings class has been removed. co19 issue 380
+
# Issues with co19 test suite in checked mode.
[ $compiler == dart2js && $checked ]
LibTest/isolate/SendPort/call_A01_t01: Fail # Future is in async library. co19 issue 367
diff --git a/tests/co19/co19-runtime.status b/tests/co19/co19-runtime.status
index 6a312f5..0c4e1d2 100644
--- a/tests/co19/co19-runtime.status
+++ b/tests/co19/co19-runtime.status
@@ -504,6 +504,11 @@
LibTest/core/Queue/removeLast_A02_t01: Fail # Moved collection classes from core to collection. co19 issue 371.
LibTest/core/Set/Set.from_A01_t01: Fail # Moved collection classes from core to collection. co19 issue 371.
+LibTest/core/Strings/join_A01_t01: Fail # Strings class has been removed. co19 issue 380
+LibTest/core/Strings/join_A04_t01: Fail # Strings class has been removed. co19 issue 380
+LibTest/core/Strings/concatAll_A01_t01: Fail # Strings class has been removed. co19 issue 380
+LibTest/core/Strings/concatAll_A04_t01: Fail # Strings class has been removed. co19 issue 380
+
# Doesn't expect null to be allowed in Set or Map keys (issue 377).
LibTest/core/Map/containsKey_A01_t02: Fail
LibTest/core/Map/operator_subscript_A01_t02: Fail
diff --git a/tests/language/named_parameters_with_dollars_test.dart b/tests/language/named_parameters_with_dollars_test.dart
index 6bd7af3..e4f0f27 100644
--- a/tests/language/named_parameters_with_dollars_test.dart
+++ b/tests/language/named_parameters_with_dollars_test.dart
@@ -28,7 +28,7 @@
fragments.add(format(item));
}
fragments.add(']');
- return Strings.concatAll(fragments);
+ return fragments.join();
}
return thing.toString();
}
diff --git a/tests/language/string_join_test.dart b/tests/language/string_join_test.dart
index d332331..c98b79fa 100644
--- a/tests/language/string_join_test.dart
+++ b/tests/language/string_join_test.dart
@@ -8,7 +8,8 @@
List<String> ga = new List<String>();
ga.add("a");
ga.add("b");
- Expect.equals("ab", Strings.join(ga, ""));
+ Expect.equals("ab", ga.join());
+ Expect.equals("ab", ga.join(""));
}
}
diff --git a/tests/language/string_test.dart b/tests/language/string_test.dart
index 9e84396..52cdf71 100644
--- a/tests/language/string_test.dart
+++ b/tests/language/string_test.dart
@@ -24,7 +24,7 @@
List<String> a = new List<String>.fixedLength(2);
a[0] = "Hello";
a[1] = "World";
- String s = Strings.join(a, "*^*");
+ String s = a.join("*^*");
Expect.equals("Hello*^*World", s);
}
diff --git a/tests/standalone/io/secure_socket_bad_certificate_test.dart b/tests/standalone/io/secure_socket_bad_certificate_test.dart
index e3a2616..d53dd93 100644
--- a/tests/standalone/io/secure_socket_bad_certificate_test.dart
+++ b/tests/standalone/io/secure_socket_bad_certificate_test.dart
@@ -63,7 +63,7 @@
};
secure.onClosed = () {
Expect.isTrue(acceptCertificate);
- String fullPage = Strings.concatAll(chunks);
+ String fullPage = chunks.join();
Expect.isTrue(fullPage.contains('</body></html>'));
completer.complete(null);
};
diff --git a/tests/standalone/io/secure_socket_test.dart b/tests/standalone/io/secure_socket_test.dart
index e1fe2a8..f010444 100644
--- a/tests/standalone/io/secure_socket_test.dart
+++ b/tests/standalone/io/secure_socket_test.dart
@@ -53,7 +53,7 @@
};
secure.onData = useRead;
secure.onClosed = () {
- String fullPage = Strings.concatAll(chunks);
+ String fullPage = chunks.join();
Expect.isTrue(fullPage.contains('</body></html>'));
keepAlive.close();
};
diff --git a/tests/standalone/io/secure_stream_test.dart b/tests/standalone/io/secure_stream_test.dart
index 63c0fce..11acb7b 100644
--- a/tests/standalone/io/secure_stream_test.dart
+++ b/tests/standalone/io/secure_stream_test.dart
@@ -29,7 +29,7 @@
chunks.add(new String.fromCharCodes(input.read()));
};
input.onClosed = () {
- String fullPage = Strings.concatAll(chunks);
+ String fullPage = chunks.join();
Expect.isTrue(fullPage.contains('</body></html>'));
keepAlive.close();
};
diff --git a/tests/utils/test_utils.dart b/tests/utils/test_utils.dart
index 40a2e55..a786fa2 100644
--- a/tests/utils/test_utils.dart
+++ b/tests/utils/test_utils.dart
@@ -30,7 +30,7 @@
}
}
- return Strings.join(lines, '\n');
+ return lines.join('\n');
}
/**
@@ -49,5 +49,5 @@
lines[i] = " ${lines[i]}";
}
- return Strings.join(lines, "\n");
+ return lines.join("\n");
}
diff --git a/tools/VERSION b/tools/VERSION
index 54f29d1..f532fc3 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -1,4 +1,4 @@
MAJOR 0
MINOR 3
BUILD 7
-PATCH 5
+PATCH 6
diff --git a/tools/ddbg.dart b/tools/ddbg.dart
index de21364..7d95f79 100644
--- a/tools/ddbg.dart
+++ b/tools/ddbg.dart
@@ -556,7 +556,7 @@
arguments = <String>['--debug', '--verbose_debug']..addAll(arguments);
Process.start(options.executable, arguments).then((Process process) {
process.onExit = (int exitCode) {
- print('${Strings.join(arguments, " ")} exited with $exitCode');
+ print('${arguments.join(" ")} exited with $exitCode');
};
process.stdin.close();
// Redirecting both stdout and stderr of the child process to
diff --git a/tools/dom/scripts/idlrenderer.dart b/tools/dom/scripts/idlrenderer.dart
index 9bfcd4f..9b7bd32 100644
--- a/tools/dom/scripts/idlrenderer.dart
+++ b/tools/dom/scripts/idlrenderer.dart
@@ -111,7 +111,7 @@
else
formattedArgs.add('$argName=$argValue');
}
- w('@$name(${Strings.join(formattedArgs,',')})');
+ w('@$name(${formattedArgs.join(',')})');
}
w(' ');
}
@@ -176,5 +176,5 @@
};
w(idl_node);
- return Strings.concatAll(output);
+ return output.join();
}
diff --git a/tools/dom/src/CssClassSet.dart b/tools/dom/src/CssClassSet.dart
index 72fdc7e..51dd3b5 100644
--- a/tools/dom/src/CssClassSet.dart
+++ b/tools/dom/src/CssClassSet.dart
@@ -7,7 +7,7 @@
abstract class CssClassSet implements Set<String> {
String toString() {
- return Strings.join(new List.from(readClasses()), ' ');
+ return readClasses().join(' ');
}
/**
diff --git a/tools/dom/templates/html/impl/impl_SVGElement.darttemplate b/tools/dom/templates/html/impl/impl_SVGElement.darttemplate
index c3ee680..61cf7f6 100644
--- a/tools/dom/templates/html/impl/impl_SVGElement.darttemplate
+++ b/tools/dom/templates/html/impl/impl_SVGElement.darttemplate
@@ -26,8 +26,7 @@
}
void writeClasses(Set s) {
- List list = new List.from(s);
- _element.attributes['class'] = Strings.join(list, ' ');
+ _element.attributes['class'] = s.join(' ');
}
}
diff --git a/tools/test-runtime.dart b/tools/test-runtime.dart
index 036c861..867d39e 100755
--- a/tools/test-runtime.dart
+++ b/tools/test-runtime.dart
@@ -67,9 +67,9 @@
List settings = ['compiler', 'runtime', 'mode', 'arch']
.mappedBy((name) => conf[name]).toList();
if (conf['checked']) settings.add('checked');
- output_words.add(Strings.join(settings, '_'));
+ output_words.add(settings.join('_'));
}
- print(Strings.join(output_words, ' '));
+ print(output_words.join(' '));
}
var testSuites = new List<TestSuite>();
diff --git a/tools/test.dart b/tools/test.dart
index 12cff10..1f88fd7 100755
--- a/tools/test.dart
+++ b/tools/test.dart
@@ -104,9 +104,9 @@
List settings = ['compiler', 'runtime', 'mode', 'arch']
.mappedBy((name) => conf[name]).toList();
if (conf['checked']) settings.add('checked');
- output_words.add(Strings.join(settings, '_'));
+ output_words.add(settings.join('_'));
}
- print(Strings.join(output_words, ' '));
+ print(output_words.join(' '));
}
// Start global http servers that serve the entire dart repo.
diff --git a/tools/testing/dart/multitest.dart b/tools/testing/dart/multitest.dart
index 85a9d1b..585502c 100644
--- a/tools/testing/dart/multitest.dart
+++ b/tools/testing/dart/multitest.dart
@@ -122,8 +122,7 @@
// Copy all the tests into the output map tests, as multiline strings.
for (String key in testsAsLines.keys) {
- tests[key] =
- Strings.join(testsAsLines[key], line_separator).concat(line_separator);
+ tests[key] = testsAsLines[key].join(line_separator).concat(line_separator);
}
}
diff --git a/tools/testing/dart/test_runner.dart b/tools/testing/dart/test_runner.dart
index 356b664..9833dd4 100644
--- a/tools/testing/dart/test_runner.dart
+++ b/tools/testing/dart/test_runner.dart
@@ -107,7 +107,7 @@
// TODO(efortuna): Remove this when fixed (Issue 1306).
executable = executable.replaceAll('/', '\\');
}
- commandLine = "$executable ${Strings.join(arguments, ' ')}";
+ commandLine = "$executable ${arguments.join(' ')}";
}
String toString() => commandLine;
@@ -196,7 +196,7 @@
if (needDartFlags) {
env = new Map.from(io.Platform.environment);
if (needDartFlags) {
- env['DART_FLAGS'] = Strings.join(dartFlags, " ");
+ env['DART_FLAGS'] = dartFlags.join(" ");
}
}
@@ -305,7 +305,7 @@
newCommands.add(newCommand);
// If there are extra spaces inside the prefix or suffix, this fails.
String expected =
- '$prefix ${c.executable} $suffix ${Strings.join(c.arguments, ' ')}';
+ '$prefix ${c.executable} $suffix ${c.arguments.join(' ')}';
Expect.stringEquals(expected.trim(), newCommand.commandLine);
}
commands = newCommands;
@@ -1152,7 +1152,7 @@
}
String _createArgumentsLine(List<String> arguments) {
- return Strings.join(arguments, ' ').concat('\n');
+ return arguments.join(' ').concat('\n');
}
void _reportResult() {
@@ -1287,7 +1287,7 @@
callback();
}).catchError((e) {
print("Process error:");
- print(" Command: $_executable ${Strings.join(_batchArguments, ' ')}");
+ print(" Command: $_executable ${_batchArguments.join(' ')}");
print(" Error: $e");
// If there is an error starting a batch process, chances are that
// it will always fail. So rather than re-trying a 1000+ times, we
@@ -1464,7 +1464,7 @@
};
}).catchError((e) {
print("Error starting process:");
- print(" Command: $cmd ${Strings.join(arg, ' ')}");
+ print(" Command: $cmd ${arg.join(' ')}");
print(" Error: $e");
// TODO(ahe): How to report this as a test failure?
exit(1);
@@ -1580,10 +1580,10 @@
TestCase test = _tests.removeFirst();
if (_listTests) {
var fields = [test.displayName,
- Strings.join(new List.from(test.expectedOutcomes), ','),
+ test.expectedOutcomes.join(','),
test.isNegative.toString()];
fields.addAll(test.commands.last.arguments);
- print(Strings.join(fields, '\t'));
+ print(fields.join('\t'));
return;
}
if (test.usesWebDriver && _needsSelenium && !_isSeleniumAvailable || (test
diff --git a/tools/testing/dart/test_suite.dart b/tools/testing/dart/test_suite.dart
index 894fb5a..f8b59d8 100644
--- a/tools/testing/dart/test_suite.dart
+++ b/tools/testing/dart/test_suite.dart
@@ -850,9 +850,9 @@
// replaceAll(RegExp, String) is implemented.
String optionsName = '';
if (getVmOptions(optionsFromFile).length > 1) {
- optionsName = Strings.join(vmOptions, '-').replaceAll('-','')
- .replaceAll('=','')
- .replaceAll('/','');
+ optionsName = vmOptions.join('-').replaceAll('-','')
+ .replaceAll('=','')
+ .replaceAll('/','');
}
final String tempDir = createOutputDirectory(info.filePath, optionsName);
@@ -1633,7 +1633,7 @@
}
void computeClassPath() {
- classPath = Strings.join(
+ classPath =
['$buildDir/analyzer/util/analyzer/dart_analyzer.jar',
'$buildDir/analyzer/dart_analyzer_tests.jar',
// Third party libraries.
@@ -1644,8 +1644,8 @@
'$dartDir/third_party/hamcrest/v1_3/hamcrest-generator-1.3.0RC2.jar',
'$dartDir/third_party/hamcrest/v1_3/hamcrest-integration-1.3.0RC2.jar',
'$dartDir/third_party/hamcrest/v1_3/hamcrest-library-1.3.0RC2.jar',
- '$dartDir/third_party/junit/v4_8_2/junit.jar'],
- Platform.operatingSystem == 'windows'? ';': ':'); // Path separator.
+ '$dartDir/third_party/junit/v4_8_2/junit.jar']
+ .join(Platform.operatingSystem == 'windows'? ';': ':'); // Path separator.
}
}
diff --git a/utils/apidoc/html_diff.dart b/utils/apidoc/html_diff.dart
index d6a5067..3c8324d 100644
--- a/utils/apidoc/html_diff.dart
+++ b/utils/apidoc/html_diff.dart
@@ -197,7 +197,7 @@
for (var t in domTypes) {
options.add('$t.$name');
}
- Strings.join(options, ' or ');
+ options.join(' or ');
warn('no member $options');
}
}
diff --git a/utils/lib/file_system.dart b/utils/lib/file_system.dart
index 7b8da62..306be7a 100644
--- a/utils/lib/file_system.dart
+++ b/utils/lib/file_system.dart
@@ -47,7 +47,7 @@
pieces.add(piece);
}
}
- return Strings.join(pieces, '/');
+ return pieces.join('/');
}
/** Returns the directory name for the [path]. */
diff --git a/utils/peg/pegparser.dart b/utils/peg/pegparser.dart
index 1333682..9072e2d 100644
--- a/utils/peg/pegparser.dart
+++ b/utils/peg/pegparser.dart
@@ -275,7 +275,7 @@
a.startsWith("'") == b.startsWith("'")
? a.compareTo(b)
: a.startsWith("'") ? +1 : -1);
- var expected = Strings.join(tokens, ' or ');
+ var expected = tokens.join(' or ');
var found = state.max_pos == state._end ? 'end of file'
: "'${state._text[state.max_pos]}'";
message = 'Expected $expected but found $found';
diff --git a/utils/pub/entrypoint.dart b/utils/pub/entrypoint.dart
index 7de7c2c..b2dc9b4 100644
--- a/utils/pub/entrypoint.dart
+++ b/utils/pub/entrypoint.dart
@@ -209,7 +209,7 @@
LockFile loadLockFile() {
var lockFilePath = path.join(root.dir, 'pubspec.lock');
if (!fileExists(lockFilePath)) return new LockFile.empty();
- return new LockFile.parse(readTextFile(lockFilePath), cache.sources);
+ return new LockFile.load(lockFilePath, cache.sources);
}
/// Saves a list of concrete package versions to the `pubspec.lock` file.
@@ -294,9 +294,9 @@
/// Creates a symlink to the `packages` directory in [dir] if none exists.
Future _linkSecondaryPackageDir(String dir) {
return defer(() {
- var to = path.join(dir, 'packages');
- if (entryExists(to)) return;
- return createSymlink(packagesDir, to);
+ var symlink = path.join(dir, 'packages');
+ if (entryExists(symlink)) return;
+ return createSymlink(packagesDir, symlink);
});
}
}
diff --git a/utils/pub/git_source.dart b/utils/pub/git_source.dart
index fdb0ed4..2b54c72 100644
--- a/utils/pub/git_source.dart
+++ b/utils/pub/git_source.dart
@@ -10,6 +10,7 @@
import 'git.dart' as git;
import 'io.dart';
+import 'log.dart' as log;
import 'package.dart';
import 'source.dart';
import 'source_registry.dart';
@@ -67,24 +68,33 @@
return path.join(systemCacheRoot, revisionCacheName);
});
}
+
/// Ensures [description] is a Git URL.
- void validateDescription(description, {bool fromLockFile: false}) {
+ dynamic parseDescription(String containingPath, description,
+ {bool fromLockFile: false}) {
+ // TODO(rnystrom): Handle git URLs that are relative file paths (#8570).
+ // TODO(rnystrom): Now that this function can modify the description, it
+ // may as well canonicalize it to a map so that other code in the source
+ // can assume that.
// A single string is assumed to be a Git URL.
- if (description is String) return;
+ if (description is String) return description;
if (description is! Map || !description.containsKey('url')) {
throw new FormatException("The description must be a Git URL or a map "
"with a 'url' key.");
}
- description = new Map.from(description);
- description.remove('url');
- description.remove('ref');
- if (fromLockFile) description.remove('resolved-ref');
- if (!description.isEmpty) {
- var plural = description.length > 1;
- var keys = description.keys.join(', ');
+ var parsed = new Map.from(description);
+ parsed.remove('url');
+ parsed.remove('ref');
+ if (fromLockFile) parsed.remove('resolved-ref');
+
+ if (!parsed.isEmpty) {
+ var plural = parsed.length > 1;
+ var keys = parsed.keys.join(', ');
throw new FormatException("Invalid key${plural ? 's' : ''}: $keys.");
}
+
+ return description;
}
/// Two Git descriptions are equal if both their URLs and their refs are
diff --git a/utils/pub/hosted_source.dart b/utils/pub/hosted_source.dart
index dda00a4..6fdc8e9 100644
--- a/utils/pub/hosted_source.dart
+++ b/utils/pub/hosted_source.dart
@@ -56,7 +56,7 @@
"${id.version}.yaml";
return httpClient.read(fullUrl).then((yaml) {
- return new Pubspec.parse(yaml, systemCache.sources);
+ return new Pubspec.parse(null, yaml, systemCache.sources);
}).catchError((ex) {
_throwFriendlyError(ex, id, parsed.last);
});
@@ -114,8 +114,10 @@
/// There are two valid formats. A plain string refers to a package with the
/// given name from the default host, while a map with keys "name" and "url"
/// refers to a package with the given name from the host at the given URL.
- void validateDescription(description, {bool fromLockFile: false}) {
+ dynamic parseDescription(String containingPath, description,
+ {bool fromLockFile: false}) {
_parseDescription(description);
+ return description;
}
/// When an error occurs trying to read something about [package] from [url],
diff --git a/utils/pub/io.dart b/utils/pub/io.dart
index 82614ca..a031da2 100644
--- a/utils/pub/io.dart
+++ b/utils/pub/io.dart
@@ -264,15 +264,32 @@
return makeAttempt(null);
}
-/// Creates a new symlink that creates an alias from [from] to [to]. Returns a
-/// [Future] which completes to the symlink file (i.e. [to]).
+/// Creates a new symlink at path [symlink] that points to [target]. Returns a
+/// [Future] which completes to the path to the symlink file.
+///
+/// If [relative] is true, creates a symlink with a relative path from the
+/// symlink to the target. Otherwise, uses the [target] path unmodified.
///
/// Note that on Windows, only directories may be symlinked to.
-Future<String> createSymlink(String from, String to) {
- log.fine("Creating symlink ($to is a symlink to $from)");
+Future<String> createSymlink(String target, String symlink,
+ {bool relative: false}) {
+ if (relative) {
+ // Relative junction points are not supported on Windows. Instead, just
+ // make sure we have a clean absolute path because it will interpret a
+ // relative path to be relative to the cwd, not the symlink, and will be
+ // confused by forward slashes.
+ if (Platform.operatingSystem == 'windows') {
+ target = path.normalize(path.absolute(target));
+ } else {
+ target = path.normalize(
+ path.relative(target, from: path.dirname(symlink)));
+ }
+ }
+
+ log.fine("Creating $symlink pointing to $target");
var command = 'ln';
- var args = ['-s', from, to];
+ var args = ['-s', target, symlink];
if (Platform.operatingSystem == 'windows') {
// Call mklink on Windows to create an NTFS junction point. Only works on
@@ -281,24 +298,29 @@
// link (/d) because the latter requires some privilege shenanigans that
// I'm not sure how to specify from the command line.
command = 'mklink';
- args = ['/j', to, from];
+ args = ['/j', symlink, target];
}
// TODO(rnystrom): Check exit code and output?
- return runProcess(command, args).then((result) => to);
+ return runProcess(command, args).then((result) => symlink);
}
-/// Creates a new symlink that creates an alias from the `lib` directory of
-/// package [from] to [to]. Returns a [Future] which completes to the symlink
-/// file (i.e. [to]). If [from] does not have a `lib` directory, this shows a
-/// warning if appropriate and then does nothing.
-Future<String> createPackageSymlink(String name, String from, String to,
- {bool isSelfLink: false}) {
+/// Creates a new symlink that creates an alias at [symlink] that points to the
+/// `lib` directory of package [target]. Returns a [Future] which completes to
+/// the path to the symlink file. If [target] does not have a `lib` directory,
+/// this shows a warning if appropriate and then does nothing.
+///
+/// If [relative] is true, creates a symlink with a relative path from the
+/// symlink to the target. Otherwise, uses the [target] path unmodified.
+Future<String> createPackageSymlink(String name, String target, String symlink,
+ {bool isSelfLink: false, bool relative: false}) {
return defer(() {
// See if the package has a "lib" directory.
- from = path.join(from, 'lib');
+ target = path.join(target, 'lib');
log.fine("Creating ${isSelfLink ? "self" : ""}link for package '$name'.");
- if (dirExists(from)) return createSymlink(from, to);
+ if (dirExists(target)) {
+ return createSymlink(target, symlink, relative: relative);
+ }
// It's OK for the self link (i.e. the root package) to not have a lib
// directory since it may just be a leaf application that only has
@@ -308,7 +330,7 @@
'you will not be able to import any libraries from it.');
}
- return to;
+ return symlink;
});
}
diff --git a/utils/pub/lock_file.dart b/utils/pub/lock_file.dart
index 23e7099..594e523 100644
--- a/utils/pub/lock_file.dart
+++ b/utils/pub/lock_file.dart
@@ -5,6 +5,7 @@
library lock_file;
import 'dart:json' as json;
+import 'io.dart';
import 'package.dart';
import 'source_registry.dart';
import 'utils.dart';
@@ -21,8 +22,19 @@
LockFile.empty()
: packages = <String, PackageId>{};
- /// Parses the lockfile whose text is [contents].
+ /// Loads a lockfile from [filePath].
+ factory LockFile.load(String filePath, SourceRegistry sources) {
+ return LockFile._parse(filePath, readTextFile(filePath), sources);
+ }
+
+ /// Parses a lockfile whose text is [contents].
factory LockFile.parse(String contents, SourceRegistry sources) {
+ return LockFile._parse(null, contents, sources);
+ }
+
+ /// Parses the lockfile whose text is [contents].
+ static LockFile _parse(String filePath, String contents,
+ SourceRegistry sources) {
var packages = <String, PackageId>{};
if (contents.trim() == '') return new LockFile.empty();
@@ -54,7 +66,8 @@
throw new FormatException('Package $name is missing a description.');
}
var description = spec['description'];
- source.validateDescription(description, fromLockFile: true);
+ description = source.parseDescription(filePath, description,
+ fromLockFile: true);
var id = new PackageId(name, source, version, description);
diff --git a/utils/pub/path_source.dart b/utils/pub/path_source.dart
index 123a308..69471f8 100644
--- a/utils/pub/path_source.dart
+++ b/utils/pub/path_source.dart
@@ -25,45 +25,77 @@
Future<Pubspec> describe(PackageId id) {
return defer(() {
_validatePath(id.name, id.description);
- return new Pubspec.load(id.name, id.description, systemCache.sources);
+ return new Pubspec.load(id.name, id.description["path"],
+ systemCache.sources);
});
}
- Future<bool> install(PackageId id, String path) {
+ Future<bool> install(PackageId id, String destination) {
return defer(() {
try {
_validatePath(id.name, id.description);
} on FormatException catch(err) {
return false;
}
- return createPackageSymlink(id.name, id.description, path);
+
+ return createPackageSymlink(id.name, id.description["path"], destination,
+ relative: id.description["relative"]);
}).then((_) => true);
}
- void validateDescription(description, {bool fromLockFile: false}) {
+ /// Parses a path dependency. This takes in a path string and returns a map.
+ /// The "path" key will be the original path but resolves relative to the
+ /// containing path. The "relative" key will be `true` if the original path
+ /// was relative.
+ ///
+ /// A path coming from a pubspec is a simple string. From a lock file, it's
+ /// an expanded {"path": ..., "relative": ...} map.
+ dynamic parseDescription(String containingPath, description,
+ {bool fromLockFile: false}) {
+ if (fromLockFile) {
+ if (description is! Map) {
+ throw new FormatException("The description must be a map.");
+ }
+
+ if (description["path"] is! String) {
+ throw new FormatException("The 'path' field of the description must "
+ "be a string.");
+ }
+
+ if (description["relative"] is! bool) {
+ throw new FormatException("The 'relative' field of the description "
+ "must be a boolean.");
+ }
+
+ return description;
+ }
+
if (description is! String) {
throw new FormatException("The description must be a path string.");
}
+
+ // Resolve the path relative to the containing file path, and remember
+ // whether the original path was relative or absolute.
+ bool isRelative = path.isRelative(description);
+ if (path.isRelative(description)) {
+ // Can't handle relative paths coming from pubspecs that are not on the
+ // local file system.
+ assert(containingPath != null);
+
+ description = path.join(path.dirname(containingPath), description);
+ }
+
+ return {
+ "path": description,
+ "relative": isRelative
+ };
}
- /// Ensures that [dir] is a valid path. It must be an absolute path that
- /// points to an existing directory. Throws a [FormatException] if the path
- /// is invalid.
- void _validatePath(String name, String dir) {
- // Relative paths are not (currently) allowed because the user would expect
- // them to be relative to the pubspec where the dependency appears. That in
- // turn means that two pubspecs in different locations with the same
- // relative path dependency could refer to two different packages. That
- // violates pub's rule that a description should uniquely identify a
- // package.
- //
- // At some point, we may want to loosen this, but it will mean tracking
- // where a given PackageId appeared.
- if (!path.isAbsolute(dir)) {
- throw new FormatException(
- "Path dependency for package '$name' must be an absolute path. "
- "Was '$dir'.");
- }
+ /// Ensures that [description] is a valid path description. It must be a map,
+ /// with a "path" key containing a path that points to an existing directory.
+ /// Throws a [FormatException] if the path is invalid.
+ void _validatePath(String name, description) {
+ var dir = description["path"];
if (fileExists(dir)) {
throw new FormatException(
@@ -75,4 +107,4 @@
throw new FormatException("Could not find package '$name' at '$dir'.");
}
}
-}
\ No newline at end of file
+}
diff --git a/utils/pub/pubspec.dart b/utils/pub/pubspec.dart
index 779a294..55b775d 100644
--- a/utils/pub/pubspec.dart
+++ b/utils/pub/pubspec.dart
@@ -38,7 +38,8 @@
if (!fileExists(pubspecPath)) throw new PubspecNotFoundException(name);
try {
- var pubspec = new Pubspec.parse(readTextFile(pubspecPath), sources);
+ var pubspec = new Pubspec.parse(pubspecPath, readTextFile(pubspecPath),
+ sources);
if (pubspec.name == null) {
throw new PubspecHasNoNameException(name);
@@ -69,10 +70,14 @@
bool get isEmpty =>
name == null && version == Version.none && dependencies.isEmpty;
- // TODO(rnystrom): Make this a static method to match corelib.
- /// Parses the pubspec whose text is [contents]. If the pubspec doesn't define
- /// version for itself, it defaults to [Version.none].
- factory Pubspec.parse(String contents, SourceRegistry sources) {
+ // TODO(rnystrom): Instead of allowing a null argument here, split this up
+ // into load(), parse(), and _parse() like LockFile does.
+ /// Parses the pubspec stored at [filePath] whose text is [contents]. If the
+ /// pubspec doesn't define version for itself, it defaults to [Version.none].
+ /// [filePath] may be `null` if the pubspec is not on the user's local
+ /// file system.
+ factory Pubspec.parse(String filePath, String contents,
+ SourceRegistry sources) {
var name = null;
var version = Version.none;
@@ -97,7 +102,7 @@
version = new Version.parse(parsedPubspec['version']);
}
- var dependencies = _parseDependencies(sources,
+ var dependencies = _parseDependencies(filePath, sources,
parsedPubspec['dependencies']);
var environmentYaml = parsedPubspec['environment'];
@@ -187,7 +192,8 @@
}
}
-List<PackageRef> _parseDependencies(SourceRegistry sources, yaml) {
+List<PackageRef> _parseDependencies(String pubspecPath, SourceRegistry sources,
+ yaml) {
var dependencies = <PackageRef>[];
// Allow an empty dependencies key.
@@ -233,7 +239,8 @@
'Dependency specification $spec should be a string or a mapping.');
}
- source.validateDescription(description, fromLockFile: false);
+ description = source.parseDescription(pubspecPath, description,
+ fromLockFile: false);
dependencies.add(new PackageRef(
name, source, versionConstraint, description));
diff --git a/utils/pub/source.dart b/utils/pub/source.dart
index 1fd9327..0568d95 100644
--- a/utils/pub/source.dart
+++ b/utils/pub/source.dart
@@ -169,13 +169,23 @@
/// When a [Pubspec] or [LockFile] is parsed, it reads in the description for
/// each dependency. It is up to the dependency's [Source] to determine how
/// that should be interpreted. This will be called during parsing to validate
- /// that the given [description] is well-formed according to this source. It
- /// should return if the description is valid, or throw a [FormatException] if
- /// not.
+ /// that the given [description] is well-formed according to this source, and
+ /// to give the source a chance to canonicalize the description.
+ ///
+ /// [containingPath] is the path to the local file (pubspec or lockfile)
+ /// where this description appears. It may be `null` if the description is
+ /// coming from some in-memory source (such as pulling down a pubspec from
+ /// pub.dartlang.org).
+ ///
+ /// It should return if a (possibly modified) valid description, or throw a
+ /// [FormatException] if not valid.
///
/// [fromLockFile] is true when the description comes from a [LockFile], to
/// allow the source to use lockfile-specific descriptions via [resolveId].
- void validateDescription(description, {bool fromLockFile: false}) {}
+ dynamic parseDescription(String containingPath, description,
+ {bool fromLockFile: false}) {
+ return description;
+ }
/// Returns whether or not [description1] describes the same package as
/// [description2] for this source. This method should be light-weight. It
@@ -199,7 +209,7 @@
/// the resolved id.
///
/// The returned [PackageId] may have a description field that's invalid
- /// according to [validateDescription], although it must still be serializable
+ /// according to [parseDescription], although it must still be serializable
/// to JSON and YAML. It must also be equal to [id] according to
/// [descriptionsEqual].
///
diff --git a/utils/testrunner/pipeline_utils.dart b/utils/testrunner/pipeline_utils.dart
index 4362e3d..94391dc 100644
--- a/utils/testrunner/pipeline_utils.dart
+++ b/utils/testrunner/pipeline_utils.dart
@@ -61,7 +61,7 @@
Future _processHelper(String command, List<String> args,
[int timeout = 300, int procId = 0, Function outputMonitor]) {
var completer = procId == 0 ? new Completer() : null;
- log.add('Running $command ${Strings.join(args, " ")}');
+ log.add('Running $command ${args.join(" ")}');
var timer = null;
var stdoutHandler, stderrHandler;
var processFuture = Process.start(command, args);
diff --git a/utils/tests/pub/install/path/absolute_symlink_test.dart b/utils/tests/pub/install/path/absolute_symlink_test.dart
new file mode 100644
index 0000000..37aec85
--- /dev/null
+++ b/utils/tests/pub/install/path/absolute_symlink_test.dart
@@ -0,0 +1,45 @@
+// Copyright (c) 2013, 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 '../../../../../pkg/path/lib/path.dart' as path;
+
+import '../../../../pub/exit_codes.dart' as exit_codes;
+import '../../test_pub.dart';
+
+main() {
+ initConfig();
+ integration("generates a symlink with an absolute path if the dependency "
+ "path was absolute", () {
+ dir("foo", [
+ libDir("foo"),
+ libPubspec("foo", "0.0.1")
+ ]).scheduleCreate();
+
+ dir(appPath, [
+ pubspec({
+ "name": "myapp",
+ "dependencies": {
+ "foo": {"path": path.join(sandboxDir, "foo")}
+ }
+ })
+ ]).scheduleCreate();
+
+ schedulePub(args: ["install"],
+ output: new RegExp(r"Dependencies installed!$"));
+
+ dir("moved").scheduleCreate();
+
+ // Move the app but not the package. Since the symlink is absolute, it
+ // should still be able to find it.
+ scheduleRename(appPath, path.join("moved", appPath));
+
+ dir("moved", [
+ dir(packagesPath, [
+ dir("foo", [
+ file("foo.dart", 'main() => "foo";')
+ ])
+ ])
+ ]).scheduleValidate();
+ });
+}
\ No newline at end of file
diff --git a/utils/tests/pub/install/path/relative_path_test.dart b/utils/tests/pub/install/path/relative_path_test.dart
index 56fe28a..497283b 100644
--- a/utils/tests/pub/install/path/relative_path_test.dart
+++ b/utils/tests/pub/install/path/relative_path_test.dart
@@ -2,12 +2,19 @@
// 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 '../../../../../pkg/path/lib/path.dart' as path;
+
import '../../../../pub/exit_codes.dart' as exit_codes;
import '../../test_pub.dart';
main() {
initConfig();
- integration('path dependencies cannot use relative paths', () {
+ integration("can use relative path", () {
+ dir("foo", [
+ libDir("foo"),
+ libPubspec("foo", "0.0.1")
+ ]).scheduleCreate();
+
dir(appPath, [
pubspec({
"name": "myapp",
@@ -17,9 +24,49 @@
})
]).scheduleCreate();
- schedulePub(args: ['install'],
- error: new RegExp("Path dependency for package 'foo' must be an "
- "absolute path. Was '../foo'."),
- exitCode: exit_codes.DATA);
+ schedulePub(args: ["install"],
+ output: new RegExp(r"Dependencies installed!$"));
+
+ dir(packagesPath, [
+ dir("foo", [
+ file("foo.dart", 'main() => "foo";')
+ ])
+ ]).scheduleValidate();
});
-}
\ No newline at end of file
+
+ integration("path is relative to containing pubspec", () {
+ dir("relative", [
+ dir("foo", [
+ libDir("foo"),
+ libPubspec("foo", "0.0.1", deps: [
+ {"path": "../bar"}
+ ])
+ ]),
+ dir("bar", [
+ libDir("bar"),
+ libPubspec("bar", "0.0.1")
+ ])
+ ]).scheduleCreate();
+
+ dir(appPath, [
+ pubspec({
+ "name": "myapp",
+ "dependencies": {
+ "foo": {"path": "../relative/foo"}
+ }
+ })
+ ]).scheduleCreate();
+
+ schedulePub(args: ["install"],
+ output: new RegExp(r"Dependencies installed!$"));
+
+ dir(packagesPath, [
+ dir("foo", [
+ file("foo.dart", 'main() => "foo";')
+ ]),
+ dir("bar", [
+ file("bar.dart", 'main() => "bar";')
+ ])
+ ]).scheduleValidate();
+ });
+}
diff --git a/utils/tests/pub/install/path/relative_symlink_test.dart b/utils/tests/pub/install/path/relative_symlink_test.dart
new file mode 100644
index 0000000..9460d7d
--- /dev/null
+++ b/utils/tests/pub/install/path/relative_symlink_test.dart
@@ -0,0 +1,54 @@
+// Copyright (c) 2013, 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 'dart:io';
+
+import '../../../../../pkg/path/lib/path.dart' as path;
+
+import '../../../../pub/exit_codes.dart' as exit_codes;
+import '../../test_pub.dart';
+
+main() {
+ // Pub uses NTFS junction points to create links in the packages directory.
+ // These (unlike the symlinks that are supported in Vista and later) do not
+ // support relative paths. So this test, by design, will not pass on Windows.
+ // So just skip it.
+ if (Platform.operatingSystem == "windows") return;
+
+ initConfig();
+ integration("generates a symlink with a relative path if the dependency "
+ "path was relative", () {
+ dir("foo", [
+ libDir("foo"),
+ libPubspec("foo", "0.0.1")
+ ]).scheduleCreate();
+
+ dir(appPath, [
+ pubspec({
+ "name": "myapp",
+ "dependencies": {
+ "foo": {"path": "../foo"}
+ }
+ })
+ ]).scheduleCreate();
+
+ schedulePub(args: ["install"],
+ output: new RegExp(r"Dependencies installed!$"));
+
+ dir("moved").scheduleCreate();
+
+ // Move the app and package. Since they are still next to each other, it
+ // should still be found.
+ scheduleRename("foo", path.join("moved", "foo"));
+ scheduleRename(appPath, path.join("moved", appPath));
+
+ dir("moved", [
+ dir(packagesPath, [
+ dir("foo", [
+ file("foo.dart", 'main() => "foo";')
+ ])
+ ])
+ ]).scheduleValidate();
+ });
+}
diff --git a/utils/tests/pub/lock_file_test.dart b/utils/tests/pub/lock_file_test.dart
index eeef7bf..cd57bd1 100644
--- a/utils/tests/pub/lock_file_test.dart
+++ b/utils/tests/pub/lock_file_test.dart
@@ -17,8 +17,10 @@
final String name = 'mock';
final bool shouldCache = false;
- void validateDescription(String description, {bool fromLockFile: false}) {
+ dynamic parseDescription(String filePath, String description,
+ {bool fromLockFile: false}) {
if (!description.endsWith(' desc')) throw new FormatException();
+ return description;
}
String packageName(String description) {
diff --git a/utils/tests/pub/pubspec_test.dart b/utils/tests/pub/pubspec_test.dart
index f2d0b61..9813cf5 100644
--- a/utils/tests/pub/pubspec_test.dart
+++ b/utils/tests/pub/pubspec_test.dart
@@ -15,8 +15,10 @@
class MockSource extends Source {
final String name = "mock";
final bool shouldCache = false;
- void validateDescription(description, {bool fromLockFile: false}) {
+ dynamic parseDescription(String filePath, description,
+ {bool fromLockFile: false}) {
if (description != 'ok') throw new FormatException('Bad');
+ return description;
}
String packageName(description) => 'foo';
}
@@ -29,12 +31,12 @@
sources.register(new MockSource());
expectFormatError(String pubspec) {
- expect(() => new Pubspec.parse(pubspec, sources),
+ expect(() => new Pubspec.parse(null, pubspec, sources),
throwsFormatException);
}
test("allows a version constraint for dependencies", () {
- var pubspec = new Pubspec.parse('''
+ var pubspec = new Pubspec.parse(null, '''
dependencies:
foo:
mock: ok
@@ -49,7 +51,7 @@
});
test("allows an empty dependencies map", () {
- var pubspec = new Pubspec.parse('''
+ var pubspec = new Pubspec.parse(null, '''
dependencies:
''', sources);
@@ -74,8 +76,8 @@
});
test("throws if 'homepage' doesn't have an HTTP scheme", () {
- new Pubspec.parse('homepage: http://ok.com', sources);
- new Pubspec.parse('homepage: https://also-ok.com', sources);
+ new Pubspec.parse(null, 'homepage: http://ok.com', sources);
+ new Pubspec.parse(null, 'homepage: https://also-ok.com', sources);
expectFormatError('homepage: ftp://badscheme.com');
expectFormatError('homepage: javascript:alert("!!!")');
@@ -89,8 +91,8 @@
});
test("throws if 'documentation' doesn't have an HTTP scheme", () {
- new Pubspec.parse('documentation: http://ok.com', sources);
- new Pubspec.parse('documentation: https://also-ok.com', sources);
+ new Pubspec.parse(null, 'documentation: http://ok.com', sources);
+ new Pubspec.parse(null, 'documentation: https://also-ok.com', sources);
expectFormatError('documentation: ftp://badscheme.com');
expectFormatError('documentation: javascript:alert("!!!")');
@@ -99,8 +101,8 @@
});
test("throws if 'authors' is not a string or a list of strings", () {
- new Pubspec.parse('authors: ok fine', sources);
- new Pubspec.parse('authors: [also, ok, fine]', sources);
+ new Pubspec.parse(null, 'authors: ok fine', sources);
+ new Pubspec.parse(null, 'authors: [also, ok, fine]', sources);
expectFormatError('authors: 123');
expectFormatError('authors: {not: {a: string}}');
@@ -108,7 +110,7 @@
});
test("throws if 'author' is not a string", () {
- new Pubspec.parse('author: ok fine', sources);
+ new Pubspec.parse(null, 'author: ok fine', sources);
expectFormatError('author: 123');
expectFormatError('author: {not: {a: string}}');
@@ -120,7 +122,7 @@
});
test("allows comment-only files", () {
- var pubspec = new Pubspec.parse('''
+ var pubspec = new Pubspec.parse(null, '''
# No external dependencies yet
# Including for completeness
# ...and hoping the spec expands to include details about author, version, etc
@@ -132,12 +134,12 @@
group("environment", () {
test("defaults to any SDK constraint if environment is omitted", () {
- var pubspec = new Pubspec.parse('', sources);
+ var pubspec = new Pubspec.parse(null, '', sources);
expect(pubspec.environment.sdkVersion, equals(VersionConstraint.any));
});
test("allows an empty environment map", () {
- var pubspec = new Pubspec.parse('''
+ var pubspec = new Pubspec.parse(null, '''
environment:
''', sources);
expect(pubspec.environment.sdkVersion, equals(VersionConstraint.any));
@@ -150,7 +152,7 @@
});
test("allows a version constraint for the sdk", () {
- var pubspec = new Pubspec.parse('''
+ var pubspec = new Pubspec.parse(null, '''
environment:
sdk: ">=1.2.3 <2.3.4"
''', sources);