Rename typechecker parameter related to whether or not we produce diagnostics.

Comment what the flag means.
This commit is contained in:
Cyrus Najmabadi
2014-12-16 13:30:34 -08:00
parent 4aa361d4bf
commit 96c3c90d9a
8 changed files with 67 additions and 49 deletions
+2
View File
@@ -39,6 +39,7 @@ var compilerSources = [
"binder.ts",
"checker.ts",
"emitter.ts",
"program.ts",
"commandLineParser.ts",
"tsc.ts",
"diagnosticInformationMap.generated.ts"
@@ -56,6 +57,7 @@ var servicesSources = [
"binder.ts",
"checker.ts",
"emitter.ts",
"program.ts",
"diagnosticInformationMap.generated.ts"
].map(function (f) {
return path.join(compilerDirectory, f);
+37 -29
View File
@@ -9,7 +9,7 @@ module ts {
/// If fullTypeCheck === true, then the typechecker should do every possible check to produce all errors
/// If fullTypeCheck === false, the typechecker can take shortcuts and skip checks that only produce errors.
/// NOTE: checks that somehow affect decisions being made during typechecking should be executed in both cases.
export function createTypeChecker(program: Program, fullTypeCheck: boolean): TypeChecker {
export function createTypeChecker(program: Program, produceDiagnostics: boolean): TypeChecker {
var Symbol = objectAllocator.getSymbolConstructor();
var Type = objectAllocator.getTypeConstructor();
var Signature = objectAllocator.getSignatureConstructor();
@@ -4168,7 +4168,7 @@ module ts {
}
function reportErrorsFromWidening(declaration: Declaration, type: Type) {
if (fullTypeCheck && compilerOptions.noImplicitAny && type.flags & TypeFlags.Unwidened) {
if (produceDiagnostics && compilerOptions.noImplicitAny && type.flags & TypeFlags.Unwidened) {
// Report implicit any error within type if possible, otherwise report error on declaration
if (!reportWideningErrorsInType(type)) {
reportImplicitAnyError(declaration, type);
@@ -5957,7 +5957,7 @@ module ts {
// Pick the first candidate that matches the arity. This way we can get a contextual type for cases like:
// declare function f(a: { xa: number; xb: number; });
// f({ |
if (!fullTypeCheck) {
if (!produceDiagnostics) {
for (var i = 0, n = candidates.length; i < n; i++) {
if (hasCorrectArity(node, args, candidates[i])) {
return candidates[i];
@@ -6254,7 +6254,7 @@ module ts {
function checkTypeAssertion(node: TypeAssertion): Type {
var exprType = checkExpression(node.expression);
var targetType = getTypeFromTypeNode(node.type);
if (fullTypeCheck && targetType !== unknownType) {
if (produceDiagnostics && targetType !== unknownType) {
var widenedType = getWidenedType(exprType);
if (!(isTypeAssignableTo(targetType, widenedType))) {
checkTypeAssignableTo(exprType, targetType, node, Diagnostics.Neither_type_0_nor_type_1_is_assignable_to_the_other);
@@ -6340,7 +6340,7 @@ module ts {
// must have at least one return statement somewhere in its body.
// An exception to this rule is if the function implementation consists of a single 'throw' statement.
function checkIfNonVoidFunctionHasReturnExpressionsOrSingleThrowStatment(func: FunctionLikeDeclaration, returnType: Type): void {
if (!fullTypeCheck) {
if (!produceDiagnostics) {
return;
}
@@ -6406,7 +6406,7 @@ module ts {
}
}
if (fullTypeCheck && node.kind !== SyntaxKind.MethodDeclaration && node.kind !== SyntaxKind.MethodSignature) {
if (produceDiagnostics && node.kind !== SyntaxKind.MethodDeclaration && node.kind !== SyntaxKind.MethodSignature) {
checkCollisionWithCapturedSuperVariable(node, (<FunctionExpression>node).name);
checkCollisionWithCapturedThisVariable(node,(<FunctionExpression>node).name);
}
@@ -6813,7 +6813,7 @@ module ts {
}
function checkAssignmentOperator(valueType: Type): void {
if (fullTypeCheck && operator >= SyntaxKind.FirstAssignment && operator <= SyntaxKind.LastAssignment) {
if (produceDiagnostics && operator >= SyntaxKind.FirstAssignment && operator <= SyntaxKind.LastAssignment) {
// TypeScript 1.0 spec (April 2014): 4.17
// An assignment of the form
// VarExpr = ValueExpr
@@ -6996,7 +6996,7 @@ module ts {
function checkTypeParameter(node: TypeParameterDeclaration) {
checkSourceElement(node.constraint);
if (fullTypeCheck) {
if (produceDiagnostics) {
checkTypeParameterHasIllegalReferencesInConstraint(node);
checkTypeNameIsReserved(node.name, Diagnostics.Type_parameter_name_cannot_be_0);
}
@@ -7025,7 +7025,7 @@ module ts {
if (node.type) {
checkSourceElement(node.type);
}
if (fullTypeCheck) {
if (produceDiagnostics) {
checkCollisionWithArgumentsInGeneratedCode(node);
if (compilerOptions.noImplicitAny && !node.type) {
switch (node.kind) {
@@ -7109,7 +7109,7 @@ module ts {
return;
}
if (!fullTypeCheck) {
if (!produceDiagnostics) {
return;
}
@@ -7177,7 +7177,7 @@ module ts {
}
function checkAccessorDeclaration(node: AccessorDeclaration) {
if (fullTypeCheck) {
if (produceDiagnostics) {
if (node.kind === SyntaxKind.GetAccessor) {
if (!isInAmbientContext(node) && node.body && !(bodyContainsAReturnStatement(<Block>node.body) || bodyContainsSingleThrowStatement(<Block>node.body))) {
error(node.name, Diagnostics.A_get_accessor_must_return_a_value_or_consist_of_a_single_throw_statement);
@@ -7220,7 +7220,7 @@ module ts {
for (var i = 0; i < len; i++) {
checkSourceElement(node.typeArguments[i]);
var constraint = getConstraintOfTypeParameter((<TypeReference>type).target.typeParameters[i]);
if (fullTypeCheck && constraint) {
if (produceDiagnostics && constraint) {
var typeArgument = (<TypeReference>type).typeArguments[i];
checkTypeAssignableTo(typeArgument, constraint, node, Diagnostics.Type_0_does_not_satisfy_the_constraint_1);
}
@@ -7234,7 +7234,7 @@ module ts {
function checkTypeLiteral(node: TypeLiteralNode) {
forEach(node.members, checkSourceElement);
if (fullTypeCheck) {
if (produceDiagnostics) {
var type = getTypeFromTypeLiteralOrFunctionOrConstructorTypeNode(node);
checkIndexConstraints(type);
checkTypeForDuplicateIndexSignatures(node);
@@ -7258,7 +7258,7 @@ module ts {
}
function checkSpecializedSignatureDeclaration(signatureDeclarationNode: SignatureDeclaration): void {
if (!fullTypeCheck) {
if (!produceDiagnostics) {
return;
}
var signature = getSignatureFromDeclaration(signatureDeclarationNode);
@@ -7314,7 +7314,7 @@ module ts {
}
function checkFunctionOrConstructorSymbol(symbol: Symbol): void {
if (!fullTypeCheck) {
if (!produceDiagnostics) {
return;
}
@@ -7524,7 +7524,7 @@ module ts {
}
function checkExportsOnMergedDeclarations(node: Node): void {
if (!fullTypeCheck) {
if (!produceDiagnostics) {
return;
}
@@ -7599,7 +7599,7 @@ module ts {
function checkFunctionDeclaration(node: FunctionDeclaration): void {
checkFunctionLikeDeclaration(node);
if (fullTypeCheck) {
if (produceDiagnostics) {
checkCollisionWithCapturedSuperVariable(node, node.name);
checkCollisionWithCapturedThisVariable(node, node.name);
checkCollisionWithRequireExportsInGeneratedCode(node, node.name);
@@ -7999,7 +7999,7 @@ module ts {
function checkSwitchStatement(node: SwitchStatement) {
var expressionType = checkExpression(node.expression);
forEach(node.clauses, clause => {
if (fullTypeCheck && clause.kind === SyntaxKind.CaseClause) {
if (produceDiagnostics && clause.kind === SyntaxKind.CaseClause) {
var caseClause = <CaseClause>clause;
// TypeScript 1.0 spec (April 2014):5.9
// In a 'switch' statement, each 'case' expression must be of a type that is assignable to or from the type of the 'switch' expression.
@@ -8119,7 +8119,7 @@ module ts {
var node = typeParameterDeclarations[i];
checkTypeParameter(node);
if (fullTypeCheck) {
if (produceDiagnostics) {
for (var j = 0; j < i; j++) {
if (typeParameterDeclarations[j].symbol === node.symbol) {
error(node.name, Diagnostics.Duplicate_identifier_0, declarationNameToString(node.name));
@@ -8145,7 +8145,7 @@ module ts {
checkTypeReference(baseTypeNode);
}
if (type.baseTypes.length) {
if (fullTypeCheck) {
if (produceDiagnostics) {
var baseType = type.baseTypes[0];
checkTypeAssignableTo(type, baseType, node.name, Diagnostics.Class_0_incorrectly_extends_base_class_1);
var staticBaseType = getTypeOfSymbol(baseType.symbol);
@@ -8166,7 +8166,7 @@ module ts {
if (implementedTypeNodes) {
forEach(implementedTypeNodes, typeRefNode => {
checkTypeReference(typeRefNode);
if (fullTypeCheck) {
if (produceDiagnostics) {
var t = getTypeFromTypeReferenceNode(typeRefNode);
if (t !== unknownType) {
var declaredType = (t.flags & TypeFlags.Reference) ? (<TypeReference>t).target : t;
@@ -8182,7 +8182,7 @@ module ts {
}
forEach(node.members, checkSourceElement);
if (fullTypeCheck) {
if (produceDiagnostics) {
checkIndexConstraints(type);
checkTypeForDuplicateIndexSignatures(node);
}
@@ -8335,7 +8335,7 @@ module ts {
function checkInterfaceDeclaration(node: InterfaceDeclaration) {
checkTypeParameters(node.typeParameters);
if (fullTypeCheck) {
if (produceDiagnostics) {
checkTypeNameIsReserved(node.name, Diagnostics.Interface_name_cannot_be_0);
checkExportsOnMergedDeclarations(node);
@@ -8362,7 +8362,7 @@ module ts {
forEach(getInterfaceBaseTypeNodes(node), checkTypeReference);
forEach(node.members, checkSourceElement);
if (fullTypeCheck) {
if (produceDiagnostics) {
checkTypeForDuplicateIndexSignatures(node);
}
}
@@ -8531,7 +8531,7 @@ module ts {
}
function checkEnumDeclaration(node: EnumDeclaration) {
if (!fullTypeCheck) {
if (!produceDiagnostics) {
return;
}
@@ -8598,7 +8598,7 @@ module ts {
}
function checkModuleDeclaration(node: ModuleDeclaration) {
if (fullTypeCheck) {
if (produceDiagnostics) {
checkCollisionWithCapturedThisVariable(node, node.name);
checkCollisionWithRequireExportsInGeneratedCode(node, node.name);
checkExportsOnMergedDeclarations(node);
@@ -8919,7 +8919,7 @@ module ts {
}
function getSortedDiagnostics(): Diagnostic[]{
Debug.assert(fullTypeCheck, "diagnostics are available only in the full typecheck mode");
Debug.assert(produceDiagnostics, "diagnostics are available only in the full typecheck mode");
if (diagnosticsModified) {
diagnostics.sort(compareDiagnostics);
@@ -8929,7 +8929,8 @@ module ts {
return diagnostics;
}
function getDiagnostics(sourceFile?: SourceFile): Diagnostic[]{
function getDiagnostics(sourceFile?: SourceFile): Diagnostic[] {
throwIfNonDiagnosticsProducing();
if (sourceFile) {
checkSourceFile(sourceFile);
return filter(getSortedDiagnostics(), d => d.file === sourceFile);
@@ -8938,10 +8939,17 @@ module ts {
return getSortedDiagnostics();
}
function getGlobalDiagnostics(): Diagnostic[] {
function getGlobalDiagnostics(): Diagnostic[]{
throwIfNonDiagnosticsProducing();
return filter(getSortedDiagnostics(), d => !d.file);
}
function throwIfNonDiagnosticsProducing() {
if (!produceDiagnostics) {
throw new Error("Trying to get diagnostics from a type checker that does not produce them.");
}
}
// Language service support
function isInsideWithStatementBody(node: Node): boolean {
+8 -8
View File
@@ -89,15 +89,15 @@ module ts {
verifyCompilerOptions();
errors.sort(compareDiagnostics);
var fullTypeChecker: TypeChecker;
var nonFullTypeChecker: TypeChecker;
var diagnosticsProducingTypeChecker: TypeChecker;
var noDiagnosticsTypeChecker: TypeChecker;
function getTypeChecker(full: boolean) {
if (full) {
return fullTypeChecker || (fullTypeChecker = createTypeChecker(program, full));
function getTypeChecker(produceDiagnostics: boolean) {
if (produceDiagnostics) {
return diagnosticsProducingTypeChecker || (diagnosticsProducingTypeChecker = createTypeChecker(program, produceDiagnostics));
}
else {
return nonFullTypeChecker || (nonFullTypeChecker = createTypeChecker(program, full));
return noDiagnosticsTypeChecker || (noDiagnosticsTypeChecker = createTypeChecker(program, produceDiagnostics));
}
}
@@ -116,14 +116,14 @@ module ts {
return program;
function getDeclarationDiagnostics(targetSourceFile: SourceFile): Diagnostic[]{
var fullTypeChecker = getTypeChecker(/*full:*/ true);
var fullTypeChecker = getTypeChecker(/*produceDiagnostics:*/true);
fullTypeChecker.getDiagnostics(targetSourceFile);
var resolver = fullTypeChecker.getEmitResolver();
return ts.getDeclarationDiagnostics(program, resolver, targetSourceFile);
}
function invokeEmitter(targetSourceFile?: SourceFile) {
var resolver = getTypeChecker(/*full:*/ true).getEmitResolver();
var resolver = getTypeChecker(/*produceDiagnostics:*/true).getEmitResolver();
return emitFiles(resolver, targetSourceFile);
}
+9 -1
View File
@@ -917,7 +917,15 @@ module ts {
getGlobalDiagnostics(): Diagnostic[];
getDeclarationDiagnostics(sourceFile: SourceFile): Diagnostic[];
getTypeChecker(fullTypeCheckMode: boolean): TypeChecker;
// Gets a type checker that can be used to semantically analyze source fils in the program.
// The 'produceDiagnostics' flag determines if the checker will produce diagnostics while
// analyzing the code. It can be set to 'false' to make many type checking operaitons
// faster. With this flag set, the checker can avoid codepaths only necessary to produce
// diagnostics, but not necessary to answer semantic questions about the code.
//
// If 'produceDiagnostics' is false, then any calls to get diagnostics from the TypeChecker
// will throw an invalid operation exception.
getTypeChecker(produceDiagnostics: boolean): TypeChecker;
getCommonSourceDirectory(): string;
emitFiles(targetSourceFile?: SourceFile): EmitResult;
}
+1 -1
View File
@@ -2196,7 +2196,7 @@ module FourSlash {
ts.sys.useCaseSensitiveFileNames);
// TODO (drosen): We need to enforce checking on these tests.
var program = ts.createProgram([Harness.Compiler.fourslashFilename, fileName], { out: "fourslashTestOutput.js", noResolve: true, target: ts.ScriptTarget.ES3 }, host);
var checker = ts.createTypeChecker(program, /*fullTypeCheckMode*/ true);
var checker = ts.createTypeChecker(program, /*produceDiagnostics*/ true);
var errors = program.getDiagnostics().concat(checker.getDiagnostics());
if (errors.length > 0) {
+1 -1
View File
@@ -1044,7 +1044,7 @@ module Harness {
options.target,
useCaseSensitiveFileNames));
var checker = program.getTypeChecker(/*fullTypeCheckMode*/ true);
var checker = program.getTypeChecker(/*produceDiagnostics*/ true);
var isEmitBlocked = checker.isEmitBlocked();
+1 -1
View File
@@ -130,7 +130,7 @@ class ProjectRunner extends RunnerBase {
var errors = program.getDiagnostics();
var sourceMapData: ts.SourceMapData[] = null;
if (!errors.length) {
var checker = program.getTypeChecker(/*fullTypeCheck*/ true);
var checker = program.getTypeChecker(/*produceDiagnostics:*/ true);
errors = checker.getDiagnostics();
var emitResult = program.emitFiles();
errors = ts.concatenate(errors, emitResult.diagnostics);
+8 -8
View File
@@ -2217,7 +2217,7 @@ module ts {
// the sole purpose of this checker is to return semantic diagnostics
// creation is deferred - use getFullTypeCheckChecker to get instance
var fullTypeCheckChecker_doNotAccessDirectly: TypeChecker;
var diagnosticsProducingTypeChecker_doNotAccessDirectly: TypeChecker;
var useCaseSensitivefilenames = false;
var sourceFilesByName: Map<SourceFile> = {};
@@ -2239,8 +2239,8 @@ module ts {
return lookUp(sourceFilesByName, getCanonicalFileName(filename));
}
function getFullTypeCheckChecker() {
return fullTypeCheckChecker_doNotAccessDirectly || (fullTypeCheckChecker_doNotAccessDirectly = program.getTypeChecker(/*fullTypeCheck*/ true));
function getDiagnosticsProducingTypeChecker() {
return diagnosticsProducingTypeChecker_doNotAccessDirectly || (diagnosticsProducingTypeChecker_doNotAccessDirectly = program.getTypeChecker(/*produceDiagnostics:*/ true));
}
function getRuleProvider(options: FormatCodeOptions) {
@@ -2380,8 +2380,8 @@ module ts {
// Now create a new compiler
program = createProgram(hostfilenames, compilationSettings, createCompilerHost());
typeInfoResolver = program.getTypeChecker(/*fullTypeCheckMode*/ false);
fullTypeCheckChecker_doNotAccessDirectly = undefined;
typeInfoResolver = program.getTypeChecker(/*produceDiagnostics*/ false);
diagnosticsProducingTypeChecker_doNotAccessDirectly = undefined;
}
/**
@@ -2391,8 +2391,8 @@ module ts {
*/
function cleanupSemanticCache(): void {
if (program) {
typeInfoResolver = program.getTypeChecker(/*fullTypeCheckMode*/ false);
fullTypeCheckChecker_doNotAccessDirectly = undefined;
typeInfoResolver = program.getTypeChecker(/*produceDiagnostics*/ false);
diagnosticsProducingTypeChecker_doNotAccessDirectly = undefined;
}
}
@@ -2421,7 +2421,7 @@ module ts {
filename = normalizeSlashes(filename)
var compilerOptions = program.getCompilerOptions();
var checker = getFullTypeCheckChecker();
var checker = getDiagnosticsProducingTypeChecker();
var targetSourceFile = getSourceFile(filename);
// Only perform the action per file regardless of '-out' flag as LanguageServiceHost is expected to call this function per file.