| OLD | NEW |
| 1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file | 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 | 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 analyzer.src.util.absolute_path; | 5 library analyzer.src.util.absolute_path; |
| 6 | 6 |
| 7 /// The class for manipulating absolute, normalized paths. | 7 /// The class for manipulating absolute, normalized paths. |
| 8 class AbsolutePathContext { | 8 class AbsolutePathContext { |
| 9 static const int _COLON = 0x3A; | 9 static const int _COLON = 0x3A; |
| 10 static const int _PERIOD = 0x2e; | |
| 11 static const int _LOWER_A = 0x61; | 10 static const int _LOWER_A = 0x61; |
| 12 static const int _LOWER_Z = 0x7A; | 11 static const int _LOWER_Z = 0x7A; |
| 13 static const int _UPPER_A = 0x41; | 12 static const int _UPPER_A = 0x41; |
| 14 static const int _UPPER_Z = 0x5A; | 13 static const int _UPPER_Z = 0x5A; |
| 15 | 14 |
| 16 final bool _isWindows; | 15 final bool _isWindows; |
| 17 String separator; | 16 String separator; |
| 18 int _separatorChar; | 17 int _separatorChar; |
| 18 String _singlePeriodComponent; |
| 19 String _doublePeriodComponent; |
| 20 String _singlePeriodEnding; |
| 21 String _doublePeriodEnding; |
| 19 | 22 |
| 20 AbsolutePathContext(this._isWindows) { | 23 AbsolutePathContext(this._isWindows) { |
| 21 separator = _isWindows ? r'\' : '/'; | 24 separator = _isWindows ? r'\' : '/'; |
| 22 _separatorChar = separator.codeUnitAt(0); | 25 _separatorChar = separator.codeUnitAt(0); |
| 26 _singlePeriodComponent = separator + '.' + separator; |
| 27 _doublePeriodComponent = separator + '..' + separator; |
| 28 _singlePeriodEnding = separator + '.'; |
| 29 _doublePeriodEnding = separator + '..'; |
| 23 } | 30 } |
| 24 | 31 |
| 25 /// Append the given relative [suffix] to the given absolute [parent]. | 32 /// Append the given relative [suffix] to the given absolute [parent]. |
| 26 /// | 33 /// |
| 27 /// context.append('/path/to', 'foo'); // -> '/path/to/foo' | 34 /// context.append('/path/to', 'foo'); // -> '/path/to/foo' |
| 28 /// | 35 /// |
| 29 /// The given [suffix] cannot be an absolute path or use `..`. | 36 /// The given [suffix] cannot be an absolute path or use `..`. |
| 30 String append(String parent, String suffix) { | 37 String append(String parent, String suffix) { |
| 31 return '$parent$separator$suffix'; | 38 return '$parent$separator$suffix'; |
| 32 } | 39 } |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 118 if (_isWindows) { | 125 if (_isWindows) { |
| 119 return path.length >= 3 && | 126 return path.length >= 3 && |
| 120 _isAlphabetic(path.codeUnitAt(0)) && | 127 _isAlphabetic(path.codeUnitAt(0)) && |
| 121 path.codeUnitAt(1) == _COLON && | 128 path.codeUnitAt(1) == _COLON && |
| 122 path.codeUnitAt(2) == _separatorChar; | 129 path.codeUnitAt(2) == _separatorChar; |
| 123 } else { | 130 } else { |
| 124 return path.isNotEmpty && path.codeUnitAt(0) == _separatorChar; | 131 return path.isNotEmpty && path.codeUnitAt(0) == _separatorChar; |
| 125 } | 132 } |
| 126 } | 133 } |
| 127 | 134 |
| 128 | |
| 129 /// Return `true` if the given absolute [path] is normalized. | 135 /// Return `true` if the given absolute [path] is normalized. |
| 130 /// | 136 /// |
| 131 /// _isNormalized('/foo/bar'); // -> true | 137 /// _isNormalized('/foo/bar'); // -> true |
| 132 /// _isNormalized('/foo/..bar'); // -> true | 138 /// _isNormalized('/foo/..bar'); // -> true |
| 139 /// _isNormalized('/foo/bar..'); // -> true |
| 133 /// _isNormalized('/'); // -> true | 140 /// _isNormalized('/'); // -> true |
| 134 /// _isNormalized('/foo/bar/../baz'); // -> false | 141 /// _isNormalized('/foo/bar/../baz'); // -> false |
| 135 /// _isNormalized('/foo/bar/..'); // -> false | 142 /// _isNormalized('/foo/bar/..'); // -> false |
| 136 bool _isNormalized(String path) { | 143 bool _isNormalized(String path) { |
| 137 int periodCount = 0; | 144 return !path.contains(_singlePeriodComponent) && |
| 138 for (int c in path.codeUnits) { | 145 !path.contains(_doublePeriodComponent) && |
| 139 if (c == _PERIOD) { | 146 !path.endsWith(_singlePeriodEnding) && |
| 140 periodCount++; | 147 !path.endsWith(_doublePeriodEnding); |
| 141 continue; | |
| 142 } | |
| 143 if (c == _separatorChar) { | |
| 144 if (periodCount == 1 || periodCount == 2) { | |
| 145 return false; | |
| 146 } | |
| 147 } | |
| 148 periodCount = 0; | |
| 149 } | |
| 150 return periodCount != 1 && periodCount != 2; | |
| 151 } | 148 } |
| 152 | 149 |
| 153 /// Returns whether [char] is the code for an ASCII letter (uppercase or | 150 /// Returns whether [char] is the code for an ASCII letter (uppercase or |
| 154 /// lowercase). | 151 /// lowercase). |
| 155 static bool _isAlphabetic(int char) { | 152 static bool _isAlphabetic(int char) { |
| 156 return char >= _UPPER_A && char <= _UPPER_Z || | 153 return char >= _UPPER_A && char <= _UPPER_Z || |
| 157 char >= _LOWER_A && char <= _LOWER_Z; | 154 char >= _LOWER_A && char <= _LOWER_Z; |
| 158 } | 155 } |
| 159 | 156 |
| 160 /// Return `true` if [str] starts with the given [prefix]. | 157 /// Return `true` if [str] starts with the given [prefix]. |
| 161 /// | 158 /// |
| 162 /// The check is done from the end of [prefix], because absolute paths | 159 /// The check is done from the end of [prefix], because absolute paths |
| 163 /// usually have the same prefix, e.g. the user's home directory. | 160 /// usually have the same prefix, e.g. the user's home directory. |
| 164 static bool _startsWithUnsafe(String str, String prefix) { | 161 static bool _startsWithUnsafe(String str, String prefix) { |
| 165 int len = prefix.length; | 162 int len = prefix.length; |
| 166 for (int i = len - 1; i >= 0; i--) { | 163 for (int i = len - 1; i >= 0; i--) { |
| 167 if (str.codeUnitAt(i) != prefix.codeUnitAt(i)) { | 164 if (str.codeUnitAt(i) != prefix.codeUnitAt(i)) { |
| 168 return false; | 165 return false; |
| 169 } | 166 } |
| 170 } | 167 } |
| 171 return true; | 168 return true; |
| 172 } | 169 } |
| 173 } | 170 } |
| OLD | NEW |