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

Port skip semantic check to release-2.0.5 #11713

Merged
merged 4 commits into from
Oct 18, 2016
Merged
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
2 changes: 1 addition & 1 deletion src/compiler/commandLineParser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -902,7 +902,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;
Expand Down
8 changes: 6 additions & 2 deletions src/harness/unittests/convertCompilerOptionsFromJson.ts
Original file line number Diff line number Diff line change
Expand Up @@ -405,6 +405,7 @@ namespace ts {
allowJs: true,
maxNodeModuleJsDepth: 2,
allowSyntheticDefaultImports: true,
skipLibCheck: true,
module: ModuleKind.CommonJS,
target: ScriptTarget.ES5,
noImplicitAny: false,
Expand Down Expand Up @@ -433,6 +434,7 @@ namespace ts {
allowJs: false,
maxNodeModuleJsDepth: 2,
allowSyntheticDefaultImports: true,
skipLibCheck: true,
module: ModuleKind.CommonJS,
target: ScriptTarget.ES5,
noImplicitAny: false,
Expand All @@ -456,7 +458,8 @@ namespace ts {
{
allowJs: true,
maxNodeModuleJsDepth: 2,
allowSyntheticDefaultImports: true
allowSyntheticDefaultImports: true,
skipLibCheck: true
},
errors: [{
file: undefined,
Expand All @@ -477,7 +480,8 @@ namespace ts {
{
allowJs: true,
maxNodeModuleJsDepth: 2,
allowSyntheticDefaultImports: true
allowSyntheticDefaultImports: true,
skipLibCheck: true
},
errors: <Diagnostic[]>[]
}
Expand Down
92 changes: 84 additions & 8 deletions src/harness/unittests/tsserverProjectSystem.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

namespace ts.projectSystem {
import TI = server.typingsInstaller;
import protocol = server.protocol;
import CommandNames = server.CommandNames;

const safeList = {
Expand Down Expand Up @@ -125,7 +126,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 };
}

Expand Down Expand Up @@ -551,7 +552,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,
Expand All @@ -562,7 +563,7 @@ namespace ts.projectSystem {

export function openFilesForSession(files: FileOrFolder[], session: server.Session) {
for (const file of files) {
const request = makeSessionRequest<server.protocol.OpenRequestArgs>(CommandNames.Open, { file: file.path });
const request = makeSessionRequest<protocol.OpenRequestArgs>(CommandNames.Open, { file: file.path });
session.executeCommand(request);
}
}
Expand Down Expand Up @@ -1775,7 +1776,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;
}

Expand All @@ -1793,12 +1794,12 @@ namespace ts.projectSystem {
openFilesForSession([file1], session);

// Try to find some interface type defined in lib.d.ts
const libTypeNavToRequest = makeSessionRequest<server.protocol.NavtoRequestArgs>(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>(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".`);
});
});
Expand Down Expand Up @@ -2245,7 +2246,82 @@ namespace ts.projectSystem {
// verify content
const snap2 = projectServiice.getScriptInfo(f1.path).snap();
assert.equal(snap2.getText(0, snap2.getLength()), f1.content, "content should be equal to the content of original file");
});
});

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);
});
});
}
34 changes: 32 additions & 2 deletions src/server/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -397,11 +397,41 @@ namespace ts.server {
}

getSyntacticDiagnostics(fileName: string): Diagnostic[] {
throw new Error("Not Implemented Yet.");
const args: protocol.SyntacticDiagnosticsSyncRequestArgs = { file: fileName, includeLinePosition: true };

const request = this.processRequest<protocol.SyntacticDiagnosticsSyncRequest>(CommandNames.SyntacticDiagnosticsSync, args);
const response = this.processResponse<protocol.SyntacticDiagnosticsSyncResponse>(request);

return (<protocol.DiagnosticWithLinePosition[]>response.body).map(entry => this.convertDiagnostic(entry, fileName));
}

getSemanticDiagnostics(fileName: string): Diagnostic[] {
throw new Error("Not Implemented Yet.");
const args: protocol.SemanticDiagnosticsSyncRequestArgs = { file: fileName, includeLinePosition: true };

const request = this.processRequest<protocol.SemanticDiagnosticsSyncRequest>(CommandNames.SemanticDiagnosticsSync, args);
const response = this.processResponse<protocol.SemanticDiagnosticsSyncResponse>(request);

return (<protocol.DiagnosticWithLinePosition[]>response.body).map(entry => this.convertDiagnostic(entry, fileName));
}

