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

Add support for 'lib' reference directive #15780

Closed
wants to merge 17 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
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
104 changes: 28 additions & 76 deletions Gulpfile.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import through2 = require("through2");
import merge2 = require("merge2");
import * as os from "os";
import fold = require("travis-fold");
import ts = require("./lib/typescript");
const gulp = helpMaker(originalGulp);

Error.stackTraceLimit = 1000;
Expand Down Expand Up @@ -74,7 +75,22 @@ const cmdLineOptions = minimist(process.argv.slice(2), {
}
});

function readJson(jsonPath: string): any {
const jsonText = fs.readFileSync(jsonPath).toString();
const result = ts.parseConfigFileTextToJson(jsonPath, jsonText);
if (result.error) {
throw new Error(diagnosticsToString([result.error]));
}

return result.config;

function diagnosticsToString(s: ts.Diagnostic[]) {
return s.map(e => ts.flattenDiagnosticMessageText(e.messageText, ts.sys.newLine)).join(ts.sys.newLine);
}
}

const noop = () => {}; // tslint:disable-line no-empty

function exec(cmd: string, args: string[], complete: () => void = noop, error: (e: any, status: number) => void = noop) {
console.log(`${cmd} ${args.join(" ")}`);
// TODO (weswig): Update child_process types to add windowsVerbatimArguments to the type definition
Expand Down Expand Up @@ -114,71 +130,6 @@ const nodeModulesPathPrefix = path.resolve("./node_modules/.bin/");
const isWin = /^win/.test(process.platform);
const mocha = path.join(nodeModulesPathPrefix, "mocha") + (isWin ? ".cmd" : "");

const es2015LibrarySources = [
"es2015.core.d.ts",
"es2015.collection.d.ts",
"es2015.generator.d.ts",
"es2015.iterable.d.ts",
"es2015.promise.d.ts",
"es2015.proxy.d.ts",
"es2015.reflect.d.ts",
"es2015.symbol.d.ts",
"es2015.symbol.wellknown.d.ts"
];

const es2015LibrarySourceMap = es2015LibrarySources.map(source =>
({ target: "lib." + source, sources: ["header.d.ts", source] }));

const es2016LibrarySource = ["es2016.array.include.d.ts"];

const es2016LibrarySourceMap = es2016LibrarySource.map(source =>
({ target: "lib." + source, sources: ["header.d.ts", source] }));

const es2017LibrarySource = [
"es2017.object.d.ts",
"es2017.sharedmemory.d.ts",
"es2017.string.d.ts",
"es2017.intl.d.ts",
"es2017.typedarrays.d.ts",
];

const es2017LibrarySourceMap = es2017LibrarySource.map(source =>
({ target: "lib." + source, sources: ["header.d.ts", source] }));

const esnextLibrarySource = [
"esnext.asynciterable.d.ts"
];

const esnextLibrarySourceMap = esnextLibrarySource.map(source =>
({ target: "lib." + source, sources: ["header.d.ts", source] }));

const hostsLibrarySources = ["dom.generated.d.ts", "webworker.importscripts.d.ts", "scripthost.d.ts"];

const librarySourceMap = [
// Host library
{ target: "lib.dom.d.ts", sources: ["header.d.ts", "dom.generated.d.ts"] },
{ target: "lib.dom.iterable.d.ts", sources: ["header.d.ts", "dom.iterable.d.ts"] },
{ target: "lib.webworker.d.ts", sources: ["header.d.ts", "webworker.generated.d.ts"] },
{ target: "lib.scripthost.d.ts", sources: ["header.d.ts", "scripthost.d.ts"] },

// JavaScript library
{ target: "lib.es5.d.ts", sources: ["header.d.ts", "es5.d.ts"] },
{ target: "lib.es2015.d.ts", sources: ["header.d.ts", "es2015.d.ts"] },
{ target: "lib.es2016.d.ts", sources: ["header.d.ts", "es2016.d.ts"] },
{ target: "lib.es2017.d.ts", sources: ["header.d.ts", "es2017.d.ts"] },
{ target: "lib.esnext.d.ts", sources: ["header.d.ts", "esnext.d.ts"] },

// JavaScript + all host library
{ target: "lib.d.ts", sources: ["header.d.ts", "es5.d.ts"].concat(hostsLibrarySources) },
{ target: "lib.es6.d.ts", sources: ["header.d.ts", "es5.d.ts"].concat(es2015LibrarySources, hostsLibrarySources, "dom.iterable.d.ts") },
{ target: "lib.es2016.full.d.ts", sources: ["header.d.ts", "es2016.d.ts"].concat(hostsLibrarySources, "dom.iterable.d.ts") },
{ target: "lib.es2017.full.d.ts", sources: ["header.d.ts", "es2017.d.ts"].concat(hostsLibrarySources, "dom.iterable.d.ts") },
{ target: "lib.esnext.full.d.ts", sources: ["header.d.ts", "esnext.d.ts"].concat(hostsLibrarySources, "dom.iterable.d.ts") },
].concat(es2015LibrarySourceMap, es2016LibrarySourceMap, es2017LibrarySourceMap, esnextLibrarySourceMap);

const libraryTargets = librarySourceMap.map(f =>
path.join(builtLocalDirectory, f.target));

/**
* .lcg file is what localization team uses to know what messages to localize.
* The file is always generated in 'enu\diagnosticMessages.generated.json.lcg'
Expand All @@ -196,17 +147,6 @@ const localizationTargets = ["cs", "de", "es", "fr", "it", "ja", "ko", "pl", "pt
.map(f => path.join(builtLocalDirectory, f, "diagnosticMessages.generated.json"))
.concat(generatedLCGFile);

for (const i in libraryTargets) {
const entry = librarySourceMap[i];
const target = libraryTargets[i];
const sources = [copyright].concat(entry.sources.map(s => path.join(libraryDirectory, s)));
gulp.task(target, /*help*/ false, [], () =>
gulp.src(sources)
.pipe(newer(target))
.pipe(concat(target, { newLine: "\n\n" }))
.pipe(gulp.dest(".")));
}

