diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index a4f690137d5..ec681318806 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -37,7 +37,9 @@ module ts { var emptyArray: any[] = []; var emptySymbols: SymbolTable = {}; - + + var compilerOptions = program.getCompilerOptions(); + var checker: TypeChecker = { getProgram: () => program, getDiagnostics: getDiagnostics, @@ -943,20 +945,37 @@ module ts { writer.write(symbolToString(symbol, enclosingDeclaration, meaning)); } - function createSingleLineTextWriter() { + function createSingleLineTextWriter(maxLength?: number) { var result = ""; + var overflow = false; + function write(s: string) { + if (!overflow) { + result += s; + if (result.length > maxLength) { + result = result.substr(0, maxLength - 3) + "..."; + overflow = true; + } + } + } return { - write(s: string) { result += s; }, - writeSymbol(symbol: Symbol, enclosingDeclaration?: Node, meaning?: SymbolFlags) { writeSymbolToTextWriter(symbol, enclosingDeclaration, meaning, this); }, - writeLine() { result += " "; }, + write: write, + writeSymbol(symbol: Symbol, enclosingDeclaration?: Node, meaning?: SymbolFlags) { + writeSymbolToTextWriter(symbol, enclosingDeclaration, meaning, this); + }, + writeLine() { + write(" "); + }, increaseIndent() { }, decreaseIndent() { }, - getText() { return result; } + getText() { + return result; + } }; } function typeToString(type: Type, enclosingDeclaration?: Node, flags?: TypeFormatFlags): string { - var stringWriter = createSingleLineTextWriter(); + var maxLength = compilerOptions.noErrorTruncation || flags & TypeFormatFlags.NoTruncation ? undefined : 100; + var stringWriter = createSingleLineTextWriter(maxLength); // TODO(shkamat): typeToString should take enclosingDeclaration as input, once we have implemented enclosingDeclaration writeTypeToTextWriter(type, enclosingDeclaration, flags, stringWriter); return stringWriter.getText(); @@ -1348,7 +1367,7 @@ module ts { return type; function checkImplicitAny(type: Type) { - if (!fullTypeCheck || !program.getCompilerOptions().noImplicitAny) { + if (!fullTypeCheck || !compilerOptions.noImplicitAny) { return; } // We need to have ended up with 'any', 'any[]', 'any[][]', etc. @@ -1451,7 +1470,7 @@ module ts { } // Otherwise, fall back to 'any'. else { - if (program.getCompilerOptions().noImplicitAny) { + if (compilerOptions.noImplicitAny) { error(setter, Diagnostics.Property_0_implicitly_has_type_any_because_its_set_accessor_lacks_a_type_annotation, symbol.name); } @@ -3971,7 +3990,7 @@ module ts { } // Fall back to any. - if (program.getCompilerOptions().noImplicitAny && objectType !== anyType) { + if (compilerOptions.noImplicitAny && objectType !== anyType) { error(node, Diagnostics.Index_signature_of_object_type_implicitly_has_an_any_type); } @@ -4316,7 +4335,7 @@ module ts { var declaration = signature.declaration; if (declaration && (declaration.kind !== SyntaxKind.Constructor && declaration.kind !== SyntaxKind.ConstructSignature)) { // When resolved signature is a call signature (and not a construct signature) the result type is any - if (program.getCompilerOptions().noImplicitAny) { + if (compilerOptions.noImplicitAny) { error(node, Diagnostics.new_expression_whose_target_lacks_a_construct_signature_implicitly_has_an_any_type); } return anyType; @@ -4362,7 +4381,7 @@ module ts { var unwidenedType = checkAndMarkExpression(func.body, contextualMapper); var widenedType = getWidenedType(unwidenedType); - if (fullTypeCheck && program.getCompilerOptions().noImplicitAny && widenedType !== unwidenedType && getInnermostTypeOfNestedArrayTypes(widenedType) === anyType) { + if (fullTypeCheck && compilerOptions.noImplicitAny && widenedType !== unwidenedType && getInnermostTypeOfNestedArrayTypes(widenedType) === anyType) { error(func, Diagnostics.Function_expression_which_lacks_return_type_annotation_implicitly_has_an_0_return_type, typeToString(widenedType)); } @@ -4384,7 +4403,7 @@ module ts { var widenedType = getWidenedType(commonType); // Check and report for noImplicitAny if the best common type implicitly gets widened to an 'any'/arrays-of-'any' type. - if (fullTypeCheck && program.getCompilerOptions().noImplicitAny && widenedType !== commonType && getInnermostTypeOfNestedArrayTypes(widenedType) === anyType) { + if (fullTypeCheck && compilerOptions.noImplicitAny && widenedType !== commonType && getInnermostTypeOfNestedArrayTypes(widenedType) === anyType) { var typeName = typeToString(widenedType); if (func.name) { @@ -4960,7 +4979,7 @@ module ts { checkCollisionWithCapturedThisVariable(node, node.name); checkCollistionWithRequireExportsInGeneratedCode(node, node.name); checkCollisionWithArgumentsInGeneratedCode(node); - if (program.getCompilerOptions().noImplicitAny && !node.type) { + if (compilerOptions.noImplicitAny && !node.type) { switch (node.kind) { case SyntaxKind.ConstructSignature: error(node, Diagnostics.Construct_signature_which_lacks_return_type_annotation_implicitly_has_an_any_return_type); @@ -5516,7 +5535,7 @@ module ts { } // If there is no body and no explicit return type, then report an error. - if (fullTypeCheck && program.getCompilerOptions().noImplicitAny && !node.body && !node.type) { + if (fullTypeCheck && compilerOptions.noImplicitAny && !node.body && !node.type) { // Ignore privates within ambient contexts; they exist purely for documentative purposes to avoid name clashing. // (e.g. privates within .d.ts files do not expose type information) if (!isPrivateWithinAmbient(node)) { @@ -7161,7 +7180,7 @@ module ts { function shouldEmitDeclarations() { // If the declaration emit and there are no errors being reported in program or by checker // declarations can be emitted - return program.getCompilerOptions().declaration && + return compilerOptions.declaration && !program.getDiagnostics().length && !getDiagnostics().length; } diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 922db40cdec..c13b47a066c 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -631,12 +631,10 @@ module ts { } export enum TypeFormatFlags { - None = 0x00000000, - - /** writes Array instead T[] */ - WriteArrayAsGenericType = 0x00000001, // Declarations - - UseTypeOfFunction = 0x00000002, // instead of writing signature type of function use typeof + None = 0x00000000, + WriteArrayAsGenericType = 0x00000001, // Write Array instead T[] + UseTypeOfFunction = 0x00000002, // Write typeof instead of function type literal + NoTruncation = 0x00000004, // Don't truncate typeToString result } export enum SymbolAccessibility { @@ -957,6 +955,7 @@ module ts { locale?: string; mapRoot?: string; module?: ModuleKind; + noErrorTruncation?: boolean; noImplicitAny?: boolean; noLib?: boolean; noLibCheck?: boolean; @@ -969,7 +968,6 @@ module ts { target?: ScriptTarget; version?: boolean; watch?: boolean; - [option: string]: any; } diff --git a/src/harness/harness.ts b/src/harness/harness.ts index 654f240b4b5..5ee3139d8f7 100644 --- a/src/harness/harness.ts +++ b/src/harness/harness.ts @@ -622,6 +622,7 @@ module Harness { options = options || { noResolve: false }; options.target = options.target || ts.ScriptTarget.ES3; options.module = options.module || ts.ModuleKind.None; + options.noErrorTruncation = true; if (settingsCallback) { settingsCallback(null); @@ -725,6 +726,10 @@ module Harness { options.emitBOM = !!setting.value; break; + case 'errortruncation': + options.noErrorTruncation = setting.value === 'false'; + break; + default: throw new Error('Unsupported compiler setting ' + setting.flag); } @@ -1030,7 +1035,7 @@ module Harness { var optionRegex = /^[\/]{2}\s*@(\w+)\s*:\s*(\S*)/gm; // multiple matches on multiple lines // List of allowed metadata names - var fileMetadataNames = ["filename", "comments", "declaration", "module", "nolib", "sourcemap", "target", "out", "outDir", "noimplicitany", "noresolve", "newline", "newlines", "emitbom"]; + var fileMetadataNames = ["filename", "comments", "declaration", "module", "nolib", "sourcemap", "target", "out", "outDir", "noimplicitany", "noresolve", "newline", "newlines", "emitbom", "errortruncation"]; function extractCompilerSettings(content: string): CompilerSetting[] { diff --git a/src/harness/typeWriter.ts b/src/harness/typeWriter.ts index a3b23d10f14..8fac5e45dab 100644 --- a/src/harness/typeWriter.ts +++ b/src/harness/typeWriter.ts @@ -86,7 +86,7 @@ class TypeWriterWalker { column: lineAndCharacter.character, syntaxKind: ts.SyntaxKind[node.kind], sourceText: sourceText, - type: this.checker.typeToString(type, node.parent, ts.TypeFormatFlags.None) + type: this.checker.typeToString(type, node.parent, ts.TypeFormatFlags.NoTruncation) }); } diff --git a/tests/baselines/reference/errorWithTruncatedType.errors.txt b/tests/baselines/reference/errorWithTruncatedType.errors.txt new file mode 100644 index 00000000000..7d3cab5f3c5 --- /dev/null +++ b/tests/baselines/reference/errorWithTruncatedType.errors.txt @@ -0,0 +1,15 @@ +==== tests/cases/compiler/errorWithTruncatedType.ts (1 errors) ==== + + var x: { + propertyWithAnExceedinglyLongName1: string; + propertyWithAnExceedinglyLongName2: string; + propertyWithAnExceedinglyLongName3: string; + propertyWithAnExceedinglyLongName4: string; + propertyWithAnExceedinglyLongName5: string; + }; + + // String representation of type of 'x' should be truncated in error message + var s: string = x; + ~ +!!! Type '{ propertyWithAnExceedinglyLongName1: string; propertyWithAnExceedinglyLongName2: string; propert...' is not assignable to type 'string'. + \ No newline at end of file diff --git a/tests/baselines/reference/errorWithTruncatedType.js b/tests/baselines/reference/errorWithTruncatedType.js new file mode 100644 index 00000000000..5fd45579a29 --- /dev/null +++ b/tests/baselines/reference/errorWithTruncatedType.js @@ -0,0 +1,18 @@ +//// [errorWithTruncatedType.ts] + +var x: { + propertyWithAnExceedinglyLongName1: string; + propertyWithAnExceedinglyLongName2: string; + propertyWithAnExceedinglyLongName3: string; + propertyWithAnExceedinglyLongName4: string; + propertyWithAnExceedinglyLongName5: string; +}; + +// String representation of type of 'x' should be truncated in error message +var s: string = x; + + +//// [errorWithTruncatedType.js] +var x; +// String representation of type of 'x' should be truncated in error message +var s = x; diff --git a/tests/cases/compiler/errorWithTruncatedType.ts b/tests/cases/compiler/errorWithTruncatedType.ts new file mode 100644 index 00000000000..307ff642ed9 --- /dev/null +++ b/tests/cases/compiler/errorWithTruncatedType.ts @@ -0,0 +1,12 @@ +// @errortruncation: true + +var x: { + propertyWithAnExceedinglyLongName1: string; + propertyWithAnExceedinglyLongName2: string; + propertyWithAnExceedinglyLongName3: string; + propertyWithAnExceedinglyLongName4: string; + propertyWithAnExceedinglyLongName5: string; +}; + +// String representation of type of 'x' should be truncated in error message +var s: string = x;