Skip to content

Add support for 'lib' reference directive #15780

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

Closed
wants to merge 17 commits into from
Closed
Show file tree
Hide file tree
Changes from 5 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
41 changes: 1 addition & 40 deletions src/compiler/checker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14296,46 +14296,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;
if (name.length > 30) {
return undefined;
}
name = name.toLowerCase();
for (const candidate of symbols) {
if (candidate.flags & meaning &&
candidate.name &&
Math.abs(candidate.name.length - name.length) < maximumLengthDifference) {
const candidateName = candidate.name.toLowerCase();
if (candidateName === name) {
return candidate;
}
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) {
return candidate;
}
else if (distance < bestDistance) {
bestDistance = distance;
bestCandidate = candidate;
}
}
}
return bestCandidate;
return getSpellingSuggestion(name, symbols, ["eval", "intl", "undefined", "map", "set"], candidate => candidate.flags & meaning ? candidate.name : undefined);
}

function markPropertyAsReferenced(prop: Symbol) {
Expand Down
67 changes: 37 additions & 30 deletions src/compiler/commandLineParser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,42 @@
namespace ts {
/* @internal */
export const compileOnSaveCommandLineOption: CommandLineOption = { name: "compileOnSave", type: "boolean" };

/* @internal */
export const libMap = createMapFromTemplate({
Copy link

@ghost ghost May 11, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This just maps x to lib.x.d.ts. Could be a function instead, combined with a set of allowed libs.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This must be a Map to be used in the compiler option I pulled it from, below. If I added a function then we would have yet another place to maintain this list (in addition to the jakefile/gulpfile).

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would still be nice to generate this instead of writing it explicitly. Start with const libs = ["es5", ..., "esnext.asynciterable"], generate the map with lib.${x}.d.ts, and you'll no longer need to use arrayFrom(libMap.keys()).

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Except for the outliers like "es6" and "es7" which are aliases.

Copy link
Member Author

@rbuckton rbuckton May 11, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Alternatively, we leave libMap as is, and add: export const libs = arrayFrom(libMap.keys());

// JavaScript only
"es5": "lib.es5.d.ts",
"es6": "lib.es2015.d.ts",
"es2015": "lib.es2015.d.ts",
"es7": "lib.es2016.d.ts",
"es2016": "lib.es2016.d.ts",
"es2017": "lib.es2017.d.ts",
"esnext": "lib.esnext.d.ts",
// Host only
"dom": "lib.dom.d.ts",
"dom.iterable": "lib.dom.iterable.d.ts",
"webworker": "lib.webworker.d.ts",
"scripthost": "lib.scripthost.d.ts",
// ES2015 Or ESNext By-feature options
"es2015.core": "lib.es2015.core.d.ts",
"es2015.collection": "lib.es2015.collection.d.ts",
"es2015.generator": "lib.es2015.generator.d.ts",
"es2015.iterable": "lib.es2015.iterable.d.ts",
"es2015.promise": "lib.es2015.promise.d.ts",
"es2015.proxy": "lib.es2015.proxy.d.ts",
"es2015.reflect": "lib.es2015.reflect.d.ts",
"es2015.symbol": "lib.es2015.symbol.d.ts",
"es2015.symbol.wellknown": "lib.es2015.symbol.wellknown.d.ts",
"es2016.array.include": "lib.es2016.array.include.d.ts",
"es2017.object": "lib.es2017.object.d.ts",
"es2017.sharedmemory": "lib.es2017.sharedmemory.d.ts",
"es2017.string": "lib.es2017.string.d.ts",
"esnext.asynciterable": "lib.esnext.asynciterable.d.ts",
});

/* @internal */
export const libs = arrayFrom(libMap.keys());

/* @internal */
export const optionDeclarations: CommandLineOption[] = [
// CommandLine only options
Expand Down Expand Up @@ -111,36 +147,7 @@ namespace ts {
type: "list",
element: {
name: "lib",
type: createMapFromTemplate({
// JavaScript only
"es5": "lib.es5.d.ts",
"es6": "lib.es2015.d.ts",
"es2015": "lib.es2015.d.ts",
"es7": "lib.es2016.d.ts",
"es2016": "lib.es2016.d.ts",
"es2017": "lib.es2017.d.ts",
"esnext": "lib.esnext.d.ts",
// Host only
"dom": "lib.dom.d.ts",
"dom.iterable": "lib.dom.iterable.d.ts",
"webworker": "lib.webworker.d.ts",
"scripthost": "lib.scripthost.d.ts",
// ES2015 Or ESNext By-feature options
"es2015.core": "lib.es2015.core.d.ts",
"es2015.collection": "lib.es2015.collection.d.ts",
"es2015.generator": "lib.es2015.generator.d.ts",
"es2015.iterable": "lib.es2015.iterable.d.ts",
"es2015.promise": "lib.es2015.promise.d.ts",
"es2015.proxy": "lib.es2015.proxy.d.ts",
"es2015.reflect": "lib.es2015.reflect.d.ts",
"es2015.symbol": "lib.es2015.symbol.d.ts",
"es2015.symbol.wellknown": "lib.es2015.symbol.wellknown.d.ts",
"es2016.array.include": "lib.es2016.array.include.d.ts",
"es2017.object": "lib.es2017.object.d.ts",
"es2017.sharedmemory": "lib.es2017.sharedmemory.d.ts",
"es2017.string": "lib.es2017.string.d.ts",
"esnext.asynciterable": "lib.esnext.asynciterable.d.ts",
}),
type: libMap,
},
showInSimplifiedHelpView: true,
category: Diagnostics.Basic_Options,
Expand Down
4 changes: 1 addition & 3 deletions src/compiler/comments.ts
Original file line number Diff line number Diff line change
Expand Up @@ -419,9 +419,7 @@ namespace ts {
commentPos + 2 < commentEnd &&
currentText.charCodeAt(commentPos + 2) === CharacterCodes.slash) {
const textSubStr = currentText.substring(commentPos, commentEnd);
return textSubStr.match(fullTripleSlashReferencePathRegEx) ||
textSubStr.match(fullTripleSlashAMDReferencePathRegEx) ?
true : false;
return isTripleSlashPathReferenceOrAmdDependency(textSubStr);
}
return false;
}
Expand Down
4 changes: 4 additions & 0 deletions src/compiler/core.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1126,6 +1126,10 @@ namespace ts {
/** Does nothing. */
export function noop(): void {}

export function identity<T>(value: T): T {
return value;
}

/** Throws an error because a function is not implemented. */
export function notImplemented(): never {
throw new Error("Not implemented");
Expand Down
8 changes: 8 additions & 0 deletions src/compiler/diagnosticMessages.json
Original file line number Diff line number Diff line change
Expand Up @@ -2135,6 +2135,14 @@
"category": "Error",
"code": 2710
},
"Cannot find lib definition for '{0}'.": {
"category": "Error",
"code": 2711
},
"Cannot find lib definition for '{0}'. Did you mean '{1}'?": {
"category": "Error",
"code": 2712
},

"Import declaration '{0}' is using private name '{1}'.": {
"category": "Error",
Expand Down
1 change: 1 addition & 0 deletions src/compiler/factory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1978,6 +1978,7 @@ namespace ts {
if (node.moduleName !== undefined) updated.moduleName = node.moduleName;
if (node.referencedFiles !== undefined) updated.referencedFiles = node.referencedFiles;
if (node.typeReferenceDirectives !== undefined) updated.typeReferenceDirectives = node.typeReferenceDirectives;
if (node.libReferenceDirectives !== undefined) updated.libReferenceDirectives = node.libReferenceDirectives;
if (node.languageVariant !== undefined) updated.languageVariant = node.languageVariant;
if (node.isDeclarationFile !== undefined) updated.isDeclarationFile = node.isDeclarationFile;
if (node.renamedDependencies !== undefined) updated.renamedDependencies = node.renamedDependencies;
Expand Down
31 changes: 18 additions & 13 deletions src/compiler/parser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5830,6 +5830,7 @@ namespace ts {
const triviaScanner = createScanner(sourceFile.languageVersion, /*skipTrivia*/ false, LanguageVariant.Standard, sourceText);
const referencedFiles: FileReference[] = [];
const typeReferenceDirectives: FileReference[] = [];
const libReferenceDirectives: FileReference[] = [];
const amdDependencies: { path: string; name: string }[] = [];
let amdModuleName: string;
let checkJsDirective: CheckJsDirective = undefined;
Expand Down Expand Up @@ -5857,19 +5858,22 @@ namespace ts {
const comment = sourceText.substring(range.pos, range.end);
const referencePathMatchResult = getFileReferenceFromReferencePath(comment, range);
if (referencePathMatchResult) {
const fileReference = referencePathMatchResult.fileReference;
sourceFile.hasNoDefaultLib = referencePathMatchResult.isNoDefaultLib;
const diagnosticMessage = referencePathMatchResult.diagnosticMessage;
if (fileReference) {
if (referencePathMatchResult.isTypeReferenceDirective) {
typeReferenceDirectives.push(fileReference);
}
else {
referencedFiles.push(fileReference);
}
}
if (diagnosticMessage) {
parseDiagnostics.push(createFileDiagnostic(sourceFile, range.pos, range.end - range.pos, diagnosticMessage));
switch (referencePathMatchResult.kind) {
case "error":
parseDiagnostics.push(createFileDiagnostic(sourceFile, range.pos, range.end - range.pos, referencePathMatchResult.diagnosticMessage));
break;
case "no-default-lib":
sourceFile.hasNoDefaultLib = true;
break;
case "types":
typeReferenceDirectives.push(referencePathMatchResult.fileReference);
break;
case "lib":
libReferenceDirectives.push(referencePathMatchResult.fileReference);
break;
case "path":
referencedFiles.push(referencePathMatchResult.fileReference);
break;
}
}
else {
Expand Down Expand Up @@ -5909,6 +5913,7 @@ namespace ts {

sourceFile.referencedFiles = referencedFiles;
sourceFile.typeReferenceDirectives = typeReferenceDirectives;
sourceFile.libReferenceDirectives = libReferenceDirectives;
sourceFile.amdDependencies = amdDependencies;
sourceFile.moduleName = amdModuleName;
sourceFile.checkJsDirective = checkJsDirective;
Expand Down
Loading