Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
f9ae3e4
Initial support for globs in tsconfig.json
rbuckton Dec 3, 2015
30575db
Added caching, more tests
rbuckton Dec 7, 2015
5de2fcc
Merge branch 'master' into glob2
rbuckton Dec 7, 2015
def3ba1
Added stubs to ChakraHost interface for readDirectoryNames/readFileNames
rbuckton Dec 7, 2015
c3c3bca
Fixed typos in comments
rbuckton Dec 8, 2015
bf9af46
Changed name of 'reduce' method added to FileSet
rbuckton Dec 8, 2015
d857250
Heavily revised implementation that relies on an updated 'readDirecto…
rbuckton Dec 14, 2015
247657f
Merge branch 'master' into glob2
rbuckton Dec 15, 2015
94a5327
more tests
rbuckton Dec 16, 2015
6f85fe9
Minor update to shims.ts for forthcoming VS support for globs.
rbuckton Dec 16, 2015
d23df34
Detailed comments for regular expressions and renamed some files.
rbuckton Dec 16, 2015
c224917
Comment cleanup
rbuckton Jan 4, 2016
cde12ef
Merge branch 'master' into glob2
rbuckton Jan 4, 2016
c1205eb
Fixed new linter warnings
rbuckton Jan 5, 2016
084b94c
Merge branch 'master' into glob2
riknoll May 26, 2016
db85643
Fixing linter and test errors
riknoll May 26, 2016
c340c88
Bringing back excludes error and fixing faulty test
riknoll May 26, 2016
50f0033
Merge branch 'master' into glob2_merged
riknoll May 26, 2016
aa5c51c
Fixing lint errors
riknoll May 26, 2016
0415b95
Passing regular expressions to native hosts
riknoll May 31, 2016
08ca1c0
Merge branch 'master' into glob2_merged
riknoll Jun 17, 2016
86cde9e
Updating readDirectory for tsserverProjectSystem unit tests
riknoll Jun 17, 2016
95072aa
Responding to PR feedback
riknoll Jun 18, 2016
f817ffa
Merge branch 'master' into glob2_merged
riknoll Jun 18, 2016
f73ed59
Adding more matchFiles test cases
riknoll Jun 20, 2016
b49acd5
Merge branch 'master' into glob2_merged
riknoll Jun 20, 2016
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
Initial support for globs in tsconfig.json
  • Loading branch information
rbuckton committed Dec 3, 2015
commit f9ae3e4f2b529a2f59a0fd0f9dae1bb01c94f9a7
573 changes: 544 additions & 29 deletions src/compiler/commandLineParser.ts

Large diffs are not rendered by default.

70 changes: 70 additions & 0 deletions src/compiler/core.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ namespace ts {
contains,
remove,
forEachValue: forEachValueInMap,
reduce,
clear
};

Expand All @@ -34,6 +35,10 @@ namespace ts {
}
}

function reduce<U>(callback: (memo: U, value: T, key: Path) => U, initial: U) {
return reduceProperties(files, callback, initial);
}

