mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-02-26 21:23:53 -06:00
Turn on skipLibCheck for js-only inferred project and external project (#11399)
* Turn on skipLibCheck for js-only inferred project and external project * avoid changing compiler options * Update tests
This commit is contained in:
parent
2671668d86
commit
460de66311
@ -975,7 +975,7 @@ namespace ts {
|
||||
basePath: string, errors: Diagnostic[], configFileName?: string): CompilerOptions {
|
||||
|
||||
const options: CompilerOptions = getBaseFileName(configFileName) === "jsconfig.json"
|
||||
? { allowJs: true, maxNodeModuleJsDepth: 2, allowSyntheticDefaultImports: true }
|
||||
? { allowJs: true, maxNodeModuleJsDepth: 2, allowSyntheticDefaultImports: true, skipLibCheck: true }
|
||||
: {};
|
||||
convertOptionsFromJson(optionDeclarations, jsonOptions, basePath, options, Diagnostics.Unknown_compiler_option_0, errors);
|
||||
return options;
|
||||
|
||||
@ -405,6 +405,7 @@ namespace ts {
|
||||
allowJs: true,
|
||||
maxNodeModuleJsDepth: 2,
|
||||
allowSyntheticDefaultImports: true,
|
||||
skipLibCheck: true,
|
||||
module: ModuleKind.CommonJS,
|
||||
target: ScriptTarget.ES5,
|
||||
noImplicitAny: false,
|
||||
@ -433,6 +434,7 @@ namespace ts {
|
||||
allowJs: false,
|
||||
maxNodeModuleJsDepth: 2,
|
||||
allowSyntheticDefaultImports: true,
|
||||
skipLibCheck: true,
|
||||
module: ModuleKind.CommonJS,
|
||||
target: ScriptTarget.ES5,
|
||||
noImplicitAny: false,
|
||||
@ -456,7 +458,8 @@ namespace ts {
|
||||
{
|
||||
allowJs: true,
|
||||
maxNodeModuleJsDepth: 2,
|
||||
allowSyntheticDefaultImports: true
|
||||
allowSyntheticDefaultImports: true,
|
||||
skipLibCheck: true
|
||||
},
|
||||
errors: [{
|
||||
file: undefined,
|
||||
@ -477,7 +480,8 @@ namespace ts {
|
||||
{
|
||||
allowJs: true,
|
||||
maxNodeModuleJsDepth: 2,
|
||||
allowSyntheticDefaultImports: true
|
||||
allowSyntheticDefaultImports: true,
|
||||
skipLibCheck: true
|
||||
},
|
||||
errors: <Diagnostic[]>[]
|
||||
}
|
||||
|
||||
@ -3,6 +3,8 @@
|
||||
|
||||
namespace ts.projectSystem {
|
||||
import TI = server.typingsInstaller;
|
||||
import protocol = server.protocol;
|
||||
import CommandNames = server.CommandNames;
|
||||
|
||||
const safeList = {
|
||||
path: <Path>"/safeList.json",
|
||||
@ -128,7 +130,7 @@ namespace ts.projectSystem {
|
||||
return combinePaths(getDirectoryPath(libFile.path), "tsc.js");
|
||||
}
|
||||
|
||||
export function toExternalFile(fileName: string): server.protocol.ExternalFile {
|
||||
export function toExternalFile(fileName: string): protocol.ExternalFile {
|
||||
return { fileName };
|
||||
}
|
||||
|
||||
@ -527,7 +529,7 @@ namespace ts.projectSystem {
|
||||
}
|
||||
|
||||
export function makeSessionRequest<T>(command: string, args: T) {
|
||||
const newRequest: server.protocol.Request = {
|
||||
const newRequest: protocol.Request = {
|
||||
seq: 0,
|
||||
type: "request",
|
||||
command,
|
||||
@ -538,7 +540,7 @@ namespace ts.projectSystem {
|
||||
|
||||
export function openFilesForSession(files: FileOrFolder[], session: server.Session) {
|
||||
for (const file of files) {
|
||||
const request = makeSessionRequest<server.protocol.OpenRequestArgs>(server.CommandNames.Open, { file: file.path });
|
||||
const request = makeSessionRequest<protocol.OpenRequestArgs>(CommandNames.Open, { file: file.path });
|
||||
session.executeCommand(request);
|
||||
}
|
||||
}
|
||||
@ -1751,7 +1753,7 @@ namespace ts.projectSystem {
|
||||
});
|
||||
|
||||
describe("navigate-to for javascript project", () => {
|
||||
function containsNavToItem(items: server.protocol.NavtoItem[], itemName: string, itemKind: string) {
|
||||
function containsNavToItem(items: protocol.NavtoItem[], itemName: string, itemKind: string) {
|
||||
return find(items, item => item.name === itemName && item.kind === itemKind) !== undefined;
|
||||
}
|
||||
|
||||
@ -1769,12 +1771,12 @@ namespace ts.projectSystem {
|
||||
openFilesForSession([file1], session);
|
||||
|
||||
// Try to find some interface type defined in lib.d.ts
|
||||
const libTypeNavToRequest = makeSessionRequest<server.protocol.NavtoRequestArgs>(server.CommandNames.Navto, { searchValue: "Document", file: file1.path, projectFileName: configFile.path });
|
||||
const items: server.protocol.NavtoItem[] = session.executeCommand(libTypeNavToRequest).response;
|
||||
const libTypeNavToRequest = makeSessionRequest<protocol.NavtoRequestArgs>(CommandNames.Navto, { searchValue: "Document", file: file1.path, projectFileName: configFile.path });
|
||||
const items: protocol.NavtoItem[] = session.executeCommand(libTypeNavToRequest).response;
|
||||
assert.isFalse(containsNavToItem(items, "Document", "interface"), `Found lib.d.ts symbol in JavaScript project nav to request result.`);
|
||||
|
||||
const localFunctionNavToRequst = makeSessionRequest<server.protocol.NavtoRequestArgs>(server.CommandNames.Navto, { searchValue: "foo", file: file1.path, projectFileName: configFile.path });
|
||||
const items2: server.protocol.NavtoItem[] = session.executeCommand(localFunctionNavToRequst).response;
|
||||
const localFunctionNavToRequst = makeSessionRequest<protocol.NavtoRequestArgs>(CommandNames.Navto, { searchValue: "foo", file: file1.path, projectFileName: configFile.path });
|
||||
const items2: protocol.NavtoItem[] = session.executeCommand(localFunctionNavToRequst).response;
|
||||
assert.isTrue(containsNavToItem(items2, "foo", "function"), `Cannot find function symbol "foo".`);
|
||||
});
|
||||
});
|
||||
@ -2309,4 +2311,80 @@ namespace ts.projectSystem {
|
||||
serverEventManager.checkEventCountOfType("configFileDiag", 1);
|
||||
});
|
||||
});
|
||||
|
||||
describe("skipLibCheck", () => {
|
||||
it("should be turned on for js-only inferred projects", () => {
|
||||
const file1 = {
|
||||
path: "/a/b/file1.js",
|
||||
content: `
|
||||
/// <reference path="file2.d.ts" />
|
||||
var x = 1;`
|
||||
};
|
||||
const file2 = {
|
||||
path: "/a/b/file2.d.ts",
|
||||
content: `
|
||||
interface T {
|
||||
name: string;
|
||||
};
|
||||
interface T {
|
||||
name: number;
|
||||
};`
|
||||
};
|
||||
const host = createServerHost([file1, file2]);
|
||||
const session = createSession(host);
|
||||
openFilesForSession([file1, file2], session);
|
||||
|
||||
const file2GetErrRequest = makeSessionRequest<protocol.SemanticDiagnosticsSyncRequestArgs>(
|
||||
CommandNames.SemanticDiagnosticsSync,
|
||||
{ file: file2.path }
|
||||
);
|
||||
let errorResult = <protocol.Diagnostic[]>session.executeCommand(file2GetErrRequest).response;
|
||||
assert.isTrue(errorResult.length === 0);
|
||||
|
||||
const closeFileRequest = makeSessionRequest<protocol.FileRequestArgs>(CommandNames.Close, { file: file1.path });
|
||||
session.executeCommand(closeFileRequest);
|
||||
errorResult = <protocol.Diagnostic[]>session.executeCommand(file2GetErrRequest).response;
|
||||
assert.isTrue(errorResult.length !== 0);
|
||||
|
||||
openFilesForSession([file1], session);
|
||||
errorResult = <protocol.Diagnostic[]>session.executeCommand(file2GetErrRequest).response;
|
||||
assert.isTrue(errorResult.length === 0);
|
||||
});
|
||||
|
||||
it("should be turned on for js-only external projects", () => {
|
||||
const jsFile = {
|
||||
path: "/a/b/file1.js",
|
||||
content: "let x =1;"
|
||||
};
|
||||
const dTsFile = {
|
||||
path: "/a/b/file2.d.ts",
|
||||
content: `
|
||||
interface T {
|
||||
name: string;
|
||||
};
|
||||
interface T {
|
||||
name: number;
|
||||
};`
|
||||
};
|
||||
const host = createServerHost([jsFile, dTsFile]);
|
||||
const session = createSession(host);
|
||||
|
||||
const openExternalProjectRequest = makeSessionRequest<protocol.OpenExternalProjectArgs>(
|
||||
CommandNames.OpenExternalProject,
|
||||
{
|
||||
projectFileName: "project1",
|
||||
rootFiles: toExternalFiles([jsFile.path, dTsFile.path]),
|
||||
options: {}
|
||||
}
|
||||
);
|
||||
session.executeCommand(openExternalProjectRequest);
|
||||
|
||||
const dTsFileGetErrRequest = makeSessionRequest<protocol.SemanticDiagnosticsSyncRequestArgs>(
|
||||
CommandNames.SemanticDiagnosticsSync,
|
||||
{ file: dTsFile.path }
|
||||
);
|
||||
const errorResult = <protocol.Diagnostic[]>session.executeCommand(dTsFileGetErrRequest).response;
|
||||
assert.isTrue(errorResult.length === 0);
|
||||
});
|
||||
});
|
||||
}
|
||||
@ -20,16 +20,42 @@ namespace ts.server {
|
||||
}
|
||||
}
|
||||
|
||||
function isJsOrDtsFile(info: ScriptInfo) {
|
||||
return info.scriptKind === ScriptKind.JS || info.scriptKind == ScriptKind.JSX || fileExtensionIs(info.fileName, ".d.ts");
|
||||
function countEachFileTypes(infos: ScriptInfo[]): { js: number, jsx: number, ts: number, tsx: number, dts: number } {
|
||||
const result = { js: 0, jsx: 0, ts: 0, tsx: 0, dts: 0 };
|
||||
for (const info of infos) {
|
||||
switch (info.scriptKind) {
|
||||
case ScriptKind.JS:
|
||||
result.js += 1;
|
||||
break;
|
||||
case ScriptKind.JSX:
|
||||
result.jsx += 1;
|
||||
break;
|
||||
case ScriptKind.TS:
|
||||
fileExtensionIs(info.fileName, ".d.ts")
|
||||
? result.dts += 1
|
||||
: result.ts += 1;
|
||||
break;
|
||||
case ScriptKind.TSX:
|
||||
result.tsx += 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
function hasOneOrMoreJsAndNoTsFiles(project: Project) {
|
||||
const counts = countEachFileTypes(project.getScriptInfos());
|
||||
return counts.js > 0 && counts.ts === 0 && counts.tsx === 0;
|
||||
}
|
||||
|
||||
export function allRootFilesAreJsOrDts(project: Project): boolean {
|
||||
return project.getRootScriptInfos().every(isJsOrDtsFile);
|
||||
const counts = countEachFileTypes(project.getRootScriptInfos());
|
||||
return counts.ts === 0 && counts.tsx === 0;
|
||||
}
|
||||
|
||||
export function allFilesAreJsOrDts(project: Project): boolean {
|
||||
return project.getScriptInfos().every(isJsOrDtsFile);
|
||||
const counts = countEachFileTypes(project.getScriptInfos());
|
||||
return counts.ts === 0 && counts.tsx === 0;
|
||||
}
|
||||
|
||||
export interface ProjectFilesWithTSDiagnostics extends protocol.ProjectFiles {
|
||||
@ -71,11 +97,16 @@ namespace ts.server {
|
||||
|
||||
public typesVersion = 0;
|
||||
|
||||
public isJsOnlyProject() {
|
||||
public isNonTsProject() {
|
||||
this.updateGraph();
|
||||
return allFilesAreJsOrDts(this);
|
||||
}
|
||||
|
||||
public isJsOnlyProject() {
|
||||
this.updateGraph();
|
||||
return hasOneOrMoreJsAndNoTsFiles(this);
|
||||
}
|
||||
|
||||
constructor(
|
||||
readonly projectKind: ProjectKind,
|
||||
readonly projectService: ProjectService,
|
||||
|
||||
@ -14,6 +14,17 @@ namespace ts.server {
|
||||
return ((1e9 * seconds) + nanoseconds) / 1000000.0;
|
||||
}
|
||||
|
||||
function shouldSkipSematicCheck(project: Project) {
|
||||
if (project.getCompilerOptions().skipLibCheck !== undefined) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((project.projectKind === ProjectKind.Inferred || project.projectKind === ProjectKind.External) && project.isJsOnlyProject()) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
interface FileStart {
|
||||
file: string;
|
||||
start: ILineInfo;
|
||||
@ -255,12 +266,13 @@ namespace ts.server {
|
||||
|
||||
private semanticCheck(file: NormalizedPath, project: Project) {
|
||||
try {
|
||||
const diags = project.getLanguageService().getSemanticDiagnostics(file);
|
||||
|
||||
if (diags) {
|
||||
const bakedDiags = diags.map((diag) => formatDiag(file, project, diag));
|
||||
this.event({ file: file, diagnostics: bakedDiags }, "semanticDiag");
|
||||
let diags: Diagnostic[] = [];
|
||||
if (!shouldSkipSematicCheck(project)) {
|
||||
diags = project.getLanguageService().getSemanticDiagnostics(file);
|
||||
}
|
||||
|
||||
const bakedDiags = diags.map((diag) => formatDiag(file, project, diag));
|
||||
this.event({ file: file, diagnostics: bakedDiags }, "semanticDiag");
|
||||
}
|
||||
catch (err) {
|
||||
this.logError(err, "semantic check");
|
||||
@ -373,6 +385,9 @@ namespace ts.server {
|
||||
|
||||
private getDiagnosticsWorker(args: protocol.FileRequestArgs, selector: (project: Project, file: string) => Diagnostic[], includeLinePosition: boolean) {
|
||||
const { project, file } = this.getFileAndProject(args);
|
||||
if (shouldSkipSematicCheck(project)) {
|
||||
return [];
|
||||
}
|
||||
const scriptInfo = project.getScriptInfoForNormalizedPath(file);
|
||||
const diagnostics = selector(project, file);
|
||||
return includeLinePosition
|
||||
@ -1133,7 +1148,7 @@ namespace ts.server {
|
||||
return combineProjectOutput(
|
||||
projects,
|
||||
project => {
|
||||
const navItems = project.getLanguageService().getNavigateToItems(args.searchValue, args.maxResultCount, fileName, /*excludeDts*/ project.isJsOnlyProject());
|
||||
const navItems = project.getLanguageService().getNavigateToItems(args.searchValue, args.maxResultCount, fileName, /*excludeDts*/ project.isNonTsProject());
|
||||
if (!navItems) {
|
||||
return [];
|
||||
}
|
||||
@ -1171,7 +1186,7 @@ namespace ts.server {
|
||||
else {
|
||||
return combineProjectOutput(
|
||||
projects,
|
||||
project => project.getLanguageService().getNavigateToItems(args.searchValue, args.maxResultCount, fileName, /*excludeDts*/ project.isJsOnlyProject()),
|
||||
project => project.getLanguageService().getNavigateToItems(args.searchValue, args.maxResultCount, fileName, /*excludeDts*/ project.isNonTsProject()),
|
||||
/*comparer*/ undefined,
|
||||
navigateToItemIsEqualTo);
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user