diff --git a/packages/compiler-cli/src/ngtsc/path/src/logical.ts b/packages/compiler-cli/src/ngtsc/path/src/logical.ts index 217cbb9ab5..40b2502c13 100644 --- a/packages/compiler-cli/src/ngtsc/path/src/logical.ts +++ b/packages/compiler-cli/src/ngtsc/path/src/logical.ts @@ -17,6 +17,8 @@ import {stripExtension} from './util'; /** * A path that's relative to the logical root of a TypeScript project (one of the project's * rootDirs). + * + * Paths in the type system use POSIX format. */ export type LogicalProjectPath = BrandedPath<'LogicalProjectPath'>; diff --git a/packages/compiler-cli/src/ngtsc/path/src/types.ts b/packages/compiler-cli/src/ngtsc/path/src/types.ts index 6c81d54034..3d9fcc8bb4 100644 --- a/packages/compiler-cli/src/ngtsc/path/src/types.ts +++ b/packages/compiler-cli/src/ngtsc/path/src/types.ts @@ -8,7 +8,7 @@ import * as ts from 'typescript'; -import {normalizeSeparators} from './util'; +import {isAbsolutePath, normalizeSeparators} from './util'; /** * A `string` representing a specific type of path, with a particular brand `B`. @@ -41,7 +41,7 @@ export const AbsoluteFsPath = { */ from: function(str: string): AbsoluteFsPath { const normalized = normalizeSeparators(str); - if (!normalized.startsWith('/')) { + if (!isAbsolutePath(normalized)) { throw new Error(`Internal Error: AbsoluteFsPath.from(${str}): path is not absolute`); } return normalized as AbsoluteFsPath; @@ -73,7 +73,7 @@ export const PathSegment = { */ fromFsPath: function(str: string): PathSegment { const normalized = normalizeSeparators(str); - if (normalized.startsWith('/')) { + if (isAbsolutePath(normalized)) { throw new Error(`Internal Error: PathSegment.from(${str}): path is not relative`); } return normalized as PathSegment; diff --git a/packages/compiler-cli/src/ngtsc/path/src/util.ts b/packages/compiler-cli/src/ngtsc/path/src/util.ts index 7ff6c21041..a416450fb0 100644 --- a/packages/compiler-cli/src/ngtsc/path/src/util.ts +++ b/packages/compiler-cli/src/ngtsc/path/src/util.ts @@ -9,9 +9,10 @@ // TODO(alxhub): Unify this file with `util/src/path`. const TS_DTS_JS_EXTENSION = /(?:\.d)?\.ts$|\.js$/; +const ABSOLUTE_PATH = /^([a-zA-Z]\:\/|\/)/; /** - * Convert Windows-style paths to POSIX paths. + * Convert Windows-style separators to POSIX separators. */ export function normalizeSeparators(path: string): string { // TODO: normalize path only for OS that need it. @@ -24,3 +25,11 @@ export function normalizeSeparators(path: string): string { export function stripExtension(path: string): string { return path.replace(TS_DTS_JS_EXTENSION, ''); } + +/** + * Returns true if the normalized path is an absolute path. + */ +export function isAbsolutePath(path: string): boolean { + // TODO: use regExp based on OS in the future + return ABSOLUTE_PATH.test(path); +} diff --git a/packages/compiler-cli/src/ngtsc/path/test/types_spec.ts b/packages/compiler-cli/src/ngtsc/path/test/types_spec.ts index 76793b67c3..41f7582987 100644 --- a/packages/compiler-cli/src/ngtsc/path/test/types_spec.ts +++ b/packages/compiler-cli/src/ngtsc/path/test/types_spec.ts @@ -10,10 +10,16 @@ import {AbsoluteFsPath} from '../src/types'; describe('path types', () => { describe('AbsoluteFsPath', () => { - it('should not throw when creating one from a non-absolute path', + it('should not throw when creating one from an absolute path', () => { expect(AbsoluteFsPath.from('/test.txt')).toEqual('/test.txt'); }); + it('should not throw when creating one from a windows absolute path', + () => { expect(AbsoluteFsPath.from('C:\\test.txt')).toEqual('C:/test.txt'); }); + it('should not throw when creating one from a windows absolute path with POSIX separators', + () => { expect(AbsoluteFsPath.from('C:/test.txt')).toEqual('C:/test.txt'); }); it('should throw when creating one from a non-absolute path', () => { expect(() => AbsoluteFsPath.from('test.txt')).toThrow(); }); + it('should support windows drive letters', + () => { expect(AbsoluteFsPath.from('D:\\foo\\test.txt')).toEqual('D:/foo/test.txt'); }); it('should convert Windows path separators to POSIX separators', () => { expect(AbsoluteFsPath.from('\\foo\\test.txt')).toEqual('/foo/test.txt'); }); });