// path should already be well-formed so it does not need to be normalized
function get(path: Path): T {
return files[toKey(path)];
Expand Down Expand Up @@ -490,6 +495,24 @@ namespace ts {
return a < b ? Comparison.LessThan : Comparison.GreaterThan;
}

export function compareStrings(a: string, b: string, ignoreCase?: boolean): Comparison {
if (a === b) return Comparison.EqualTo;
if (a === undefined) return Comparison.LessThan;
if (b === undefined) return Comparison.GreaterThan;
if (ignoreCase) {
if (String.prototype.localeCompare) {
const result = a.localeCompare(b, /*locales*/ undefined, { usage: "sort", sensitivity: "accent" });
return result < 0 ? Comparison.LessThan : result > 0 ? Comparison.GreaterThan : Comparison.EqualTo;
}

a = a.toUpperCase();
b = b.toUpperCase();
if (a === b) return Comparison.EqualTo;
}

return a < b ? Comparison.LessThan : Comparison.GreaterThan;
}

function getDiagnosticFileName(diagnostic: Diagnostic): string {
return diagnostic.file ? diagnostic.file.fileName : undefined;
}
Expand Down Expand Up @@ -756,6 +779,49 @@ namespace ts {
return path1 + directorySeparator + path2;
}

/**
* Removes a trailing directory separator from a path.
* @param path The path.
*/
export function removeTrailingDirectorySeparator(path: string) {
if (path.charAt(path.length - 1) === directorySeparator) {
return path.substr(0, path.length - 1);
}

return path;
}

/**
* Adds a trailing directory separator to a path, if it does not already have one.
* @param path The path.
*/
export function ensureTrailingDirectorySeparator(path: string) {
if (path.charAt(path.length - 1) !== directorySeparator) {
return path + directorySeparator;
}

return path;
}

export function comparePaths(a: string, b: string, currentDirectory: string, ignoreCase?: boolean) {
if (a === b) return Comparison.EqualTo;
if (a === undefined) return Comparison.LessThan;
if (b === undefined) return Comparison.GreaterThan;
a = removeTrailingDirectorySeparator(a);
b = removeTrailingDirectorySeparator(b);
const aComponents = getNormalizedPathComponents(a, currentDirectory);
const bComponents = getNormalizedPathComponents(b, currentDirectory);
const sharedLength = Math.min(aComponents.length, bComponents.length);
for (let i = 0; i < sharedLength; ++i) {
const result = compareStrings(aComponents[i], bComponents[i], ignoreCase);
if (result !== Comparison.EqualTo) {
return result;
}
}

return compareValues(aComponents.length, bComponents.length);
}

export function fileExtensionIs(path: string, extension: string): boolean {
const pathLen = path.length;
const extLen = extension.length;
Expand Down Expand Up @@ -794,6 +860,10 @@ namespace ts {
return path;
}

export function changeExtension<T extends string | Path>(path: T, newExtension: string): T {
return <T>(removeFileExtension(path) + newExtension);
}

const backslashOrDoubleQuote = /[\"\\]/g;
const escapedCharsRegExp = /[\u0000-\u001f\t\v\f\b\r\n\u2028\u2029\u0085]/g;
const escapedCharsMap: Map<string> = {
Expand Down
4 changes: 4 additions & 0 deletions src/compiler/diagnosticMessages.json
Original file line number Diff line number Diff line change
Expand Up @@ -2020,6 +2020,10 @@
"category": "Error",
"code": 5009
},
"File specification cannot contain multiple recursive directory wildcards ('**'): '{0}'.": {
"category": "Error",
"code": 5011
},
"Cannot read file '{0}': {1}": {
"category": "Error",
"code": 5012
Expand Down
46 changes: 43 additions & 3 deletions src/compiler/sys.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ namespace ts {
getExecutingFilePath(): string;
getCurrentDirectory(): string;
readDirectory(path: string, extension?: string, exclude?: string[]): string[];
readFileNames(path: string): string[];
readDirectoryNames(path: string): string[];
getMemoryUsage?(): number;
exit(exitCode?: number): void;
}
Expand Down Expand Up @@ -155,6 +157,16 @@ namespace ts {
}
}

function readFileNames(path: string): string[] {
const folder = fso.GetFolder(path || ".");
return getNames(folder.files);
}

function readDirectoryNames(path: string): string[] {
const folder = fso.GetFolder(path || ".");
return getNames(folder.directories);
}

return {
args,
newLine: "\r\n",
Expand Down Expand Up @@ -185,6 +197,8 @@ namespace ts {
return new ActiveXObject("WScript.Shell").CurrentDirectory;
},
readDirectory,
readFileNames,
readDirectoryNames,
exit(exitCode?: number): void {
try {
WScript.Quit(exitCode);
Expand Down Expand Up @@ -281,7 +295,7 @@ namespace ts {
// REVIEW: for now this implementation uses polling.
// The advantage of polling is that it works reliably
// on all os and with network mounted files.
// For 90 referenced files, the average time to detect
// For 90 referenced files, the average time to detect
// changes is 2*msInterval (by default 5 seconds).
// The overhead of this is .04 percent (1/2500) with
// average pause of < 1 millisecond (and max
Expand Down Expand Up @@ -381,6 +395,30 @@ namespace ts {
}
}

function readFileNames(path: string): string[] {
const entries = _fs.readdirSync(path || ".");
const files: string[] = [];
for (const entry of entries) {
const stat = _fs.statSync(combinePaths(path, entry));
if (stat.isFile()) {
files.push(entry);
}
}
return files.sort();
}

function readDirectoryNames(path: string): string[] {
const entries = _fs.readdirSync(path || ".");
const directories: string[] = [];
for (const entry of entries) {
const stat = _fs.statSync(combinePaths(path, entry));
if (stat.isDirectory()) {
directories.push(entry);
}
}
return directories.sort();
}

return {
args: process.argv.slice(2),
newLine: _os.EOL,
Expand All @@ -406,7 +444,7 @@ namespace ts {
};
},
watchDirectory: (path, callback, recursive) => {
// Node 4.0 `fs.watch` function supports the "recursive" option on both OSX and Windows
// Node 4.0 `fs.watch` function supports the "recursive" option on both OSX and Windows
// (ref: https://github.com/nodejs/node/pull/2649 and https://github.com/Microsoft/TypeScript/issues/4643)
return _fs.watch(
path,
Expand All @@ -426,7 +464,7 @@ namespace ts {
return _path.resolve(path);
},
fileExists(path: string): boolean {
return _fs.existsSync(path);
return _fs.existsSync(path) && _fs.statSync(path).isFile();
},
directoryExists(path: string) {
return _fs.existsSync(path) && _fs.statSync(path).isDirectory();
Expand All @@ -443,6 +481,8 @@ namespace ts {
return process.cwd();
},
readDirectory,
readFileNames,
readDirectoryNames,
getMemoryUsage() {
if (global.gc) {
global.gc();
Expand Down
21 changes: 21 additions & 0 deletions src/compiler/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ namespace ts {
remove(fileName: Path): void;

forEachValue(f: (key: Path, v: T) => void): void;
reduce<U>(f: (memo: U, value: T, key: Path) => U, initial: U): U;
clear(): void;
}

Expand Down Expand Up @@ -1582,7 +1583,27 @@ namespace ts {
}

export interface ParseConfigHost {
useCaseSensitiveFileNames: boolean;

readDirectory(rootDir: string, extension: string, exclude: string[]): string[];

/**
* Gets a value indicating whether the specified path exists.
* @param path The path to test.
*/
fileExists(path: string): boolean;

/**
* Reads the files names in the directory.
* @param rootDir The directory path.
*/
readFileNames(rootDir: string): string[];

/**
* Reads the directory names in the directory.
* @param rootDir The directory path.
*/
readDirectoryNames(rootDir: string): string[];
}

export interface WriteFileCallback {
Expand Down
3 changes: 3 additions & 0 deletions src/harness/external/chai.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,9 @@ declare module chai {
module assert {
function equal(actual: any, expected: any, message?: string): void;
function notEqual(actual: any, expected: any, message?: string): void;
function deepEqual(actual: any, expected: any, message?: string): void;
function notDeepEqual(actual: any, expected: any, message?: string): void;
function lengthOf(object: any[], length: number, message?: string): void;
function isTrue(value: any, message?: string): void;
function isFalse(value: any, message?: string): void;
function isNull(value: any, message?: string): void;
Expand Down
28 changes: 21 additions & 7 deletions src/harness/harness.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@

//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
Expand Down Expand Up @@ -282,7 +282,7 @@ namespace Utils {
break;

case "parserContextFlags":
// Clear the flag that are produced by aggregating child values.. That is ephemeral
// Clear the flag that are produced by aggregating child values.. That is ephemeral
// data we don't care about in the dump. We only care what the parser set directly
// on the ast.
let value = n.parserContextFlags & ts.ParserContextFlags.ParserGeneratedFlags;
Expand Down Expand Up @@ -356,7 +356,7 @@ namespace Utils {
assert.equal(node1.kind, node2.kind, "node1.kind !== node2.kind");
assert.equal(node1.flags, node2.flags, "node1.flags !== node2.flags");

// call this on both nodes to ensure all propagated flags have been set (and thus can be
// call this on both nodes to ensure all propagated flags have been set (and thus can be
// compared).
assert.equal(ts.containsParseError(node1), ts.containsParseError(node2));
assert.equal(node1.parserContextFlags, node2.parserContextFlags, "node1.parserContextFlags !== node2.parserContextFlags");
Expand Down Expand Up @@ -436,6 +436,8 @@ namespace Harness {
getExecutingFilePath(): string;
exit(exitCode?: number): void;
readDirectory(path: string, extension?: string, exclude?: string[]): string[];
readDirectoryNames(path: string): string[];
readFileNames(path: string): string[];
}
export var IO: IO;

Expand Down Expand Up @@ -474,6 +476,8 @@ namespace Harness {
export const fileExists: typeof IO.fileExists = fso.FileExists;
export const log: typeof IO.log = global.WScript && global.WScript.StdOut.WriteLine;
export const readDirectory: typeof IO.readDirectory = (path, extension, exclude) => ts.sys.readDirectory(path, extension, exclude);
export const readDirectoryNames: typeof IO.readDirectoryNames = path => ts.sys.readDirectoryNames(path);
export const readFileNames: typeof IO.readFileNames = path => ts.sys.readFileNames(path);

export function createDirectory(path: string) {
if (directoryExists(path)) {
Expand Down Expand Up @@ -544,6 +548,8 @@ namespace Harness {
export const log: typeof IO.log = s => console.log(s);

export const readDirectory: typeof IO.readDirectory = (path, extension, exclude) => ts.sys.readDirectory(path, extension, exclude);
export const readDirectoryNames: typeof IO.readDirectoryNames = path => ts.sys.readDirectoryNames(path);
export const readFileNames: typeof IO.readFileNames = path => ts.sys.readFileNames(path);

export function createDirectory(path: string) {
if (!directoryExists(path)) {
Expand Down Expand Up @@ -752,6 +758,14 @@ namespace Harness {
export function readDirectory(path: string, extension?: string, exclude?: string[]) {
return listFiles(path).filter(f => !extension || ts.fileExtensionIs(f, extension));
}

export function readDirectoryNames(path: string): string[] {
return [];
}

export function readFileNames(path: string) {
return readDirectory(path);
}
}
}

Expand All @@ -777,7 +791,7 @@ namespace Harness {
(emittedFile: string, emittedLine: number, emittedColumn: number, sourceFile: string, sourceLine: number, sourceColumn: number, sourceName: string): void;
}

// Settings
// Settings
export let userSpecifiedRoot = "";
export let lightMode = false;

Expand Down Expand Up @@ -816,7 +830,7 @@ namespace Harness {
fileName: string,
sourceText: string,
languageVersion: ts.ScriptTarget) {
// We'll only assert invariants outside of light mode.
// We'll only assert invariants outside of light mode.
const shouldAssertInvariants = !Harness.lightMode;

// Only set the parent nodes if we're asserting invariants. We don't need them otherwise.
Expand Down Expand Up @@ -911,7 +925,7 @@ namespace Harness {
libFiles?: string;
}

// Additional options not already in ts.optionDeclarations
// Additional options not already in ts.optionDeclarations
const harnessOptionDeclarations: ts.CommandLineOption[] = [
{ name: "allowNonTsExtensions", type: "boolean" },
{ name: "useCaseSensitiveFileNames", type: "boolean" },
Expand Down Expand Up @@ -1149,7 +1163,7 @@ namespace Harness {
errLines.forEach(e => outputLines.push(e));

// do not count errors from lib.d.ts here, they are computed separately as numLibraryDiagnostics
// if lib.d.ts is explicitly included in input files and there are some errors in it (i.e. because of duplicate identifiers)
// if lib.d.ts is explicitly included in input files and there are some errors in it (i.e. because of duplicate identifiers)
// then they will be added twice thus triggering 'total errors' assertion with condition
// 'totalErrorsReportedInNonLibraryFiles + numLibraryDiagnostics + numTest262HarnessDiagnostics, diagnostics.length

Expand Down
Loading