OLD | NEW |
| (Empty) |
1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file | |
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. | |
4 | |
5 /// Utility methods used by more than one library in the package. | |
6 library package_config.util; | |
7 | |
8 import "package:charcode/ascii.dart"; | |
9 | |
10 // All ASCII characters that are valid in a package name, with space | |
11 // for all the invalid ones (including space). | |
12 const String _validPackageNameCharacters = | |
13 r" ! $ &'()*+,-. 0123456789 ; = " | |
14 r"@ABCDEFGHIJKLMNOPQRSTUVWXYZ _ abcdefghijklmnopqrstuvwxyz ~ "; | |
15 | |
16 /// Tests whether something is a valid Dart package name. | |
17 bool isValidPackageName(String string) { | |
18 return _findInvalidCharacter(string) < 0; | |
19 } | |
20 | |
21 /// Check if a string is a valid package name. | |
22 /// | |
23 /// Valid package names contain only characters in [_validPackageNameCharacters] | |
24 /// and must contain at least one non-'.' character. | |
25 /// | |
26 /// Returns `-1` if the string is valid. | |
27 /// Otherwise returns the index of the first invalid character, | |
28 /// or `string.length` if the string contains no non-'.' character. | |
29 int _findInvalidCharacter(String string) { | |
30 // Becomes non-zero if any non-'.' character is encountered. | |
31 int nonDot = 0; | |
32 for (int i = 0; i < string.length; i++) { | |
33 var c = string.codeUnitAt(i); | |
34 if (c > 0x7f || _validPackageNameCharacters.codeUnitAt(c) <= $space) { | |
35 return i; | |
36 } | |
37 nonDot += c ^ $dot; | |
38 } | |
39 if (nonDot == 0) return string.length; | |
40 return -1; | |
41 } | |
42 | |
43 /// Validate that a Uri is a valid package:URI. | |
44 String checkValidPackageUri(Uri packageUri) { | |
45 if (packageUri.scheme != "package") { | |
46 throw new ArgumentError.value(packageUri, "packageUri", | |
47 "Not a package: URI"); | |
48 } | |
49 if (packageUri.hasAuthority) { | |
50 throw new ArgumentError.value(packageUri, "packageUri", | |
51 "Package URIs must not have a host part"); | |
52 } | |
53 if (packageUri.hasQuery) { | |
54 // A query makes no sense if resolved to a file: URI. | |
55 throw new ArgumentError.value(packageUri, "packageUri", | |
56 "Package URIs must not have a query part"); | |
57 } | |
58 if (packageUri.hasFragment) { | |
59 // We could leave the fragment after the URL when resolving, | |
60 // but it would be odd if "package:foo/foo.dart#1" and | |
61 // "package:foo/foo.dart#2" were considered different libraries. | |
62 // Keep the syntax open in case we ever get multiple libraries in one file. | |
63 throw new ArgumentError.value(packageUri, "packageUri", | |
64 "Package URIs must not have a fragment part"); | |
65 } | |
66 if (packageUri.path.startsWith('/')) { | |
67 throw new ArgumentError.value(packageUri, "packageUri", | |
68 "Package URIs must not start with a '/'"); | |
69 } | |
70 int firstSlash = packageUri.path.indexOf('/'); | |
71 if (firstSlash == -1) { | |
72 throw new ArgumentError.value(packageUri, "packageUri", | |
73 "Package URIs must start with the package name followed by a '/'"); | |
74 } | |
75 String packageName = packageUri.path.substring(0, firstSlash); | |
76 int badIndex = _findInvalidCharacter(packageName); | |
77 if (badIndex >= 0) { | |
78 if (packageName.isEmpty) { | |
79 throw new ArgumentError.value(packageUri, "packageUri", | |
80 "Package names mus be non-empty"); | |
81 } | |
82 if (badIndex == packageName.length) { | |
83 throw new ArgumentError.value(packageUri, "packageUri", | |
84 "Package names must contain at least one non-'.' character"); | |
85 } | |
86 assert(badIndex < packageName.length); | |
87 int badCharCode = packageName.codeUnitAt(badIndex); | |
88 var badChar = "U+" + badCharCode.toRadixString(16).padLeft(4, '0'); | |
89 if (badCharCode >= 0x20 && badCharCode <= 0x7e) { | |
90 // Printable character. | |
91 badChar = "'${packageName[badIndex]}' ($badChar)"; | |
92 } | |
93 throw new ArgumentError.value(packageUri, "packageUri", | |
94 "Package names must not contain $badChar"); | |
95 } | |
96 return packageName; | |
97 } | |
OLD | NEW |