mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-05-15 21:36:50 -05:00
Do not publicly expose a way on a Program instance to get typecheckers with differing behavior.
Now, you can only get the non-diagnostics, pull-type-checker from the Program instance. If you want diagnostics, you simply ask the Program instance for the diagnostics you want.
This commit is contained in:
@@ -88,7 +88,6 @@ module ts {
|
||||
verifyCompilerOptions();
|
||||
errors.sort(compareDiagnostics);
|
||||
|
||||
|
||||
var diagnosticsProducingTypeChecker: TypeChecker;
|
||||
var noDiagnosticsTypeChecker: TypeChecker;
|
||||
var emitHost: EmitHost;
|
||||
@@ -104,10 +103,16 @@ module ts {
|
||||
getTypeCheckerGlobalDiagnostics,
|
||||
getDeclarationDiagnostics,
|
||||
getTypeChecker,
|
||||
getDiagnosticsProducingTypeChecker,
|
||||
getCommonSourceDirectory: () => commonSourceDirectory,
|
||||
emitFiles: invokeEmitter,
|
||||
isEmitBlocked,
|
||||
getCurrentDirectory: host.getCurrentDirectory,
|
||||
getEmitResolver: () => getDiagnosticsProducingTypeChecker().getEmitResolver(),
|
||||
getNodeCount: () => getDiagnosticsProducingTypeChecker().getNodeCount(),
|
||||
getIdentifierCount: () => getDiagnosticsProducingTypeChecker().getIdentifierCount(),
|
||||
getSymbolCount: () => getDiagnosticsProducingTypeChecker().getSymbolCount(),
|
||||
getTypeCount: () => getDiagnosticsProducingTypeChecker().getTypeCount(),
|
||||
};
|
||||
return program;
|
||||
|
||||
@@ -127,13 +132,8 @@ module ts {
|
||||
return diagnosticsProducingTypeChecker || (diagnosticsProducingTypeChecker = createTypeChecker(program, /*produceDiagnostics:*/ true));
|
||||
}
|
||||
|
||||
function getTypeChecker(produceDiagnostics: boolean) {
|
||||
if (produceDiagnostics) {
|
||||
return getDiagnosticsProducingTypeChecker();
|
||||
}
|
||||
else {
|
||||
return noDiagnosticsTypeChecker || (noDiagnosticsTypeChecker = createTypeChecker(program, produceDiagnostics));
|
||||
}
|
||||
function getTypeChecker() {
|
||||
return noDiagnosticsTypeChecker || (noDiagnosticsTypeChecker = createTypeChecker(program, /*produceDiagnostics:*/ false));
|
||||
}
|
||||
|
||||
function getDeclarationDiagnostics(targetSourceFile: SourceFile): Diagnostic[]{
|
||||
|
||||
@@ -336,9 +336,8 @@ module ts {
|
||||
exitStatus = EmitReturnStatus.AllOutputGenerationSkipped;
|
||||
}
|
||||
else {
|
||||
var checker = program.getTypeChecker(/*fullTypeCheckMode*/ true);
|
||||
var checkStart = new Date().getTime();
|
||||
errors = checker.getDiagnostics();
|
||||
errors = program.getTypeCheckerDiagnostics();
|
||||
if (program.isEmitBlocked()) {
|
||||
exitStatus = EmitReturnStatus.AllOutputGenerationSkipped;
|
||||
}
|
||||
@@ -367,10 +366,10 @@ module ts {
|
||||
var memoryUsed = sys.getMemoryUsage ? sys.getMemoryUsage() : -1;
|
||||
reportCountStatistic("Files", program.getSourceFiles().length);
|
||||
reportCountStatistic("Lines", countLines(program));
|
||||
reportCountStatistic("Nodes", checker ? checker.getNodeCount() : 0);
|
||||
reportCountStatistic("Identifiers", checker ? checker.getIdentifierCount() : 0);
|
||||
reportCountStatistic("Symbols", checker ? checker.getSymbolCount() : 0);
|
||||
reportCountStatistic("Types", checker ? checker.getTypeCount() : 0);
|
||||
reportCountStatistic("Nodes", program.getNodeCount());
|
||||
reportCountStatistic("Identifiers", program.getIdentifierCount());
|
||||
reportCountStatistic("Symbols", program.getSymbolCount());
|
||||
reportCountStatistic("Types", program.getTypeCount());
|
||||
if (memoryUsed >= 0) {
|
||||
reportStatisticalValue("Memory used", Math.round(memoryUsed / 1000) + "K");
|
||||
}
|
||||
|
||||
@@ -930,6 +930,7 @@ module ts {
|
||||
export interface Program extends ScriptReferenceHost {
|
||||
getSourceFiles(): SourceFile[];
|
||||
getCompilerHost(): CompilerHost;
|
||||
getEmitResolver(): EmitResolver;
|
||||
|
||||
// These will merge with the below diagnostics function in a followup checkin.
|
||||
getTypeCheckerDiagnostics(sourceFile?: SourceFile): Diagnostic[];
|
||||
@@ -947,11 +948,20 @@ module ts {
|
||||
//
|
||||
// If 'produceDiagnostics' is false, then any calls to get diagnostics from the TypeChecker
|
||||
// will throw an invalid operation exception.
|
||||
getTypeChecker(produceDiagnostics: boolean): TypeChecker;
|
||||
getTypeChecker(): TypeChecker;
|
||||
getCommonSourceDirectory(): string;
|
||||
|
||||
emitFiles(targetSourceFile?: SourceFile): EmitResult;
|
||||
isEmitBlocked(sourceFile?: SourceFile): boolean;
|
||||
|
||||
// For testing purposes only. Should not be used by any other consumers (including the
|
||||
// language service).
|
||||
/* @internal */ getDiagnosticsProducingTypeChecker(): TypeChecker;
|
||||
|
||||
/* @internal */ getNodeCount(): number;
|
||||
/* @internal */ getIdentifierCount(): number;
|
||||
/* @internal */ getSymbolCount(): number;
|
||||
/* @internal */ getTypeCount(): number;
|
||||
}
|
||||
|
||||
export interface SourceMapSpan {
|
||||
@@ -1000,7 +1010,6 @@ module ts {
|
||||
}
|
||||
|
||||
export interface TypeChecker {
|
||||
getEmitResolver(): EmitResolver;
|
||||
getTypeOfSymbolAtLocation(symbol: Symbol, node: Node): Type;
|
||||
getDeclaredTypeOfSymbol(symbol: Symbol): Type;
|
||||
getPropertiesOfType(type: Type): Symbol[];
|
||||
@@ -1033,6 +1042,7 @@ module ts {
|
||||
// Should not be called directly. Should only be accessed through the Program instance.
|
||||
/* @internal */ getDiagnostics(sourceFile?: SourceFile): Diagnostic[];
|
||||
/* @internal */ getGlobalDiagnostics(): Diagnostic[];
|
||||
/* @internal */ getEmitResolver(): EmitResolver;
|
||||
|
||||
/* @internal */ getNodeCount(): number;
|
||||
/* @internal */ getIdentifierCount(): number;
|
||||
|
||||
@@ -256,11 +256,40 @@ class CompilerBaselineRunner extends RunnerBase {
|
||||
it('Correct type baselines for ' + fileName, () => {
|
||||
// NEWTODO: Type baselines
|
||||
if (result.errors.length === 0) {
|
||||
Harness.Baseline.runBaseline('Correct expression types for ' + fileName, justName.replace(/\.ts/, '.types'), () => {
|
||||
// The full walker simulates the types that you would get from doing a full
|
||||
// compile. The pull walker simulates the types you get when you just do
|
||||
// a type query for a random node (like how the LS would do it). Most of the
|
||||
// time, these will be the same. However, occasionally, they can be different.
|
||||
// Specifically, when the compiler internally depends on symbol IDs to order
|
||||
// things, then we may see different results because symbols can be created in a
|
||||
// different order with 'pull' operations, and thus can produce slightly differing
|
||||
// output.
|
||||
//
|
||||
// For example, with a full type check, we may see a type outputed as: number | string
|
||||
// But with a pull type check, we may see it as: string | number
|
||||
//
|
||||
// These types are equivalent, but depend on what order the compiler observed
|
||||
// certain parts of the program.
|
||||
|
||||
var fullWalker = new TypeWriterWalker(program, /*fullTypeCheck:*/ true);
|
||||
var pullWalker = new TypeWriterWalker(program, /*fullTypeCheck:*/ false);
|
||||
|
||||
var fullTypes = generateTypes(fullWalker);
|
||||
var pullTypes = generateTypes(pullWalker);
|
||||
|
||||
if (fullTypes !== pullTypes) {
|
||||
Harness.Baseline.runBaseline('Correct full expression types for ' + fileName, justName.replace(/\.ts/, '.types'), () => fullTypes);
|
||||
Harness.Baseline.runBaseline('Correct pull expression types for ' + fileName, justName.replace(/\.ts/, '.types.pull'), () => pullTypes);
|
||||
}
|
||||
else {
|
||||
Harness.Baseline.runBaseline('Correct expression types for ' + fileName, justName.replace(/\.ts/, '.types'), () => fullTypes);
|
||||
}
|
||||
|
||||
function generateTypes(walker: TypeWriterWalker): string {
|
||||
var allFiles = toBeCompiled.concat(otherFiles).filter(file => !!program.getSourceFile(file.unitName));
|
||||
var typeLines: string[] = [];
|
||||
var typeMap: { [fileName: string]: { [lineNum: number]: string[]; } } = {};
|
||||
var walker = new TypeWriterWalker(program);
|
||||
|
||||
allFiles.forEach(file => {
|
||||
var codeLines = file.content.split('\n');
|
||||
walker.getTypes(file.unitName).forEach(result => {
|
||||
@@ -299,7 +328,7 @@ class CompilerBaselineRunner extends RunnerBase {
|
||||
});
|
||||
|
||||
return typeLines.join('');
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1081,8 +1081,6 @@ module Harness {
|
||||
(fn, contents, writeByteOrderMark) => fileOutputs.push({ fileName: fn, code: contents, writeByteOrderMark: writeByteOrderMark }),
|
||||
options.target, useCaseSensitiveFileNames, currentDirectory));
|
||||
|
||||
var checker = program.getTypeChecker(/*produceDiagnostics*/ true);
|
||||
|
||||
var isEmitBlocked = program.isEmitBlocked();
|
||||
|
||||
// only emit if there weren't parse errors
|
||||
@@ -1092,7 +1090,7 @@ module Harness {
|
||||
}
|
||||
|
||||
var errors: HarnessDiagnostic[] = [];
|
||||
program.getDiagnostics().concat(checker.getDiagnostics()).concat(emitResult ? emitResult.diagnostics : []).forEach(err => {
|
||||
program.getDiagnostics().concat(program.getTypeCheckerDiagnostics()).concat(emitResult ? emitResult.diagnostics : []).forEach(err => {
|
||||
// TODO: new compiler formats errors after this point to add . and newlines so we'll just do it manually for now
|
||||
errors.push(getMinimalDiagnostic(err));
|
||||
});
|
||||
|
||||
@@ -130,8 +130,7 @@ class ProjectRunner extends RunnerBase {
|
||||
var errors = program.getDiagnostics();
|
||||
var sourceMapData: ts.SourceMapData[] = null;
|
||||
if (!errors.length) {
|
||||
var checker = program.getTypeChecker(/*produceDiagnostics:*/ true);
|
||||
errors = checker.getDiagnostics();
|
||||
errors = program.getTypeCheckerDiagnostics();
|
||||
var emitResult = program.emitFiles();
|
||||
errors = ts.concatenate(errors, emitResult.diagnostics);
|
||||
sourceMapData = emitResult.sourceMaps;
|
||||
|
||||
@@ -12,10 +12,12 @@ class TypeWriterWalker {
|
||||
|
||||
private checker: ts.TypeChecker;
|
||||
|
||||
constructor(private program: ts.Program) {
|
||||
constructor(private program: ts.Program, fullTypeCheck: boolean) {
|
||||
// Consider getting both the diagnostics checker and the non-diagnostics checker to verify
|
||||
// they are consistent.
|
||||
this.checker = program.getTypeChecker(/*produceDiagnostics:*/ true);
|
||||
this.checker = fullTypeCheck
|
||||
? program.getDiagnosticsProducingTypeChecker()
|
||||
: program.getTypeChecker();
|
||||
}
|
||||
|
||||
public getTypes(fileName: string): TypeWriterResult[] {
|
||||
|
||||
@@ -2024,10 +2024,6 @@ module ts {
|
||||
return sourceFile;
|
||||
}
|
||||
|
||||
function getDiagnosticsProducingTypeChecker() {
|
||||
return program.getTypeChecker(/*produceDiagnostics:*/ true);
|
||||
}
|
||||
|
||||
function getRuleProvider(options: FormatCodeOptions) {
|
||||
// Ensure rules are initialized and up to date wrt to formatting options
|
||||
if (!ruleProvider) {
|
||||
@@ -2076,7 +2072,7 @@ module ts {
|
||||
}
|
||||
|
||||
program = newProgram;
|
||||
typeInfoResolver = program.getTypeChecker(/*produceDiagnostics*/ false);
|
||||
typeInfoResolver = program.getTypeChecker();
|
||||
|
||||
return;
|
||||
|
||||
@@ -2155,7 +2151,7 @@ module ts {
|
||||
*/
|
||||
function cleanupSemanticCache(): void {
|
||||
if (program) {
|
||||
typeInfoResolver = program.getTypeChecker(/*produceDiagnostics*/ false);
|
||||
typeInfoResolver = program.getTypeChecker();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4673,7 +4669,7 @@ module ts {
|
||||
var emitHost = createEmitHostFromProgram(program);
|
||||
emitHost.writeFile = writeFile;
|
||||
|
||||
var emitOutput = emitFiles(getDiagnosticsProducingTypeChecker().getEmitResolver(), emitHost, sourceFile);
|
||||
var emitOutput = emitFiles(program.getEmitResolver(), emitHost, sourceFile);
|
||||
|
||||
return {
|
||||
outputFiles,
|
||||
|
||||
Reference in New Issue
Block a user