const configureNightlyJs = path.join(scriptsDirectory, "configureNightly.js");
const configureNightlyTs = path.join(scriptsDirectory, "configureNightly.ts");
const packageJson = "package.json";
Expand Down Expand Up @@ -341,6 +281,18 @@ gulp.task("importDefinitelyTypedTests", "Runs scripts/importDefinitelyTypedTests
exec(host, [importDefinitelyTypedTestsJs, "./", "../DefinitelyTyped"], done, done);
});

const libraries: { libs: string[], paths: Record<string, string> } = readJson(path.resolve("./src/lib/libs.json"));
const libraryTargets = libraries.libs.map(lib => {
const sources = [copyright].concat(["header.d.ts", lib + ".d.ts"].map(s => path.join(libraryDirectory, s)));
const target = path.join(builtLocalDirectory, libraries.paths[lib] || ("lib." + lib + ".d.ts"));
gulp.task(target, /*help*/ false, [], () =>
gulp.src(sources)
.pipe(newer(target))
.pipe(concat(target, { newLine: "\n\n" }))
.pipe(gulp.dest(".")));
return target;
});

gulp.task("lib", "Builds the library targets", libraryTargets);


Expand Down
138 changes: 49 additions & 89 deletions Jakefile.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,19 +37,49 @@ else if (process.env.PATH !== undefined) {
process.env.PATH = nodeModulesPathPrefix + process.env.PATH;
}

