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 |