Skip to content

Commit 96c3c90

Browse files
Rename typechecker parameter related to whether or not we produce diagnostics.
Comment what the flag means.
1 parent 4aa361d commit 96c3c90

8 files changed

Lines changed: 67 additions & 49 deletions

File tree

Jakefile

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ var compilerSources = [
3939
"binder.ts",
4040
"checker.ts",
4141
"emitter.ts",
42+
"program.ts",
4243
"commandLineParser.ts",
4344
"tsc.ts",
4445
"diagnosticInformationMap.generated.ts"
@@ -56,6 +57,7 @@ var servicesSources = [
5657
"binder.ts",
5758
"checker.ts",
5859
"emitter.ts",
60+
"program.ts",
5961
"diagnosticInformationMap.generated.ts"
6062
].map(function (f) {
6163
return path.join(compilerDirectory, f);

src/compiler/checker.ts

Lines changed: 37 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ module ts {
99
/// If fullTypeCheck === true, then the typechecker should do every possible check to produce all errors
1010
/// If fullTypeCheck === false, the typechecker can take shortcuts and skip checks that only produce errors.
1111
/// NOTE: checks that somehow affect decisions being made during typechecking should be executed in both cases.
12-
export function createTypeChecker(program: Program, fullTypeCheck: boolean): TypeChecker {
12+
export function createTypeChecker(program: Program, produceDiagnostics: boolean): TypeChecker {
1313
var Symbol = objectAllocator.getSymbolConstructor();
1414
var Type = objectAllocator.getTypeConstructor();
1515
var Signature = objectAllocator.getSignatureConstructor();
@@ -4168,7 +4168,7 @@ module ts {
41684168
}
41694169

41704170
function reportErrorsFromWidening(declaration: Declaration, type: Type) {
4171-
if (fullTypeCheck && compilerOptions.noImplicitAny && type.flags & TypeFlags.Unwidened) {
4171+
if (produceDiagnostics && compilerOptions.noImplicitAny && type.flags & TypeFlags.Unwidened) {
41724172
// Report implicit any error within type if possible, otherwise report error on declaration
41734173
if (!reportWideningErrorsInType(type)) {
41744174
reportImplicitAnyError(declaration, type);
@@ -5957,7 +5957,7 @@ module ts {
59575957
// Pick the first candidate that matches the arity. This way we can get a contextual type for cases like:
59585958
// declare function f(a: { xa: number; xb: number; });
59595959
// f({ |
5960-
if (!fullTypeCheck) {
5960+
if (!produceDiagnostics) {
59615961
for (var i = 0, n = candidates.length; i < n; i++) {
59625962
if (hasCorrectArity(node, args, candidates[i])) {
59635963
return candidates[i];
@@ -6254,7 +6254,7 @@ module ts {
62546254
function checkTypeAssertion(node: TypeAssertion): Type {
62556255
var exprType = checkExpression(node.expression);
62566256
var targetType = getTypeFromTypeNode(node.type);
6257-
if (fullTypeCheck && targetType !== unknownType) {
6257+
if (produceDiagnostics && targetType !== unknownType) {
62586258
var widenedType = getWidenedType(exprType);
62596259
if (!(isTypeAssignableTo(targetType, widenedType))) {
62606260
checkTypeAssignableTo(exprType, targetType, node, Diagnostics.Neither_type_0_nor_type_1_is_assignable_to_the_other);
@@ -6340,7 +6340,7 @@ module ts {
63406340
// must have at least one return statement somewhere in its body.
63416341
// An exception to this rule is if the function implementation consists of a single 'throw' statement.
63426342
function checkIfNonVoidFunctionHasReturnExpressionsOrSingleThrowStatment(func: FunctionLikeDeclaration, returnType: Type): void {
6343-
if (!fullTypeCheck) {
6343+
if (!produceDiagnostics) {
63446344
return;
63456345
}
63466346

@@ -6406,7 +6406,7 @@ module ts {
64066406
}
64076407
}
64086408

6409-
if (fullTypeCheck && node.kind !== SyntaxKind.MethodDeclaration && node.kind !== SyntaxKind.MethodSignature) {
6409+
if (produceDiagnostics && node.kind !== SyntaxKind.MethodDeclaration && node.kind !== SyntaxKind.MethodSignature) {
64106410
checkCollisionWithCapturedSuperVariable(node, (<FunctionExpression>node).name);
64116411
checkCollisionWithCapturedThisVariable(node,(<FunctionExpression>node).name);
64126412
}
@@ -6813,7 +6813,7 @@ module ts {
68136813
}
68146814

68156815
function checkAssignmentOperator(valueType: Type): void {
6816-
if (fullTypeCheck && operator >= SyntaxKind.FirstAssignment && operator <= SyntaxKind.LastAssignment) {
6816+
if (produceDiagnostics && operator >= SyntaxKind.FirstAssignment && operator <= SyntaxKind.LastAssignment) {
68176817
// TypeScript 1.0 spec (April 2014): 4.17
68186818
// An assignment of the form
68196819
// VarExpr = ValueExpr
@@ -6996,7 +6996,7 @@ module ts {
69966996

69976997
function checkTypeParameter(node: TypeParameterDeclaration) {
69986998
checkSourceElement(node.constraint);
6999-
if (fullTypeCheck) {
6999+
if (produceDiagnostics) {
70007000
checkTypeParameterHasIllegalReferencesInConstraint(node);
70017001
checkTypeNameIsReserved(node.name, Diagnostics.Type_parameter_name_cannot_be_0);
70027002
}
@@ -7025,7 +7025,7 @@ module ts {
70257025
if (node.type) {
70267026
checkSourceElement(node.type);
70277027
}
7028-
if (fullTypeCheck) {
7028+
if (produceDiagnostics) {
70297029
checkCollisionWithArgumentsInGeneratedCode(node);
70307030
if (compilerOptions.noImplicitAny && !node.type) {
70317031
switch (node.kind) {
@@ -7109,7 +7109,7 @@ module ts {
71097109
return;
71107110
}
71117111

7112-
if (!fullTypeCheck) {
7112+
if (!produceDiagnostics) {
71137113
return;
71147114
}
71157115

@@ -7177,7 +7177,7 @@ module ts {
71777177
}
71787178

71797179
function checkAccessorDeclaration(node: AccessorDeclaration) {
7180-
if (fullTypeCheck) {
7180+
if (produceDiagnostics) {
71817181
if (node.kind === SyntaxKind.GetAccessor) {
71827182
if (!isInAmbientContext(node) && node.body && !(bodyContainsAReturnStatement(<Block>node.body) || bodyContainsSingleThrowStatement(<Block>node.body))) {
71837183
error(node.name, Diagnostics.A_get_accessor_must_return_a_value_or_consist_of_a_single_throw_statement);
@@ -7220,7 +7220,7 @@ module ts {
72207220
for (var i = 0; i < len; i++) {
72217221
checkSourceElement(node.typeArguments[i]);
72227222
var constraint = getConstraintOfTypeParameter((<TypeReference>type).target.typeParameters[i]);
7223-
if (fullTypeCheck && constraint) {
7223+
if (produceDiagnostics && constraint) {
72247224
var typeArgument = (<TypeReference>type).typeArguments[i];
72257225
checkTypeAssignableTo(typeArgument, constraint, node, Diagnostics.Type_0_does_not_satisfy_the_constraint_1);
72267226
}
@@ -7234,7 +7234,7 @@ module ts {
72347234

72357235
function checkTypeLiteral(node: TypeLiteralNode) {
72367236
forEach(node.members, checkSourceElement);
7237-
if (fullTypeCheck) {
7237+
if (produceDiagnostics) {
72387238
var type = getTypeFromTypeLiteralOrFunctionOrConstructorTypeNode(node);
72397239
checkIndexConstraints(type);
72407240
checkTypeForDuplicateIndexSignatures(node);
@@ -7258,7 +7258,7 @@ module ts {
72587258
}
72597259

72607260
function checkSpecializedSignatureDeclaration(signatureDeclarationNode: SignatureDeclaration): void {
7261-
if (!fullTypeCheck) {
7261+
if (!produceDiagnostics) {
72627262
return;
72637263
}
72647264
var signature = getSignatureFromDeclaration(signatureDeclarationNode);
@@ -7314,7 +7314,7 @@ module ts {
73147314
}
73157315

73167316
function checkFunctionOrConstructorSymbol(symbol: Symbol): void {
7317-
if (!fullTypeCheck) {
7317+
if (!produceDiagnostics) {
73187318
return;
73197319
}
73207320

@@ -7524,7 +7524,7 @@ module ts {
75247524
}
75257525

75267526
function checkExportsOnMergedDeclarations(node: Node): void {
7527-
if (!fullTypeCheck) {
7527+
if (!produceDiagnostics) {
75287528
return;
75297529
}
75307530

@@ -7599,7 +7599,7 @@ module ts {
75997599

76007600
function checkFunctionDeclaration(node: FunctionDeclaration): void {
76017601
checkFunctionLikeDeclaration(node);
7602-
if (fullTypeCheck) {
7602+
if (produceDiagnostics) {
76037603
checkCollisionWithCapturedSuperVariable(node, node.name);
76047604
checkCollisionWithCapturedThisVariable(node, node.name);
76057605
checkCollisionWithRequireExportsInGeneratedCode(node, node.name);
@@ -7999,7 +7999,7 @@ module ts {
79997999
function checkSwitchStatement(node: SwitchStatement) {
80008000
var expressionType = checkExpression(node.expression);
80018001
forEach(node.clauses, clause => {
8002-
if (fullTypeCheck && clause.kind === SyntaxKind.CaseClause) {
8002+
if (produceDiagnostics && clause.kind === SyntaxKind.CaseClause) {
80038003
var caseClause = <CaseClause>clause;
80048004
// TypeScript 1.0 spec (April 2014):5.9
80058005
// 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 {
81198119
var node = typeParameterDeclarations[i];
81208120
checkTypeParameter(node);
81218121

8122-
if (fullTypeCheck) {
8122+
if (produceDiagnostics) {
81238123
for (var j = 0; j < i; j++) {
81248124
if (typeParameterDeclarations[j].symbol === node.symbol) {
81258125
error(node.name, Diagnostics.Duplicate_identifier_0, declarationNameToString(node.name));
@@ -8145,7 +8145,7 @@ module ts {
81458145
checkTypeReference(baseTypeNode);
81468146
}
81478147
if (type.baseTypes.length) {
8148-
if (fullTypeCheck) {
8148+
if (produceDiagnostics) {
81498149
var baseType = type.baseTypes[0];
81508150
checkTypeAssignableTo(type, baseType, node.name, Diagnostics.Class_0_incorrectly_extends_base_class_1);
81518151
var staticBaseType = getTypeOfSymbol(baseType.symbol);
@@ -8166,7 +8166,7 @@ module ts {
81668166
if (implementedTypeNodes) {
81678167
forEach(implementedTypeNodes, typeRefNode => {
81688168
checkTypeReference(typeRefNode);
8169-
if (fullTypeCheck) {
8169+
if (produceDiagnostics) {
81708170
var t = getTypeFromTypeReferenceNode(typeRefNode);
81718171
if (t !== unknownType) {
81728172
var declaredType = (t.flags & TypeFlags.Reference) ? (<TypeReference>t).target : t;
@@ -8182,7 +8182,7 @@ module ts {
81828182
}
81838183

81848184
forEach(node.members, checkSourceElement);
8185-
if (fullTypeCheck) {
8185+
if (produceDiagnostics) {
81868186
checkIndexConstraints(type);
81878187
checkTypeForDuplicateIndexSignatures(node);
81888188
}
@@ -8335,7 +8335,7 @@ module ts {
83358335

83368336
function checkInterfaceDeclaration(node: InterfaceDeclaration) {
83378337
checkTypeParameters(node.typeParameters);
8338-
if (fullTypeCheck) {
8338+
if (produceDiagnostics) {
83398339
checkTypeNameIsReserved(node.name, Diagnostics.Interface_name_cannot_be_0);
83408340

83418341
checkExportsOnMergedDeclarations(node);
@@ -8362,7 +8362,7 @@ module ts {
83628362
forEach(getInterfaceBaseTypeNodes(node), checkTypeReference);
83638363
forEach(node.members, checkSourceElement);
83648364

8365-
if (fullTypeCheck) {
8365+
if (produceDiagnostics) {
83668366
checkTypeForDuplicateIndexSignatures(node);
83678367
}
83688368
}
@@ -8531,7 +8531,7 @@ module ts {
85318531
}
85328532

85338533
function checkEnumDeclaration(node: EnumDeclaration) {
8534-
if (!fullTypeCheck) {
8534+
if (!produceDiagnostics) {
85358535
return;
85368536
}
85378537

@@ -8598,7 +8598,7 @@ module ts {
85988598
}
85998599

86008600
function checkModuleDeclaration(node: ModuleDeclaration) {
8601-
if (fullTypeCheck) {
8601+
if (produceDiagnostics) {
86028602
checkCollisionWithCapturedThisVariable(node, node.name);
86038603
checkCollisionWithRequireExportsInGeneratedCode(node, node.name);
86048604
checkExportsOnMergedDeclarations(node);
@@ -8919,7 +8919,7 @@ module ts {
89198919
}
89208920

89218921
function getSortedDiagnostics(): Diagnostic[]{
8922-
Debug.assert(fullTypeCheck, "diagnostics are available only in the full typecheck mode");
8922+
Debug.assert(produceDiagnostics, "diagnostics are available only in the full typecheck mode");
89238923

89248924
if (diagnosticsModified) {
89258925
diagnostics.sort(compareDiagnostics);
@@ -8929,7 +8929,8 @@ module ts {
89298929
return diagnostics;
89308930
}
89318931

8932-
function getDiagnostics(sourceFile?: SourceFile): Diagnostic[]{
8932+
function getDiagnostics(sourceFile?: SourceFile): Diagnostic[] {
8933+
throwIfNonDiagnosticsProducing();
89338934
if (sourceFile) {
89348935
checkSourceFile(sourceFile);
89358936
return filter(getSortedDiagnostics(), d => d.file === sourceFile);
@@ -8938,10 +8939,17 @@ module ts {
89388939
return getSortedDiagnostics();
89398940
}
89408941

8941-
function getGlobalDiagnostics(): Diagnostic[] {
8942+
function getGlobalDiagnostics(): Diagnostic[]{
8943+
throwIfNonDiagnosticsProducing();
89428944
return filter(getSortedDiagnostics(), d => !d.file);
89438945
}
89448946

8947+
function throwIfNonDiagnosticsProducing() {
8948+
if (!produceDiagnostics) {
8949+
throw new Error("Trying to get diagnostics from a type checker that does not produce them.");
8950+
}
8951+
}
8952+
89458953
// Language service support
89468954

89478955
function isInsideWithStatementBody(node: Node): boolean {

src/compiler/program.ts

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -89,15 +89,15 @@ module ts {
8989
verifyCompilerOptions();
9090
errors.sort(compareDiagnostics);
9191

92-
var fullTypeChecker: TypeChecker;
93-
var nonFullTypeChecker: TypeChecker;
92+
var diagnosticsProducingTypeChecker: TypeChecker;
93+
var noDiagnosticsTypeChecker: TypeChecker;
9494

95-
function getTypeChecker(full: boolean) {
96-
if (full) {
97-
return fullTypeChecker || (fullTypeChecker = createTypeChecker(program, full));
95+
function getTypeChecker(produceDiagnostics: boolean) {
96+
if (produceDiagnostics) {
97+
return diagnosticsProducingTypeChecker || (diagnosticsProducingTypeChecker = createTypeChecker(program, produceDiagnostics));
9898
}
9999
else {
100-
return nonFullTypeChecker || (nonFullTypeChecker = createTypeChecker(program, full));
100+
return noDiagnosticsTypeChecker || (noDiagnosticsTypeChecker = createTypeChecker(program, produceDiagnostics));
101101
}
102102
}
103103

@@ -116,14 +116,14 @@ module ts {
116116
return program;
117117

118118
function getDeclarationDiagnostics(targetSourceFile: SourceFile): Diagnostic[]{
119-
var fullTypeChecker = getTypeChecker(/*full:*/ true);
119+
var fullTypeChecker = getTypeChecker(/*produceDiagnostics:*/true);
120120
fullTypeChecker.getDiagnostics(targetSourceFile);
121121
var resolver = fullTypeChecker.getEmitResolver();
122122
return ts.getDeclarationDiagnostics(program, resolver, targetSourceFile);
123123
}
124124

125125
function invokeEmitter(targetSourceFile?: SourceFile) {
126-
var resolver = getTypeChecker(/*full:*/ true).getEmitResolver();
126+
var resolver = getTypeChecker(/*produceDiagnostics:*/true).getEmitResolver();
127127
return emitFiles(resolver, targetSourceFile);
128128
}
129129

src/compiler/types.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -917,7 +917,15 @@ module ts {
917917
getGlobalDiagnostics(): Diagnostic[];
918918
getDeclarationDiagnostics(sourceFile: SourceFile): Diagnostic[];
919919

920-
getTypeChecker(fullTypeCheckMode: boolean): TypeChecker;
920+
// Gets a type checker that can be used to semantically analyze source fils in the program.
921+
// The 'produceDiagnostics' flag determines if the checker will produce diagnostics while
922+
// analyzing the code. It can be set to 'false' to make many type checking operaitons
923+
// faster. With this flag set, the checker can avoid codepaths only necessary to produce
924+
// diagnostics, but not necessary to answer semantic questions about the code.
925+
//
926+
// If 'produceDiagnostics' is false, then any calls to get diagnostics from the TypeChecker
927+
// will throw an invalid operation exception.
928+
getTypeChecker(produceDiagnostics: boolean): TypeChecker;
921929
getCommonSourceDirectory(): string;
922930
emitFiles(targetSourceFile?: SourceFile): EmitResult;
923931
}

src/harness/fourslash.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2196,7 +2196,7 @@ module FourSlash {
21962196
ts.sys.useCaseSensitiveFileNames);
21972197
// TODO (drosen): We need to enforce checking on these tests.
21982198
var program = ts.createProgram([Harness.Compiler.fourslashFilename, fileName], { out: "fourslashTestOutput.js", noResolve: true, target: ts.ScriptTarget.ES3 }, host);
2199-
var checker = ts.createTypeChecker(program, /*fullTypeCheckMode*/ true);
2199+
var checker = ts.createTypeChecker(program, /*produceDiagnostics*/ true);
22002200

22012201
var errors = program.getDiagnostics().concat(checker.getDiagnostics());
22022202
if (errors.length > 0) {

src/harness/harness.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1044,7 +1044,7 @@ module Harness {
10441044
options.target,
10451045
useCaseSensitiveFileNames));
10461046

1047-
var checker = program.getTypeChecker(/*fullTypeCheckMode*/ true);
1047+
var checker = program.getTypeChecker(/*produceDiagnostics*/ true);
10481048

10491049
var isEmitBlocked = checker.isEmitBlocked();
10501050

src/harness/projectsRunner.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,7 @@ class ProjectRunner extends RunnerBase {
130130
var errors = program.getDiagnostics();
131131
var sourceMapData: ts.SourceMapData[] = null;
132132
if (!errors.length) {
133-
var checker = program.getTypeChecker(/*fullTypeCheck*/ true);
133+
var checker = program.getTypeChecker(/*produceDiagnostics:*/ true);
134134
errors = checker.getDiagnostics();
135135
var emitResult = program.emitFiles();
136136
errors = ts.concatenate(errors, emitResult.diagnostics);

0 commit comments

Comments
 (0)