Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adds glob-style pattern matching for file specifications using new "include" property in tsconfig.json #3232

Closed
wants to merge 11 commits into from
7 changes: 5 additions & 2 deletions Jakefile.js
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,8 @@ var harnessSources = [
"services/preProcessFile.ts",
"services/patternMatcher.ts",
"versionCache.ts",
"convertToBase64.ts"
"convertToBase64.ts",
"expandFiles.ts"
].map(function (f) {
return path.join(unittestsDirectory, f);
})).concat([
Expand Down Expand Up @@ -505,7 +506,9 @@ function cleanTestDirs() {
// used to pass data from jake command line directly to run.js
function writeTestConfigFile(tests, testConfigFile) {
console.log('Running test(s): ' + tests);
var testConfigContents = '{\n' + '\ttest: [\'' + tests + '\']\n}';
var testConfigContents = JSON.stringify({
"test": [tests]
});
fs.writeFileSync('test.config', testConfigContents);
}

Expand Down
462 changes: 447 additions & 15 deletions src/compiler/commandLineParser.ts

Large diffs are not rendered by default.

58 changes: 58 additions & 0 deletions src/compiler/core.ts
Original file line number Diff line number Diff line change
Expand Up @@ -380,6 +380,19 @@ module ts {
if (b === undefined) return Comparison.GreaterThan;
return a < b ? Comparison.LessThan : Comparison.GreaterThan;
}

export function compareStrings(a: string, b: string, ignoreCase?: boolean) {
if (a === b) return Comparison.EqualTo;
if (a === undefined) return Comparison.LessThan;
if (b === undefined) return Comparison.GreaterThan;
if (ignoreCase) {
a = a.toLowerCase();
b = b.toLowerCase();
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 @@ -643,7 +656,48 @@ module ts {
if (path1.charAt(path1.length - 1) === directorySeparator) return path1 + path2;
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);
let aComponents = getNormalizedPathComponents(a, currentDirectory);
let bComponents = getNormalizedPathComponents(b, currentDirectory);
let sharedLength = Math.min(aComponents.length, bComponents.length);
for (let i = 0; i < sharedLength; ++i) {
let result = compareStrings(aComponents[i], bComponents[i], ignoreCase);
if (result) return result;
}

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

export function fileExtensionIs(path: string, extension: string): boolean {
let pathLen = path.length;
let extLen = extension.length;
Expand All @@ -654,6 +708,10 @@ module ts {
* List of supported extensions in order of file resolution precedence.
*/
export const supportedExtensions = [".ts", ".d.ts"];

export function hasSupportedFileExtension(file: string) {
return forEach(supportedExtensions, extension => fileExtensionIs(file, extension));
}

const extensionsToRemove = [".d.ts", ".ts", ".js"];
export function removeFileExtension(path: string): string {
Expand Down
1 change: 1 addition & 0 deletions src/compiler/diagnosticInformationMap.generated.ts
Original file line number Diff line number Diff line change
Expand Up @@ -438,6 +438,7 @@ module ts {
Loop_contains_block_scoped_variable_0_referenced_by_a_function_in_the_loop_This_is_only_supported_in_ECMAScript_6_or_higher: { code: 4091, category: DiagnosticCategory.Error, key: "Loop contains block-scoped variable '{0}' referenced by a function in the loop. This is only supported in ECMAScript 6 or higher." },
The_current_host_does_not_support_the_0_option: { code: 5001, category: DiagnosticCategory.Error, key: "The current host does not support the '{0}' option." },
Cannot_find_the_common_subdirectory_path_for_the_input_files: { code: 5009, category: DiagnosticCategory.Error, key: "Cannot find the common subdirectory path for the input files." },
File_specification_cannot_contain_multiple_recursive_directory_wildcards_Asterisk_Asterisk_Colon_0: { code: 5011, category: DiagnosticCategory.Error, key: "File specification cannot contain multiple recursive directory wildcards ('**'): '{0}'." },
Cannot_read_file_0_Colon_1: { code: 5012, category: DiagnosticCategory.Error, key: "Cannot read file '{0}': {1}" },
Unsupported_file_encoding: { code: 5013, category: DiagnosticCategory.Error, key: "Unsupported file encoding." },
Failed_to_parse_file_0_Colon_1: { code: 5014, category: DiagnosticCategory.Error, key: "Failed to parse file '{0}': {1}." },
Expand Down
4 changes: 4 additions & 0 deletions src/compiler/diagnosticMessages.json
Original file line number Diff line number Diff line change
Expand Up @@ -1741,6 +1741,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
14 changes: 13 additions & 1 deletion src/compiler/sys.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ module ts {
getExecutingFilePath(): string;
getCurrentDirectory(): string;
readDirectory(path: string, extension?: string): string[];
readDirectoryFlat(path: string): string[];
getMemoryUsage?(): number;
exit(exitCode?: number): void;
}
Expand Down Expand Up @@ -135,6 +136,11 @@ module ts {
}
}
}

function readDirectoryFlat(path: string): string[] {
var folder = fso.GetFolder(path || ".");
return [...getNames(folder.files), ...getNames(folder.subfolders)];
}

return {
args,
Expand Down Expand Up @@ -166,6 +172,7 @@ module ts {
return new ActiveXObject("WScript.Shell").CurrentDirectory;
},
readDirectory,
readDirectoryFlat,
exit(exitCode?: number): void {
try {
WScript.Quit(exitCode);
Expand Down Expand Up @@ -246,6 +253,10 @@ module ts {
}
}
}

function readDirectoryFlat(path: string): string[] {
return _fs.readdirSync(path || ".").sort();
}

return {
args: process.argv.slice(2),
Expand Down Expand Up @@ -277,7 +288,7 @@ module 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 @@ -294,6 +305,7 @@ module ts {
return process.cwd();
},
readDirectory,
readDirectoryFlat,
getMemoryUsage() {
if (global.gc) {
global.gc();
Expand Down
2 changes: 1 addition & 1 deletion src/compiler/tsc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -242,7 +242,7 @@ module ts {
setCachedProgram(compileResult.program);
reportDiagnostic(createCompilerDiagnostic(Diagnostics.Compilation_complete_Watching_for_file_changes));
}

function getSourceFile(fileName: string, languageVersion: ScriptTarget, onError ?: (message: string) => void) {
// Return existing SourceFile object if one is available
if (cachedProgram) {
Expand Down
22 changes: 21 additions & 1 deletion src/compiler/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1027,15 +1027,35 @@ module ts {
// This field should never be used directly to obtain line map, use getLineMap function instead.
/* @internal */ lineMap: number[];
}

export interface ScriptReferenceHost {
getCompilerOptions(): CompilerOptions;
getSourceFile(fileName: string): SourceFile;
getCurrentDirectory(): string;
}

export interface ParseConfigHost {
useCaseSensitiveFileNames: boolean;

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

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

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

/**
* Reads the files in the directory.
* @param path The directory path.
*/
readDirectoryFlat(path: 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 @@ -171,5 +171,8 @@ declare module chai {
function isFalse(value: any, message?: string): void;
function isNull(value: any, message?: string): void;
function isNotNull(value: 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;
}
}
8 changes: 8 additions & 0 deletions src/harness/harnessLanguageService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,10 @@ module Harness.LanguageService {
readDirectory(rootDir: string, extension: string): string {
throw new Error("NYI");
}

readDirectoryFlat(path: string): string {
throw new Error("NYI");
}

log(s: string): void { this.nativeHost.log(s); }
trace(s: string): void { this.nativeHost.trace(s); }
Expand Down Expand Up @@ -537,6 +541,10 @@ module Harness.LanguageService {
throw new Error("Not implemented Yet.");
}

readDirectoryFlat(path: string): string[] {
throw new Error("Not implemented Yet.");
}

watchFile(fileName: string, callback: (fileName: string) => void): ts.FileWatcher {
return { close() { } };
}
Expand Down
21 changes: 16 additions & 5 deletions src/harness/runner.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,19 @@ var testConfigFile =
Harness.IO.fileExists(mytestconfig) ? Harness.IO.readFile(mytestconfig) :
(Harness.IO.fileExists(testconfig) ? Harness.IO.readFile(testconfig) : '');

var unitTestsRequested = false;

if (testConfigFile !== '') {
// TODO: not sure why this is crashing mocha
//var testConfig = JSON.parse(testConfigRaw);
var testConfig = testConfigFile.match(/test:\s\['(.*)'\]/);
var options = testConfig ? [testConfig[1]] : [];
var options: string[];
try {
let testConfigJson = JSON.parse(testConfigFile);
options = testConfigJson.test instanceof Array ? testConfigJson.test : [];
}
catch (e) {
let testConfig = testConfigFile.match(/test:\s\['(.*)'\]/);
options = testConfig ? [testConfig[1]] : [];
}

for (var i = 0; i < options.length; i++) {
switch (options[i]) {
case 'compiler':
Expand Down Expand Up @@ -73,11 +81,14 @@ if (testConfigFile !== '') {
case 'test262':
runners.push(new Test262BaselineRunner());
break;
case 'unit':
unitTestsRequested = true;
break;
}
}
}

if (runners.length === 0) {
if (runners.length === 0 && !unitTestsRequested) {
// compiler
runners.push(new CompilerBaselineRunner(CompilerTestType.Conformance));
runners.push(new CompilerBaselineRunner(CompilerTestType.Regressions));
Expand Down
46 changes: 45 additions & 1 deletion src/services/shims.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,10 @@ module ts {
export interface CoreServicesShimHost extends Logger {
/** Returns a JSON-encoded value of the type: string[] */
readDirectory(rootDir: string, extension: string): string;
readDirectoryFlat?(path: string): string;
useCaseSensitiveFileNames?: boolean;
fileExists?(path: string): boolean;
directoryExists?(path: string): boolean;
}

///
Expand Down Expand Up @@ -335,13 +339,53 @@ module ts {

export class CoreServicesShimHostAdapter implements ParseConfigHost {

public useCaseSensitiveFileNames: boolean;

constructor(private shimHost: CoreServicesShimHost) {
if (typeof shimHost.useCaseSensitiveFileNames === "boolean") {
this.useCaseSensitiveFileNames = shimHost.useCaseSensitiveFileNames;
}
else if (sys) {
this.useCaseSensitiveFileNames = sys.useCaseSensitiveFileNames;
}
else {
this.useCaseSensitiveFileNames = true;
}
}

public readDirectory(rootDir: string, extension: string): string[] {
var encoded = this.shimHost.readDirectory(rootDir, extension);
return JSON.parse(encoded);
}

public readDirectoryFlat(path: string): string[] {
path = normalizePath(path);
path = ensureTrailingDirectorySeparator(path);
if (this.shimHost.readDirectoryFlat) {
var encoded = this.shimHost.readDirectoryFlat(path);
return JSON.parse(encoded);
}

return sys ? sys.readDirectoryFlat(path): [];
}

public fileExists(path: string): boolean {
path = normalizePath(path);
if (this.shimHost.fileExists) {
return this.shimHost.fileExists(path);
}

return sys ? sys.fileExists(path) : undefined;
}

public directoryExists(path: string): boolean {
path = normalizePath(path);
if (this.shimHost.directoryExists) {
return this.shimHost.directoryExists(path);
}

return sys ? sys.directoryExists(path) : undefined;
}
}

function simpleForwardCall(logger: Logger, actionDescription: string, action: () => any, noPerfLogging: boolean): any {
Expand Down
Loading