mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-07-02 14:48:32 -05:00
Merge pull request #630 from Microsoft/truncateTypesInErrors
Truncate long types in error messages
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
@@ -631,12 +631,10 @@ module ts {
|
||||
}
|
||||
|
||||
export enum TypeFormatFlags {
|
||||
None = 0x00000000,
|
||||
|
||||
/** writes Array<T> instead T[] */
|
||||
WriteArrayAsGenericType = 0x00000001, // Declarations
|
||||
|
||||
UseTypeOfFunction = 0x00000002, // instead of writing signature type of function use typeof
|
||||
None = 0x00000000,
|
||||
WriteArrayAsGenericType = 0x00000001, // Write Array<T> 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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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[] {
|
||||
|
||||
|
||||
@@ -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)
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
15
tests/baselines/reference/errorWithTruncatedType.errors.txt
Normal file
15
tests/baselines/reference/errorWithTruncatedType.errors.txt
Normal file
@@ -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'.
|
||||
|
||||
18
tests/baselines/reference/errorWithTruncatedType.js
Normal file
18
tests/baselines/reference/errorWithTruncatedType.js
Normal file
@@ -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;
|
||||
12
tests/cases/compiler/errorWithTruncatedType.ts
Normal file
12
tests/cases/compiler/errorWithTruncatedType.ts
Normal file
@@ -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;
|
||||
Reference in New Issue
Block a user