| // Copyright (c) 2023, 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:math' show min; |
| |
| import 'package:analyzer/src/generated/sdk.dart'; |
| |
| const int _backwardsSlash = 92; |
| const int _forwardSlash = 47; |
| |
| String? getImportUriIfMatchesRelativeSdkPath( |
| List<SdkLibrary> libraries, String relativePathFromFile, String separator) { |
| for (SdkLibrary library in libraries) { |
| if (_equalModuloPathSeparator(library.path, relativePathFromFile)) { |
| return library.shortName; |
| } |
| } |
| |
| for (SdkLibrary library in libraries) { |
| String? relativePathIfInside = getRelativePathIfInside( |
| library.path, relativePathFromFile, |
| ignoreOsSeparatorMismatch: true); |
| if (relativePathIfInside != null) { |
| String relPath = relativePathIfInside.replaceAll(separator, '/'); |
| return '${library.shortName}/$relPath'; |
| } |
| } |
| return null; |
| } |
| |
| String? getRelativePathIfInside(String libraryPath, String filePath, |
| {bool ignoreOsSeparatorMismatch = false}) { |
| int minLength = min(libraryPath.length, filePath.length); |
| |
| // Find how far the strings are the same (modulo path separators is asked). |
| int same = 0; |
| for (int i = 0; i < minLength; i++) { |
| if (libraryPath.codeUnitAt(i) == filePath.codeUnitAt(i)) { |
| same++; |
| } else if (ignoreOsSeparatorMismatch && |
| (libraryPath.codeUnitAt(i) == _forwardSlash || |
| libraryPath.codeUnitAt(i) == _backwardsSlash) && |
| (filePath.codeUnitAt(i) == _forwardSlash || |
| filePath.codeUnitAt(i) == _backwardsSlash)) { |
| same++; |
| } else { |
| break; |
| } |
| } |
| // They're the same up to and including index [same]. |
| // If there isn't a path separator left in the rest of the string [libPath], |
| // [filePath] is inside the same dir as [libPath] (possibly within |
| // subdirs). |
| for (int i = same; i < libraryPath.length; i++) { |
| int c = libraryPath.codeUnitAt(i); |
| if (c == _forwardSlash || c == _backwardsSlash) { |
| return null; |
| } |
| } |
| |
| // To get the relative path we need to go back to the previous path |
| // separator. |
| for (int i = same; i >= 0; i--) { |
| int c = libraryPath.codeUnitAt(i); |
| if (c == _forwardSlash || c == _backwardsSlash) { |
| return filePath.substring(i + 1); |
| } |
| } |
| |
| // Invalid non-absolute path. |
| return null; |
| } |
| |
| bool _equalModuloPathSeparator(String path, String relativePathFromFile) { |
| if (path.length != relativePathFromFile.length) { |
| return false; |
| } |
| for (int i = 0; i < path.length; i++) { |
| if (path.codeUnitAt(i) == relativePathFromFile.codeUnitAt(i)) { |
| continue; |
| } |
| if ((path.codeUnitAt(i) == _forwardSlash || |
| path.codeUnitAt(i) == _backwardsSlash) && |
| (relativePathFromFile.codeUnitAt(i) == _forwardSlash || |
| relativePathFromFile.codeUnitAt(i) == _backwardsSlash)) { |
| continue; |
| } |
| return false; |
| } |
| return true; |
| } |