mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-05-30 01:04:49 -05:00
Merge branch 'master' into testPerf
Conflicts: src/harness/harness.ts tests/baselines/reference/noDefaultLib.errors.txt tests/baselines/reference/typeCheckTypeArgument.errors.txt
This commit is contained in:
@@ -1485,7 +1485,7 @@ module ts {
|
||||
return appendParentTypeArgumentsAndSymbolName(symbol);
|
||||
}
|
||||
|
||||
function buildTypeDisplay(type: Type, writer: SymbolWriter, enclosingDeclaration?: Node, globalFlags?: TypeFormatFlags, typeStack?: Type[]) {
|
||||
function buildTypeDisplay(type: Type, writer: SymbolWriter, enclosingDeclaration?: Node, globalFlags?: TypeFormatFlags, symbolStack?: Symbol[]) {
|
||||
let globalFlagsToPass = globalFlags & TypeFormatFlags.WriteOwnNameForAnyLike;
|
||||
return writeType(type, globalFlags);
|
||||
|
||||
@@ -1608,49 +1608,54 @@ module ts {
|
||||
}
|
||||
|
||||
function writeAnonymousType(type: ObjectType, flags: TypeFormatFlags) {
|
||||
// Always use 'typeof T' for type of class, enum, and module objects
|
||||
if (type.symbol && type.symbol.flags & (SymbolFlags.Class | SymbolFlags.Enum | SymbolFlags.ValueModule)) {
|
||||
writeTypeofSymbol(type, flags);
|
||||
}
|
||||
// Use 'typeof T' for types of functions and methods that circularly reference themselves
|
||||
else if (shouldWriteTypeOfFunctionSymbol()) {
|
||||
writeTypeofSymbol(type, flags);
|
||||
}
|
||||
else if (typeStack && contains(typeStack, type)) {
|
||||
// If type is an anonymous type literal in a type alias declaration, use type alias name
|
||||
let typeAlias = getTypeAliasForTypeLiteral(type);
|
||||
if (typeAlias) {
|
||||
// The specified symbol flags need to be reinterpreted as type flags
|
||||
buildSymbolDisplay(typeAlias, writer, enclosingDeclaration, SymbolFlags.Type, SymbolFormatFlags.None, flags);
|
||||
let symbol = type.symbol;
|
||||
if (symbol) {
|
||||
// Always use 'typeof T' for type of class, enum, and module objects
|
||||
if (symbol.flags & (SymbolFlags.Class | SymbolFlags.Enum | SymbolFlags.ValueModule)) {
|
||||
writeTypeofSymbol(type, flags);
|
||||
}
|
||||
else if (shouldWriteTypeOfFunctionSymbol()) {
|
||||
writeTypeofSymbol(type, flags);
|
||||
}
|
||||
else if (contains(symbolStack, symbol)) {
|
||||
// If type is an anonymous type literal in a type alias declaration, use type alias name
|
||||
let typeAlias = getTypeAliasForTypeLiteral(type);
|
||||
if (typeAlias) {
|
||||
// The specified symbol flags need to be reinterpreted as type flags
|
||||
buildSymbolDisplay(typeAlias, writer, enclosingDeclaration, SymbolFlags.Type, SymbolFormatFlags.None, flags);
|
||||
}
|
||||
else {
|
||||
// Recursive usage, use any
|
||||
writeKeyword(writer, SyntaxKind.AnyKeyword);
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Recursive usage, use any
|
||||
writeKeyword(writer, SyntaxKind.AnyKeyword);
|
||||
// Since instantiations of the same anonymous type have the same symbol, tracking symbols instead
|
||||
// of types allows us to catch circular references to instantiations of the same anonymous type
|
||||
if (!symbolStack) {
|
||||
symbolStack = [];
|
||||
}
|
||||
symbolStack.push(symbol);
|
||||
writeLiteralType(type, flags);
|
||||
symbolStack.pop();
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (!typeStack) {
|
||||
typeStack = [];
|
||||
}
|
||||
typeStack.push(type);
|
||||
// Anonymous types with no symbol are never circular
|
||||
writeLiteralType(type, flags);
|
||||
typeStack.pop();
|
||||
}
|
||||
|
||||
function shouldWriteTypeOfFunctionSymbol() {
|
||||
if (type.symbol) {
|
||||
let isStaticMethodSymbol = !!(type.symbol.flags & SymbolFlags.Method && // typeof static method
|
||||
ts.forEach(type.symbol.declarations, declaration => declaration.flags & NodeFlags.Static));
|
||||
let isNonLocalFunctionSymbol = !!(type.symbol.flags & SymbolFlags.Function) &&
|
||||
(type.symbol.parent || // is exported function symbol
|
||||
ts.forEach(type.symbol.declarations, declaration =>
|
||||
declaration.parent.kind === SyntaxKind.SourceFile || declaration.parent.kind === SyntaxKind.ModuleBlock));
|
||||
|
||||
if (isStaticMethodSymbol || isNonLocalFunctionSymbol) {
|
||||
// typeof is allowed only for static/non local functions
|
||||
return !!(flags & TypeFormatFlags.UseTypeOfFunction) || // use typeof if format flags specify it
|
||||
(typeStack && contains(typeStack, type)); // it is type of the symbol uses itself recursively
|
||||
}
|
||||
let isStaticMethodSymbol = !!(symbol.flags & SymbolFlags.Method && // typeof static method
|
||||
forEach(symbol.declarations, declaration => declaration.flags & NodeFlags.Static));
|
||||
let isNonLocalFunctionSymbol = !!(symbol.flags & SymbolFlags.Function) &&
|
||||
(symbol.parent || // is exported function symbol
|
||||
forEach(symbol.declarations, declaration =>
|
||||
declaration.parent.kind === SyntaxKind.SourceFile || declaration.parent.kind === SyntaxKind.ModuleBlock));
|
||||
if (isStaticMethodSymbol || isNonLocalFunctionSymbol) {
|
||||
// typeof is allowed only for static/non local functions
|
||||
return !!(flags & TypeFormatFlags.UseTypeOfFunction) || // use typeof if format flags specify it
|
||||
(contains(symbolStack, symbol)); // it is type of the symbol uses itself recursively
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1685,7 +1690,7 @@ module ts {
|
||||
if (flags & TypeFormatFlags.InElementType) {
|
||||
writePunctuation(writer, SyntaxKind.OpenParenToken);
|
||||
}
|
||||
buildSignatureDisplay(resolved.callSignatures[0], writer, enclosingDeclaration, globalFlagsToPass | TypeFormatFlags.WriteArrowStyleSignature, typeStack);
|
||||
buildSignatureDisplay(resolved.callSignatures[0], writer, enclosingDeclaration, globalFlagsToPass | TypeFormatFlags.WriteArrowStyleSignature, symbolStack);
|
||||
if (flags & TypeFormatFlags.InElementType) {
|
||||
writePunctuation(writer, SyntaxKind.CloseParenToken);
|
||||
}
|
||||
@@ -1697,7 +1702,7 @@ module ts {
|
||||
}
|
||||
writeKeyword(writer, SyntaxKind.NewKeyword);
|
||||
writeSpace(writer);
|
||||
buildSignatureDisplay(resolved.constructSignatures[0], writer, enclosingDeclaration, globalFlagsToPass | TypeFormatFlags.WriteArrowStyleSignature, typeStack);
|
||||
buildSignatureDisplay(resolved.constructSignatures[0], writer, enclosingDeclaration, globalFlagsToPass | TypeFormatFlags.WriteArrowStyleSignature, symbolStack);
|
||||
if (flags & TypeFormatFlags.InElementType) {
|
||||
writePunctuation(writer, SyntaxKind.CloseParenToken);
|
||||
}
|
||||
@@ -1709,7 +1714,7 @@ module ts {
|
||||
writer.writeLine();
|
||||
writer.increaseIndent();
|
||||
for (let signature of resolved.callSignatures) {
|
||||
buildSignatureDisplay(signature, writer, enclosingDeclaration, globalFlagsToPass, typeStack);
|
||||
buildSignatureDisplay(signature, writer, enclosingDeclaration, globalFlagsToPass, symbolStack);
|
||||
writePunctuation(writer, SyntaxKind.SemicolonToken);
|
||||
writer.writeLine();
|
||||
}
|
||||
@@ -1717,7 +1722,7 @@ module ts {
|
||||
writeKeyword(writer, SyntaxKind.NewKeyword);
|
||||
writeSpace(writer);
|
||||
|
||||
buildSignatureDisplay(signature, writer, enclosingDeclaration, globalFlagsToPass, typeStack);
|
||||
buildSignatureDisplay(signature, writer, enclosingDeclaration, globalFlagsToPass, symbolStack);
|
||||
writePunctuation(writer, SyntaxKind.SemicolonToken);
|
||||
writer.writeLine();
|
||||
}
|
||||
@@ -1758,7 +1763,7 @@ module ts {
|
||||
if (p.flags & SymbolFlags.Optional) {
|
||||
writePunctuation(writer, SyntaxKind.QuestionToken);
|
||||
}
|
||||
buildSignatureDisplay(signature, writer, enclosingDeclaration, globalFlagsToPass, typeStack);
|
||||
buildSignatureDisplay(signature, writer, enclosingDeclaration, globalFlagsToPass, symbolStack);
|
||||
writePunctuation(writer, SyntaxKind.SemicolonToken);
|
||||
writer.writeLine();
|
||||
}
|
||||
@@ -1787,18 +1792,18 @@ module ts {
|
||||
}
|
||||
}
|
||||
|
||||
function buildTypeParameterDisplay(tp: TypeParameter, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags, typeStack?: Type[]) {
|
||||
function buildTypeParameterDisplay(tp: TypeParameter, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags, symbolStack?: Symbol[]) {
|
||||
appendSymbolNameOnly(tp.symbol, writer);
|
||||
let constraint = getConstraintOfTypeParameter(tp);
|
||||
if (constraint) {
|
||||
writeSpace(writer);
|
||||
writeKeyword(writer, SyntaxKind.ExtendsKeyword);
|
||||
writeSpace(writer);
|
||||
buildTypeDisplay(constraint, writer, enclosingDeclaration, flags, typeStack);
|
||||
buildTypeDisplay(constraint, writer, enclosingDeclaration, flags, symbolStack);
|
||||
}
|
||||
}
|
||||
|
||||
function buildParameterDisplay(p: Symbol, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags, typeStack?: Type[]) {
|
||||
function buildParameterDisplay(p: Symbol, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags, symbolStack?: Symbol[]) {
|
||||
let parameterNode = <ParameterDeclaration>p.valueDeclaration;
|
||||
if (isRestParameter(parameterNode)) {
|
||||
writePunctuation(writer, SyntaxKind.DotDotDotToken);
|
||||
@@ -1810,10 +1815,10 @@ module ts {
|
||||
writePunctuation(writer, SyntaxKind.ColonToken);
|
||||
writeSpace(writer);
|
||||
|
||||
buildTypeDisplay(getTypeOfSymbol(p), writer, enclosingDeclaration, flags, typeStack);
|
||||
buildTypeDisplay(getTypeOfSymbol(p), writer, enclosingDeclaration, flags, symbolStack);
|
||||
}
|
||||
|
||||
function buildDisplayForTypeParametersAndDelimiters(typeParameters: TypeParameter[], writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags, typeStack?: Type[]) {
|
||||
function buildDisplayForTypeParametersAndDelimiters(typeParameters: TypeParameter[], writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags, symbolStack?: Symbol[]) {
|
||||
if (typeParameters && typeParameters.length) {
|
||||
writePunctuation(writer, SyntaxKind.LessThanToken);
|
||||
for (let i = 0; i < typeParameters.length; i++) {
|
||||
@@ -1821,13 +1826,13 @@ module ts {
|
||||
writePunctuation(writer, SyntaxKind.CommaToken);
|
||||
writeSpace(writer);
|
||||
}
|
||||
buildTypeParameterDisplay(typeParameters[i], writer, enclosingDeclaration, flags, typeStack);
|
||||
buildTypeParameterDisplay(typeParameters[i], writer, enclosingDeclaration, flags, symbolStack);
|
||||
}
|
||||
writePunctuation(writer, SyntaxKind.GreaterThanToken);
|
||||
}
|
||||
}
|
||||
|
||||
function buildDisplayForTypeArgumentsAndDelimiters(typeParameters: TypeParameter[], mapper: TypeMapper, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags, typeStack?: Type[]) {
|
||||
function buildDisplayForTypeArgumentsAndDelimiters(typeParameters: TypeParameter[], mapper: TypeMapper, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags, symbolStack?: Symbol[]) {
|
||||
if (typeParameters && typeParameters.length) {
|
||||
writePunctuation(writer, SyntaxKind.LessThanToken);
|
||||
for (let i = 0; i < typeParameters.length; i++) {
|
||||
@@ -1841,19 +1846,19 @@ module ts {
|
||||
}
|
||||
}
|
||||
|
||||
function buildDisplayForParametersAndDelimiters(parameters: Symbol[], writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags, typeStack?: Type[]) {
|
||||
function buildDisplayForParametersAndDelimiters(parameters: Symbol[], writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags, symbolStack?: Symbol[]) {
|
||||
writePunctuation(writer, SyntaxKind.OpenParenToken);
|
||||
for (let i = 0; i < parameters.length; i++) {
|
||||
if (i > 0) {
|
||||
writePunctuation(writer, SyntaxKind.CommaToken);
|
||||
writeSpace(writer);
|
||||
}
|
||||
buildParameterDisplay(parameters[i], writer, enclosingDeclaration, flags, typeStack);
|
||||
buildParameterDisplay(parameters[i], writer, enclosingDeclaration, flags, symbolStack);
|
||||
}
|
||||
writePunctuation(writer, SyntaxKind.CloseParenToken);
|
||||
}
|
||||
|
||||
function buildReturnTypeDisplay(signature: Signature, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags, typeStack?: Type[]) {
|
||||
function buildReturnTypeDisplay(signature: Signature, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags, symbolStack?: Symbol[]) {
|
||||
if (flags & TypeFormatFlags.WriteArrowStyleSignature) {
|
||||
writeSpace(writer);
|
||||
writePunctuation(writer, SyntaxKind.EqualsGreaterThanToken);
|
||||
@@ -1862,21 +1867,21 @@ module ts {
|
||||
writePunctuation(writer, SyntaxKind.ColonToken);
|
||||
}
|
||||
writeSpace(writer);
|
||||
buildTypeDisplay(getReturnTypeOfSignature(signature), writer, enclosingDeclaration, flags, typeStack);
|
||||
buildTypeDisplay(getReturnTypeOfSignature(signature), writer, enclosingDeclaration, flags, symbolStack);
|
||||
}
|
||||
|
||||
function buildSignatureDisplay(signature: Signature, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags, typeStack?: Type[]) {
|
||||
function buildSignatureDisplay(signature: Signature, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags, symbolStack?: Symbol[]) {
|
||||
if (signature.target && (flags & TypeFormatFlags.WriteTypeArgumentsOfSignature)) {
|
||||
// Instantiated signature, write type arguments instead
|
||||
// This is achieved by passing in the mapper separately
|
||||
buildDisplayForTypeArgumentsAndDelimiters(signature.target.typeParameters, signature.mapper, writer, enclosingDeclaration);
|
||||
}
|
||||
else {
|
||||
buildDisplayForTypeParametersAndDelimiters(signature.typeParameters, writer, enclosingDeclaration, flags, typeStack);
|
||||
buildDisplayForTypeParametersAndDelimiters(signature.typeParameters, writer, enclosingDeclaration, flags, symbolStack);
|
||||
}
|
||||
|
||||
buildDisplayForParametersAndDelimiters(signature.parameters, writer, enclosingDeclaration, flags, typeStack);
|
||||
buildReturnTypeDisplay(signature, writer, enclosingDeclaration, flags, typeStack);
|
||||
buildDisplayForParametersAndDelimiters(signature.parameters, writer, enclosingDeclaration, flags, symbolStack);
|
||||
buildReturnTypeDisplay(signature, writer, enclosingDeclaration, flags, symbolStack);
|
||||
}
|
||||
|
||||
return _displayBuilder || (_displayBuilder = {
|
||||
@@ -3996,19 +4001,8 @@ module ts {
|
||||
}
|
||||
|
||||
function instantiateAnonymousType(type: ObjectType, mapper: TypeMapper): ObjectType {
|
||||
// If this type has already been instantiated using this mapper, returned the cached result. This guards against
|
||||
// infinite instantiations of cyclic types, e.g. "var x: { a: T, b: typeof x };"
|
||||
if (mapper.mappings) {
|
||||
let cached = <ObjectType>mapper.mappings[type.id];
|
||||
if (cached) {
|
||||
return cached;
|
||||
}
|
||||
}
|
||||
else {
|
||||
mapper.mappings = {};
|
||||
}
|
||||
// Instantiate the given type using the given mapper and cache the result
|
||||
let result = <ResolvedType>createObjectType(TypeFlags.Anonymous, type.symbol);
|
||||
// Mark the anonymous type as instantiated such that our infinite instantiation detection logic can recognize it
|
||||
let result = <ResolvedType>createObjectType(TypeFlags.Anonymous | TypeFlags.Instantiated, type.symbol);
|
||||
result.properties = instantiateList(getPropertiesOfObjectType(type), mapper, instantiateSymbol);
|
||||
result.members = createSymbolTable(result.properties);
|
||||
result.callSignatures = instantiateList(getSignaturesOfType(type, SignatureKind.Call), mapper, instantiateSignature);
|
||||
@@ -4017,7 +4011,6 @@ module ts {
|
||||
let numberIndexType = getIndexTypeOfType(type, IndexKind.Number);
|
||||
if (stringIndexType) result.stringIndexType = instantiateType(stringIndexType, mapper);
|
||||
if (numberIndexType) result.numberIndexType = instantiateType(numberIndexType, mapper);
|
||||
mapper.mappings[type.id] = result;
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -4432,12 +4425,13 @@ module ts {
|
||||
// Effectively, we will generate a false positive when two types are structurally equal to at least 10 levels, but unequal at
|
||||
// some level beyond that.
|
||||
function isDeeplyNestedGeneric(type: ObjectType, stack: ObjectType[]): boolean {
|
||||
if (type.flags & TypeFlags.Reference && depth >= 10) {
|
||||
let target = (<TypeReference>type).target;
|
||||
// We track type references (created by createTypeReference) and instantiated types (created by instantiateType)
|
||||
if (type.flags & (TypeFlags.Reference | TypeFlags.Instantiated) && depth >= 10) {
|
||||
let symbol = type.symbol;
|
||||
let count = 0;
|
||||
for (let i = 0; i < depth; i++) {
|
||||
let t = stack[i];
|
||||
if (t.flags & TypeFlags.Reference && (<TypeReference>t).target === target) {
|
||||
if (t.flags & (TypeFlags.Reference | TypeFlags.Instantiated) && t.symbol === symbol) {
|
||||
count++;
|
||||
if (count >= 10) return true;
|
||||
}
|
||||
|
||||
@@ -349,7 +349,7 @@ module ts {
|
||||
|
||||
return {
|
||||
options: getCompilerOptions(),
|
||||
fileNames: getFiles(),
|
||||
fileNames: getFileNames(),
|
||||
errors
|
||||
};
|
||||
|
||||
@@ -395,23 +395,24 @@ module ts {
|
||||
return options;
|
||||
}
|
||||
|
||||
function getFiles(): string[] {
|
||||
var files: string[] = [];
|
||||
function getFileNames(): string[] {
|
||||
var fileNames: string[] = [];
|
||||
if (hasProperty(json, "files")) {
|
||||
if (json["files"] instanceof Array) {
|
||||
var files = map(<string[]>json["files"], s => combinePaths(basePath, s));
|
||||
fileNames = map(<string[]>json["files"], s => combinePaths(basePath, s));
|
||||
}
|
||||
}
|
||||
else {
|
||||
var sysFiles = host.readDirectory(basePath, ".ts");
|
||||
var exclude = json["exclude"] instanceof Array ? map(<string[]>json["exclude"], normalizeSlashes) : undefined;
|
||||
var sysFiles = host.readDirectory(basePath, ".ts", exclude);
|
||||
for (var i = 0; i < sysFiles.length; i++) {
|
||||
var name = sysFiles[i];
|
||||
if (!fileExtensionIs(name, ".d.ts") || !contains(sysFiles, name.substr(0, name.length - 5) + ".ts")) {
|
||||
files.push(name);
|
||||
fileNames.push(name);
|
||||
}
|
||||
}
|
||||
}
|
||||
return files;
|
||||
return fileNames;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ module ts {
|
||||
createDirectory(path: string): void;
|
||||
getExecutingFilePath(): string;
|
||||
getCurrentDirectory(): string;
|
||||
readDirectory(path: string, extension?: string): string[];
|
||||
readDirectory(path: string, extension?: string, exclude?: string[]): string[];
|
||||
getMemoryUsage?(): number;
|
||||
exit(exitCode?: number): void;
|
||||
}
|
||||
@@ -109,7 +109,11 @@ module ts {
|
||||
}
|
||||
}
|
||||
|
||||
function getNames(collection: any): string[] {
|
||||
function getCanonicalPath(path: string): string {
|
||||
return path.toLowerCase();
|
||||
}
|
||||
|
||||
function getNames(collection: any): string[]{
|
||||
var result: string[] = [];
|
||||
for (var e = new Enumerator(collection); !e.atEnd(); e.moveNext()) {
|
||||
result.push(e.item().Name);
|
||||
@@ -117,21 +121,26 @@ module ts {
|
||||
return result.sort();
|
||||
}
|
||||
|
||||
function readDirectory(path: string, extension?: string): string[] {
|
||||
function readDirectory(path: string, extension?: string, exclude?: string[]): string[] {
|
||||
var result: string[] = [];
|
||||
exclude = map(exclude, s => getCanonicalPath(combinePaths(path, s)));
|
||||
visitDirectory(path);
|
||||
return result;
|
||||
function visitDirectory(path: string) {
|
||||
var folder = fso.GetFolder(path || ".");
|
||||
var files = getNames(folder.files);
|
||||
for (let name of files) {
|
||||
if (!extension || fileExtensionIs(name, extension)) {
|
||||
result.push(combinePaths(path, name));
|
||||
for (let current of files) {
|
||||
let name = combinePaths(path, current);
|
||||
if ((!extension || fileExtensionIs(name, extension)) && !contains(exclude, getCanonicalPath(name))) {
|
||||
result.push(name);
|
||||
}
|
||||
}
|
||||
var subfolders = getNames(folder.subfolders);
|
||||
for (let current of subfolders) {
|
||||
visitDirectory(combinePaths(path, current));
|
||||
let name = combinePaths(path, current);
|
||||
if (!contains(exclude, getCanonicalPath(name))) {
|
||||
visitDirectory(name);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -222,8 +231,13 @@ module ts {
|
||||
_fs.writeFileSync(fileName, data, "utf8");
|
||||
}
|
||||
|
||||
function readDirectory(path: string, extension?: string): string[] {
|
||||
function getCanonicalPath(path: string): string {
|
||||
return useCaseSensitiveFileNames ? path.toLowerCase() : path;
|
||||
}
|
||||
|
||||
function readDirectory(path: string, extension?: string, exclude?: string[]): string[] {
|
||||
var result: string[] = [];
|
||||
exclude = map(exclude, s => getCanonicalPath(combinePaths(path, s)));
|
||||
visitDirectory(path);
|
||||
return result;
|
||||
function visitDirectory(path: string) {
|
||||
@@ -231,14 +245,16 @@ module ts {
|
||||
var directories: string[] = [];
|
||||
for (let current of files) {
|
||||
var name = combinePaths(path, current);
|
||||
var stat = _fs.statSync(name);
|
||||
if (stat.isFile()) {
|
||||
if (!extension || fileExtensionIs(name, extension)) {
|
||||
result.push(name);
|
||||
if (!contains(exclude, getCanonicalPath(name))) {
|
||||
var stat = _fs.statSync(name);
|
||||
if (stat.isFile()) {
|
||||
if (!extension || fileExtensionIs(name, extension)) {
|
||||
result.push(name);
|
||||
}
|
||||
}
|
||||
else if (stat.isDirectory()) {
|
||||
directories.push(name);
|
||||
}
|
||||
}
|
||||
else if (stat.isDirectory()) {
|
||||
directories.push(name);
|
||||
}
|
||||
}
|
||||
for (let current of directories) {
|
||||
|
||||
@@ -1176,7 +1176,7 @@ module ts {
|
||||
}
|
||||
|
||||
export interface ParseConfigHost {
|
||||
readDirectory(rootDir: string, extension: string): string[];
|
||||
readDirectory(rootDir: string, extension: string, exclude: string[]): string[];
|
||||
}
|
||||
|
||||
export interface WriteFileCallback {
|
||||
@@ -1590,14 +1590,15 @@ module ts {
|
||||
Tuple = 0x00002000, // Tuple
|
||||
Union = 0x00004000, // Union
|
||||
Anonymous = 0x00008000, // Anonymous
|
||||
Instantiated = 0x00010000, // Instantiated anonymous type
|
||||
/* @internal */
|
||||
FromSignature = 0x00010000, // Created for signature assignment check
|
||||
ObjectLiteral = 0x00020000, // Originates in an object literal
|
||||
FromSignature = 0x00020000, // Created for signature assignment check
|
||||
ObjectLiteral = 0x00040000, // Originates in an object literal
|
||||
/* @internal */
|
||||
ContainsUndefinedOrNull = 0x00040000, // Type is or contains Undefined or Null type
|
||||
ContainsUndefinedOrNull = 0x00080000, // Type is or contains Undefined or Null type
|
||||
/* @internal */
|
||||
ContainsObjectLiteral = 0x00080000, // Type is or contains object literal type
|
||||
ESSymbol = 0x00100000, // Type of symbol primitive introduced in ES6
|
||||
ContainsObjectLiteral = 0x00100000, // Type is or contains object literal type
|
||||
ESSymbol = 0x00200000, // Type of symbol primitive introduced in ES6
|
||||
|
||||
/* @internal */
|
||||
Intrinsic = Any | String | Number | Boolean | ESSymbol | Void | Undefined | Null,
|
||||
@@ -1739,7 +1740,6 @@ module ts {
|
||||
/* @internal */
|
||||
export interface TypeMapper {
|
||||
(t: TypeParameter): Type;
|
||||
mappings?: Map<Type>; // Type mapping cache
|
||||
}
|
||||
|
||||
/* @internal */
|
||||
|
||||
@@ -900,7 +900,7 @@ module Harness {
|
||||
private compileOptions: ts.CompilerOptions;
|
||||
private settings: Harness.TestCaseParser.CompilerSetting[] = [];
|
||||
|
||||
private lastErrors: HarnessDiagnostic[];
|
||||
private lastErrors: ts.Diagnostic[];
|
||||
|
||||
public reset() {
|
||||
this.inputFiles = [];
|
||||
@@ -985,19 +985,13 @@ module Harness {
|
||||
// always push the default lib in *last* to normalize the type/symbol baselines.
|
||||
programFiles.push(defaultLibFileName);
|
||||
}
|
||||
|
||||
var program = ts.createProgram(programFiles, options,
|
||||
createCompilerHost(inputFiles.concat(includeBuiltFiles).concat(otherFiles),
|
||||
var program = ts.createProgram(programFiles, options, createCompilerHost(inputFiles.concat(includeBuiltFiles).concat(otherFiles),
|
||||
(fn, contents, writeByteOrderMark) => fileOutputs.push({ fileName: fn, code: contents, writeByteOrderMark: writeByteOrderMark }),
|
||||
options.target, useCaseSensitiveFileNames, currentDirectory, options.newLine));
|
||||
|
||||
var emitResult = program.emit();
|
||||
|
||||
var errors: HarnessDiagnostic[] = [];
|
||||
ts.getPreEmitDiagnostics(program).concat(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));
|
||||
});
|
||||
var errors = ts.getPreEmitDiagnostics(program).concat(emitResult.diagnostics);
|
||||
this.lastErrors = errors;
|
||||
|
||||
var result = new CompilerResult(fileOutputs, errors, program, ts.sys.getCurrentDirectory(), emitResult.sourceMaps);
|
||||
@@ -1114,10 +1108,6 @@ module Harness {
|
||||
}
|
||||
break;
|
||||
|
||||
case 'normalizenewline':
|
||||
newLine = setting.value;
|
||||
break;
|
||||
|
||||
case 'comments':
|
||||
options.removeComments = setting.value === 'false';
|
||||
break;
|
||||
@@ -1248,70 +1238,50 @@ module Harness {
|
||||
return normalized;
|
||||
}
|
||||
|
||||
export function getMinimalDiagnostic(err: ts.Diagnostic): HarnessDiagnostic {
|
||||
var errorLineInfo = err.file ? err.file.getLineAndCharacterOfPosition(err.start) : { line: -1, character: -1 };
|
||||
return {
|
||||
fileName: err.file && err.file.fileName,
|
||||
start: err.start,
|
||||
end: err.start + err.length,
|
||||
line: errorLineInfo.line + 1,
|
||||
character: errorLineInfo.character + 1,
|
||||
message: ts.flattenDiagnosticMessageText(err.messageText, ts.sys.newLine),
|
||||
category: ts.DiagnosticCategory[err.category].toLowerCase(),
|
||||
code: err.code
|
||||
};
|
||||
}
|
||||
|
||||
export function minimalDiagnosticsToString(diagnostics: HarnessDiagnostic[]) {
|
||||
export function minimalDiagnosticsToString(diagnostics: ts.Diagnostic[]) {
|
||||
// This is basically copied from tsc.ts's reportError to replicate what tsc does
|
||||
var errorOutput = "";
|
||||
ts.forEach(diagnostics, diagnotic => {
|
||||
if (diagnotic.fileName) {
|
||||
errorOutput += diagnotic.fileName + "(" + diagnotic.line + "," + diagnotic.character + "): ";
|
||||
ts.forEach(diagnostics, diagnostic => {
|
||||
if (diagnostic.file) {
|
||||
var lineAndCharacter = diagnostic.file.getLineAndCharacterOfPosition(diagnostic.start);
|
||||
errorOutput += diagnostic.file.fileName + "(" + (lineAndCharacter.line + 1) + "," + (lineAndCharacter.character + 1) + "): ";
|
||||
}
|
||||
|
||||
errorOutput += diagnotic.category + " TS" + diagnotic.code + ": " + diagnotic.message + ts.sys.newLine;
|
||||
errorOutput += ts.DiagnosticCategory[diagnostic.category].toLowerCase() + " TS" + diagnostic.code + ": " + ts.flattenDiagnosticMessageText(diagnostic.messageText, ts.sys.newLine) + ts.sys.newLine;
|
||||
});
|
||||
|
||||
return errorOutput;
|
||||
}
|
||||
|
||||
function compareDiagnostics(d1: HarnessDiagnostic, d2: HarnessDiagnostic) {
|
||||
return ts.compareValues(d1.fileName, d2.fileName) ||
|
||||
ts.compareValues(d1.start, d2.start) ||
|
||||
ts.compareValues(d1.end, d2.end) ||
|
||||
ts.compareValues(d1.code, d2.code) ||
|
||||
ts.compareValues(d1.message, d2.message) ||
|
||||
0;
|
||||
}
|
||||
|
||||
export function getErrorBaseline(inputFiles: { unitName: string; content: string }[], diagnostics: HarnessDiagnostic[]) {
|
||||
diagnostics.sort(compareDiagnostics);
|
||||
export function getErrorBaseline(inputFiles: { unitName: string; content: string }[], diagnostics: ts.Diagnostic[]) {
|
||||
diagnostics.sort(ts.compareDiagnostics);
|
||||
var outputLines: string[] = [];
|
||||
// Count up all the errors we find so we don't miss any
|
||||
var totalErrorsReported = 0;
|
||||
|
||||
function outputErrorText(error: Harness.Compiler.HarnessDiagnostic) {
|
||||
var errLines = RunnerBase.removeFullPaths(error.message)
|
||||
function outputErrorText(error: ts.Diagnostic) {
|
||||
var message = ts.flattenDiagnosticMessageText(error.messageText, ts.sys.newLine);
|
||||
|
||||
var errLines = RunnerBase.removeFullPaths(message)
|
||||
.split('\n')
|
||||
.map(s => s.length > 0 && s.charAt(s.length - 1) === '\r' ? s.substr(0, s.length - 1) : s)
|
||||
.filter(s => s.length > 0)
|
||||
.map(s => '!!! ' + error.category + " TS" + error.code + ": " + s);
|
||||
.map(s => '!!! ' + ts.DiagnosticCategory[error.category].toLowerCase() + " TS" + error.code + ": " + s);
|
||||
errLines.forEach(e => outputLines.push(e));
|
||||
|
||||
totalErrorsReported++;
|
||||
}
|
||||
|
||||
// Report global errors
|
||||
var globalErrors = diagnostics.filter(err => !err.fileName);
|
||||
var globalErrors = diagnostics.filter(err => !err.file);
|
||||
globalErrors.forEach(outputErrorText);
|
||||
|
||||
// 'merge' the lines of each input file with any errors associated with it
|
||||
inputFiles.filter(f => f.content !== undefined).forEach(inputFile => {
|
||||
// Filter down to the errors in the file
|
||||
var fileErrors = diagnostics.filter(e => {
|
||||
var errFn = e.fileName;
|
||||
return errFn && errFn === inputFile.unitName;
|
||||
var errFn = e.file;
|
||||
return errFn && errFn.fileName === inputFile.unitName;
|
||||
});
|
||||
|
||||
|
||||
@@ -1347,18 +1317,19 @@ module Harness {
|
||||
outputLines.push(' ' + line);
|
||||
fileErrors.forEach(err => {
|
||||
// Does any error start or continue on to this line? Emit squiggles
|
||||
if ((err.end >= thisLineStart) && ((err.start < nextLineStart) || (lineIndex === lines.length - 1))) {
|
||||
let end = ts.textSpanEnd(err);
|
||||
if ((end >= thisLineStart) && ((err.start < nextLineStart) || (lineIndex === lines.length - 1))) {
|
||||
// How many characters from the start of this line the error starts at (could be positive or negative)
|
||||
var relativeOffset = err.start - thisLineStart;
|
||||
// How many characters of the error are on this line (might be longer than this line in reality)
|
||||
var length = (err.end - err.start) - Math.max(0, thisLineStart - err.start);
|
||||
var length = (end - err.start) - Math.max(0, thisLineStart - err.start);
|
||||
// Calculate the start of the squiggle
|
||||
var squiggleStart = Math.max(0, relativeOffset);
|
||||
// TODO/REVIEW: this doesn't work quite right in the browser if a multi file test has files whose names are just the right length relative to one another
|
||||
outputLines.push(' ' + line.substr(0, squiggleStart).replace(/[^\s]/g, ' ') + new Array(Math.min(length, line.length - squiggleStart) + 1).join('~'));
|
||||
|
||||
// If the error ended here, or we're at the end of the file, emit its message
|
||||
if ((lineIndex === lines.length - 1) || nextLineStart > err.end) {
|
||||
if ((lineIndex === lines.length - 1) || nextLineStart > end) {
|
||||
// Just like above, we need to do a split on a string instead of on a regex
|
||||
// because the JS engine does regexes wrong
|
||||
|
||||
@@ -1374,12 +1345,12 @@ module Harness {
|
||||
});
|
||||
|
||||
var numLibraryDiagnostics = ts.countWhere(diagnostics, diagnostic => {
|
||||
return diagnostic.fileName && (isLibraryFile(diagnostic.fileName) || isBuiltFile(diagnostic.fileName));
|
||||
return diagnostic.file && (isLibraryFile(diagnostic.file.fileName) || isBuiltFile(diagnostic.file.fileName));
|
||||
});
|
||||
|
||||
var numTest262HarnessDiagnostics = ts.countWhere(diagnostics, diagnostic => {
|
||||
// Count an error generated from tests262-harness folder.This should only apply for test262
|
||||
return diagnostic.fileName && diagnostic.fileName.indexOf("test262-harness") >= 0;
|
||||
return diagnostic.file && diagnostic.file.fileName.indexOf("test262-harness") >= 0;
|
||||
});
|
||||
|
||||
// Verify we didn't miss any errors in total
|
||||
@@ -1433,17 +1404,6 @@ module Harness {
|
||||
//harnessCompiler.compileString(code, unitName, callback);
|
||||
}
|
||||
|
||||
export interface HarnessDiagnostic {
|
||||
fileName: string;
|
||||
start: number;
|
||||
end: number;
|
||||
line: number;
|
||||
character: number;
|
||||
message: string;
|
||||
category: string;
|
||||
code: number;
|
||||
}
|
||||
|
||||
export interface GeneratedFile {
|
||||
fileName: string;
|
||||
code: string;
|
||||
@@ -1473,12 +1433,12 @@ module Harness {
|
||||
/** Contains the code and errors of a compilation and some helper methods to check its status. */
|
||||
export class CompilerResult {
|
||||
public files: GeneratedFile[] = [];
|
||||
public errors: HarnessDiagnostic[] = [];
|
||||
public errors: ts.Diagnostic[] = [];
|
||||
public declFilesCode: GeneratedFile[] = [];
|
||||
public sourceMaps: GeneratedFile[] = [];
|
||||
|
||||
/** @param fileResults an array of strings for the fileName and an ITextWriter with its code */
|
||||
constructor(fileResults: GeneratedFile[], errors: HarnessDiagnostic[], public program: ts.Program,
|
||||
constructor(fileResults: GeneratedFile[], errors: ts.Diagnostic[], public program: ts.Program,
|
||||
public currentDirectoryForProgram: string, private sourceMapData: ts.SourceMapData[]) {
|
||||
|
||||
fileResults.forEach(emittedFile => {
|
||||
@@ -1503,15 +1463,6 @@ module Harness {
|
||||
return Harness.SourceMapRecoder.getSourceMapRecord(this.sourceMapData, this.program, this.files);
|
||||
}
|
||||
}
|
||||
|
||||
public isErrorAt(line: number, column: number, message: string) {
|
||||
for (var i = 0; i < this.errors.length; i++) {
|
||||
if ((this.errors[i].line + 1) === line && (this.errors[i].character + 1) === column && this.errors[i].message === message)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -323,9 +323,8 @@ class ProjectRunner extends RunnerBase {
|
||||
sourceFile => {
|
||||
return { unitName: sourceFile.fileName, content: sourceFile.text };
|
||||
});
|
||||
var diagnostics = ts.map(compilerResult.errors, error => Harness.Compiler.getMinimalDiagnostic(error));
|
||||
|
||||
return Harness.Compiler.getErrorBaseline(inputFiles, diagnostics);
|
||||
return Harness.Compiler.getErrorBaseline(inputFiles, compilerResult.errors);
|
||||
}
|
||||
|
||||
var name = 'Compiling project for ' + testCase.scenario + ': testcase ' + testCaseFileName;
|
||||
|
||||
Reference in New Issue
Block a user