function filesFromConfig(configPath) {
var configText = fs.readFileSync(configPath).toString();
var config = ts.parseConfigFileTextToJson(configPath, configText);
if (config.error) {
throw new Error(diagnosticsToString([config.error]));
function readJson(jsonPath) {
var jsonText = fs.readFileSync(jsonPath).toString();
var result = ts.parseJsonText(jsonPath, jsonText);
reportDiagnostics(/** @type {*} */(result).parseDiagnostics);
var diagnostics = [];
var json = ts.convertToObject(result, diagnostics);
reportDiagnostics(diagnostics);
return json;
// var result = ts.parseConfigFileTextToJson(jsonPath, jsonText);
// if (result.error) {
// throw new Error(diagnosticsToString([result.error]));
// }

// return result.config;

// function diagnosticsToString(s) {
// return s.map(function(e) { return ts.flattenDiagnosticMessageText(e.messageText, ts.sys.newLine); }).join(ts.sys.newLine);
// }
}

function reportDiagnostics(diagnostics) {
if (diagnostics && diagnostics.length) {
throw new Error("An error ocurred during parse:\n" + diagnosticsToString(diagnostics));
}

function diagnosticsToString(s) {
return ts.formatDiagnostics(s, {
getCurrentDirectory() { return process.cwd(); },
getCanonicalFileName(fileName) { return fileName; },
getNewLine() { return os.EOL; }
});
}
const configFileContent = ts.parseJsonConfigFileContent(config.config, ts.sys, path.dirname(configPath));
}

function filesFromConfig(configPath) {
var jsonText = fs.readFileSync(configPath).toString();
var config = ts.parseConfigFileTextToJson(configPath, jsonText).config;
var configFileContent = ts.parseJsonConfigFileContent(config, ts.sys, path.dirname(configPath));
if (configFileContent.errors && configFileContent.errors.length) {
throw new Error(diagnosticsToString(configFileContent.errors));
}

return configFileContent.fileNames;

function diagnosticsToString(s) {
return s.map(function(e) { return ts.flattenDiagnosticMessageText(e.messageText, ts.sys.newLine); }).join(ts.sys.newLine);
}
Expand Down Expand Up @@ -171,76 +201,6 @@ var harnessSources = harnessCoreSources.concat([
return path.join(serverDirectory, f);
}));

var es2015LibrarySources = [
"es2015.core.d.ts",
"es2015.collection.d.ts",
"es2015.generator.d.ts",
"es2015.iterable.d.ts",
"es2015.promise.d.ts",
"es2015.proxy.d.ts",
"es2015.reflect.d.ts",
"es2015.symbol.d.ts",
"es2015.symbol.wellknown.d.ts"
];

var es2015LibrarySourceMap = es2015LibrarySources.map(function (source) {
return { target: "lib." + source, sources: ["header.d.ts", source] };
});

var es2016LibrarySource = ["es2016.array.include.d.ts"];

var es2016LibrarySourceMap = es2016LibrarySource.map(function (source) {
return { target: "lib." + source, sources: ["header.d.ts", source] };
});

var es2017LibrarySource = [
"es2017.object.d.ts",
"es2017.sharedmemory.d.ts",
"es2017.string.d.ts",
"es2017.intl.d.ts",
"es2017.typedarrays.d.ts",
];

var es2017LibrarySourceMap = es2017LibrarySource.map(function (source) {
return { target: "lib." + source, sources: ["header.d.ts", source] };
});

var esnextLibrarySource = [
"esnext.asynciterable.d.ts"
];

var esnextLibrarySourceMap = esnextLibrarySource.map(function (source) {
return { target: "lib." + source, sources: ["header.d.ts", source] };
});

var hostsLibrarySources = ["dom.generated.d.ts", "webworker.importscripts.d.ts", "scripthost.d.ts"];

var librarySourceMap = [
// Host library
{ target: "lib.dom.d.ts", sources: ["header.d.ts", "dom.generated.d.ts"] },
{ target: "lib.dom.iterable.d.ts", sources: ["header.d.ts", "dom.iterable.d.ts"] },
{ target: "lib.webworker.d.ts", sources: ["header.d.ts", "webworker.generated.d.ts"] },
{ target: "lib.scripthost.d.ts", sources: ["header.d.ts", "scripthost.d.ts"] },

// JavaScript library
{ target: "lib.es5.d.ts", sources: ["header.d.ts", "es5.d.ts"] },
{ target: "lib.es2015.d.ts", sources: ["header.d.ts", "es2015.d.ts"] },
{ target: "lib.es2016.d.ts", sources: ["header.d.ts", "es2016.d.ts"] },
{ target: "lib.es2017.d.ts", sources: ["header.d.ts", "es2017.d.ts"] },
{ target: "lib.esnext.d.ts", sources: ["header.d.ts", "esnext.d.ts"] },

// JavaScript + all host library
{ target: "lib.d.ts", sources: ["header.d.ts", "es5.d.ts"].concat(hostsLibrarySources) },
{ target: "lib.es6.d.ts", sources: ["header.d.ts", "es5.d.ts"].concat(es2015LibrarySources, hostsLibrarySources, "dom.iterable.d.ts") },
{ target: "lib.es2016.full.d.ts", sources: ["header.d.ts", "es2016.d.ts"].concat(hostsLibrarySources, "dom.iterable.d.ts") },
{ target: "lib.es2017.full.d.ts", sources: ["header.d.ts", "es2017.d.ts"].concat(hostsLibrarySources, "dom.iterable.d.ts") },
{ target: "lib.esnext.full.d.ts", sources: ["header.d.ts", "esnext.d.ts"].concat(hostsLibrarySources, "dom.iterable.d.ts") },
].concat(es2015LibrarySourceMap, es2016LibrarySourceMap, es2017LibrarySourceMap, esnextLibrarySourceMap);

var libraryTargets = librarySourceMap.map(function (f) {
return path.join(builtLocalDirectory, f.target);
});

/**
* .lcg file is what localization team uses to know what messages to localize.
* The file is always generated in 'enu\diagnosticMessages.generated.json.lcg'
Expand Down Expand Up @@ -415,18 +375,18 @@ function compileFile(outFile, sources, prereqs, prefixes, useBuiltCompiler, opts
// Prerequisite task for built directory and library typings
directory(builtLocalDirectory);

for (var i in libraryTargets) {
(function (i) {
var entry = librarySourceMap[i];
var target = libraryTargets[i];
var sources = [copyright].concat(entry.sources.map(function (s) {
return path.join(libraryDirectory, s);
}));
file(target, [builtLocalDirectory].concat(sources), function () {
concatenateFiles(target, sources);
});
})(i);
}
/** @type {{ libs:string[], paths: Record<string, string> }} */
var libraries = readJson(path.resolve("./src/lib/libs.json"));
var libraryTargets = libraries.libs.map(function (lib) {
var sources = [copyright].concat(["header.d.ts", lib + ".d.ts"].map(function (s) {
return path.join(libraryDirectory, s);
}));
var target = path.join(builtLocalDirectory, libraries.paths[lib] || ("lib." + lib + ".d.ts"));
file(target, [builtLocalDirectory].concat(sources), function () {
concatenateFiles(target, sources);
});
return target;
});

// Lib target to build the library files
desc("Builds the library targets");
Expand Down
47 changes: 1 addition & 46 deletions src/compiler/checker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15379,52 +15379,7 @@ namespace ts {
* Names longer than 30 characters don't get suggestions because Levenshtein distance is an n**2 algorithm.
*/
function getSpellingSuggestionForName(name: string, symbols: Symbol[], meaning: SymbolFlags): Symbol | undefined {
const worstDistance = name.length * 0.4;
const maximumLengthDifference = Math.min(3, name.length * 0.34);
let bestDistance = Number.MAX_VALUE;
let bestCandidate = undefined;
let justCheckExactMatches = false;
if (name.length > 30) {
return undefined;
}
name = name.toLowerCase();
for (const candidate of symbols) {
let candidateName = symbolName(candidate);
if (candidate.flags & meaning &&
candidateName &&
Math.abs(candidateName.length - name.length) < maximumLengthDifference) {
candidateName = candidateName.toLowerCase();
if (candidateName === name) {
return candidate;
}
if (justCheckExactMatches) {
continue;
}
if (candidateName.length < 3 ||
name.length < 3 ||
candidateName === "eval" ||
candidateName === "intl" ||
candidateName === "undefined" ||
candidateName === "map" ||
candidateName === "nan" ||
candidateName === "set") {
continue;
}
const distance = levenshtein(name, candidateName);
if (distance > worstDistance) {
continue;
}
if (distance < 3) {
justCheckExactMatches = true;
bestCandidate = candidate;
}
else if (distance < bestDistance) {
bestDistance = distance;
bestCandidate = candidate;
}
}
}
return bestCandidate;
return getSpellingSuggestion(name, symbols, ["eval", "intl", "undefined", "map", "set"], candidate => candidate.flags & meaning ? symbolName(candidate) : undefined);
}

function markPropertyAsReferenced(prop: Symbol, nodeForCheckWriteOnly: Node | undefined, isThisAccess: boolean) {
Expand Down
Loading