convertDiagnostic(entry: protocol.DiagnosticWithLinePosition, fileName: string): Diagnostic {
let category: DiagnosticCategory;
for (const id in DiagnosticCategory) {
if (typeof id === "string" && entry.category === id.toLowerCase()) {
category = (<any>DiagnosticCategory)[id];
}
}

Debug.assert(category !== undefined, "convertDiagnostic: category should not be undefined");

return {
file: undefined,
start: entry.start,
length: entry.length,
messageText: entry.message,
category: category,
code: entry.code
};
}

getCompilerOptionsDiagnostics(): Diagnostic[] {
Expand Down
41 changes: 36 additions & 5 deletions src/server/project.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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,
Expand Down
35 changes: 25 additions & 10 deletions src/server/session.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,17 @@ namespace ts.server {
return ((1e9 * seconds) + nanoseconds) / 1000000.0;
}

function shouldSkipSemanticCheck(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;
Expand Down Expand Up @@ -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 (!shouldSkipSemanticCheck(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");
Expand Down Expand Up @@ -371,8 +383,11 @@ namespace ts.server {
});
}

private getDiagnosticsWorker(args: protocol.FileRequestArgs, selector: (project: Project, file: string) => Diagnostic[], includeLinePosition: boolean) {
private getDiagnosticsWorker(args: protocol.FileRequestArgs, isSemantic: boolean, selector: (project: Project, file: string) => Diagnostic[], includeLinePosition: boolean) {
const { project, file } = this.getFileAndProject(args);
if (isSemantic && shouldSkipSemanticCheck(project)) {
return [];
}
const scriptInfo = project.getScriptInfoForNormalizedPath(file);
const diagnostics = selector(project, file);
return includeLinePosition
Expand Down Expand Up @@ -451,11 +466,11 @@ namespace ts.server {
}

private getSyntacticDiagnosticsSync(args: protocol.SyntacticDiagnosticsSyncRequestArgs): protocol.Diagnostic[] | protocol.DiagnosticWithLinePosition[] {
return this.getDiagnosticsWorker(args, (project, file) => project.getLanguageService().getSyntacticDiagnostics(file), args.includeLinePosition);
return this.getDiagnosticsWorker(args, /*isSemantic*/ false, (project, file) => project.getLanguageService().getSyntacticDiagnostics(file), args.includeLinePosition);
}

private getSemanticDiagnosticsSync(args: protocol.SemanticDiagnosticsSyncRequestArgs): protocol.Diagnostic[] | protocol.DiagnosticWithLinePosition[] {
return this.getDiagnosticsWorker(args, (project, file) => project.getLanguageService().getSemanticDiagnostics(file), args.includeLinePosition);
return this.getDiagnosticsWorker(args, /*isSemantic*/ true, (project, file) => project.getLanguageService().getSemanticDiagnostics(file), args.includeLinePosition);
}

private getDocumentHighlights(args: protocol.DocumentHighlightsRequestArgs, simplifiedResult: boolean): protocol.DocumentHighlightsItem[] | DocumentHighlights[] {
Expand Down Expand Up @@ -1122,7 +1137,7 @@ namespace ts.server {
return combineProjectOutput(
projects,
project => {
const navItems = project.getLanguageService().getNavigateToItems(args.searchValue, args.maxResultCount, /*excludeDts*/ project.isJsOnlyProject());
const navItems = project.getLanguageService().getNavigateToItems(args.searchValue, args.maxResultCount, /*excludeDts*/ project.isNonTsProject());
if (!navItems) {
return [];
}
Expand Down Expand Up @@ -1160,7 +1175,7 @@ namespace ts.server {
else {
return combineProjectOutput(
projects,
project => project.getLanguageService().getNavigateToItems(args.searchValue, args.maxResultCount, /*excludeDts*/ project.isJsOnlyProject()),
project => project.getLanguageService().getNavigateToItems(args.searchValue, args.maxResultCount, /*excludeDts*/ project.isNonTsProject()),
/*comparer*/ undefined,
navigateToItemIsEqualTo);
}
Expand Down
Loading