mirror of
https://github.com/microsoft/TypeScript.git
synced 2025-11-18 17:21:48 +00:00
Merge branch 'master' into letAndConst
This commit is contained in:
+459
-391
File diff suppressed because it is too large
Load Diff
@@ -2899,7 +2899,7 @@ module ts {
|
||||
}
|
||||
return {
|
||||
diagnosticMessage: diagnosticMessage,
|
||||
errorNode: node.parameters[0],
|
||||
errorNode: <Node>node.parameters[0],
|
||||
typeName: node.name
|
||||
};
|
||||
}
|
||||
@@ -2920,7 +2920,7 @@ module ts {
|
||||
}
|
||||
return {
|
||||
diagnosticMessage: diagnosticMessage,
|
||||
errorNode: node.name,
|
||||
errorNode: <Node>node.name,
|
||||
typeName: undefined
|
||||
};
|
||||
}
|
||||
|
||||
+78
-13
@@ -227,6 +227,8 @@ module ts {
|
||||
return children((<TupleTypeNode>node).elementTypes);
|
||||
case SyntaxKind.UnionType:
|
||||
return children((<UnionTypeNode>node).types);
|
||||
case SyntaxKind.ParenType:
|
||||
return child((<ParenTypeNode>node).type);
|
||||
case SyntaxKind.ArrayLiteral:
|
||||
return children((<ArrayLiteral>node).elements);
|
||||
case SyntaxKind.ObjectLiteral:
|
||||
@@ -1078,7 +1080,7 @@ module ts {
|
||||
return isParameter();
|
||||
case ParsingContext.TypeArguments:
|
||||
case ParsingContext.TupleElementTypes:
|
||||
return isType();
|
||||
return token === SyntaxKind.CommaToken || isType();
|
||||
}
|
||||
|
||||
Debug.fail("Non-exhaustive case in 'isListElement'.");
|
||||
@@ -1660,6 +1662,14 @@ module ts {
|
||||
return finishNode(node);
|
||||
}
|
||||
|
||||
function parseParenType(): ParenTypeNode {
|
||||
var node = <ParenTypeNode>createNode(SyntaxKind.ParenType);
|
||||
parseExpected(SyntaxKind.OpenParenToken);
|
||||
node.type = parseType();
|
||||
parseExpected(SyntaxKind.CloseParenToken);
|
||||
return finishNode(node);
|
||||
}
|
||||
|
||||
function parseFunctionType(signatureKind: SyntaxKind): TypeLiteralNode {
|
||||
var node = <TypeLiteralNode>createNode(SyntaxKind.TypeLiteral);
|
||||
var member = <SignatureDeclaration>createNode(signatureKind);
|
||||
@@ -1693,10 +1703,7 @@ module ts {
|
||||
case SyntaxKind.OpenBracketToken:
|
||||
return parseTupleType();
|
||||
case SyntaxKind.OpenParenToken:
|
||||
case SyntaxKind.LessThanToken:
|
||||
return parseFunctionType(SyntaxKind.CallSignature);
|
||||
case SyntaxKind.NewKeyword:
|
||||
return parseFunctionType(SyntaxKind.ConstructSignature);
|
||||
return parseParenType();
|
||||
default:
|
||||
if (isIdentifier()) {
|
||||
return parseTypeReference();
|
||||
@@ -1720,18 +1727,18 @@ module ts {
|
||||
case SyntaxKind.NewKeyword:
|
||||
return true;
|
||||
case SyntaxKind.OpenParenToken:
|
||||
// Only consider an ( as the start of a type if we have () or (id
|
||||
// We don't want to consider things like (1) as a function type.
|
||||
// Only consider '(' the start of a type if followed by ')', '...', an identifier, a modifier,
|
||||
// or something that starts a type. We don't want to consider things like '(1)' a type.
|
||||
return lookAhead(() => {
|
||||
nextToken();
|
||||
return token === SyntaxKind.CloseParenToken || isParameter();
|
||||
return token === SyntaxKind.CloseParenToken || isParameter() || isType();
|
||||
});
|
||||
default:
|
||||
return isIdentifier();
|
||||
}
|
||||
}
|
||||
|
||||
function parseNonUnionType(): TypeNode {
|
||||
function parsePrimaryType(): TypeNode {
|
||||
var type = parseNonArrayType();
|
||||
while (!scanner.hasPrecedingLineBreak() && parseOptional(SyntaxKind.OpenBracketToken)) {
|
||||
parseExpected(SyntaxKind.CloseBracketToken);
|
||||
@@ -1742,13 +1749,13 @@ module ts {
|
||||
return type;
|
||||
}
|
||||
|
||||
function parseType(): TypeNode {
|
||||
var type = parseNonUnionType();
|
||||
function parseUnionType(): TypeNode {
|
||||
var type = parsePrimaryType();
|
||||
if (token === SyntaxKind.BarToken) {
|
||||
var types = <NodeArray<TypeNode>>[type];
|
||||
types.pos = type.pos;
|
||||
while (parseOptional(SyntaxKind.BarToken)) {
|
||||
types.push(parseNonUnionType());
|
||||
types.push(parsePrimaryType());
|
||||
}
|
||||
types.end = getNodeEnd();
|
||||
var node = <UnionTypeNode>createNode(SyntaxKind.UnionType, type.pos);
|
||||
@@ -1758,6 +1765,48 @@ module ts {
|
||||
return type;
|
||||
}
|
||||
|
||||
function isFunctionType(): boolean {
|
||||
return token === SyntaxKind.LessThanToken || token === SyntaxKind.OpenParenToken && lookAhead(() => {
|
||||
nextToken();
|
||||
if (token === SyntaxKind.CloseParenToken || token === SyntaxKind.DotDotDotToken) {
|
||||
// ( )
|
||||
// ( ...
|
||||
return true;
|
||||
}
|
||||
if (isIdentifier() || isModifier(token)) {
|
||||
nextToken();
|
||||
if (token === SyntaxKind.ColonToken || token === SyntaxKind.CommaToken ||
|
||||
token === SyntaxKind.QuestionToken || token === SyntaxKind.EqualsToken ||
|
||||
isIdentifier() || isModifier(token)) {
|
||||
// ( id :
|
||||
// ( id ,
|
||||
// ( id ?
|
||||
// ( id =
|
||||
// ( modifier id
|
||||
return true;
|
||||
}
|
||||
if (token === SyntaxKind.CloseParenToken) {
|
||||
nextToken();
|
||||
if (token === SyntaxKind.EqualsGreaterThanToken) {
|
||||
// ( id ) =>
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
function parseType(): TypeNode {
|
||||
if (isFunctionType()) {
|
||||
return parseFunctionType(SyntaxKind.CallSignature);
|
||||
}
|
||||
if (token === SyntaxKind.NewKeyword) {
|
||||
return parseFunctionType(SyntaxKind.ConstructSignature);
|
||||
}
|
||||
return parseUnionType();
|
||||
}
|
||||
|
||||
function parseTypeAnnotation(): TypeNode {
|
||||
return parseOptional(SyntaxKind.ColonToken) ? parseType() : undefined;
|
||||
}
|
||||
@@ -2344,13 +2393,29 @@ module ts {
|
||||
function parseTypeArguments(): NodeArray<TypeNode> {
|
||||
var typeArgumentListStart = scanner.getTokenPos();
|
||||
var errorCountBeforeTypeParameterList = file.syntacticErrors.length;
|
||||
var result = parseBracketedList(ParsingContext.TypeArguments, parseType, SyntaxKind.LessThanToken, SyntaxKind.GreaterThanToken);
|
||||
// We pass parseSingleTypeArgument instead of parseType as the element parser
|
||||
// because parseSingleTypeArgument knows how to parse a missing type argument.
|
||||
// This is useful for signature help. parseType has the disadvantage that when
|
||||
// it sees a missing type, it changes the LookAheadMode to Error, and the result
|
||||
// is a broken binary expression, which breaks signature help.
|
||||
var result = parseBracketedList(ParsingContext.TypeArguments, parseSingleTypeArgument, SyntaxKind.LessThanToken, SyntaxKind.GreaterThanToken);
|
||||
if (!result.length && file.syntacticErrors.length === errorCountBeforeTypeParameterList) {
|
||||
grammarErrorAtPos(typeArgumentListStart, scanner.getStartPos() - typeArgumentListStart, Diagnostics.Type_argument_list_cannot_be_empty);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
function parseSingleTypeArgument(): TypeNode {
|
||||
if (token === SyntaxKind.CommaToken) {
|
||||
var errorStart = scanner.getTokenPos();
|
||||
var errorLength = scanner.getTextPos() - errorStart;
|
||||
grammarErrorAtPos(errorStart, errorLength, Diagnostics.Type_expected);
|
||||
return createNode(SyntaxKind.Missing);
|
||||
}
|
||||
|
||||
return parseType();
|
||||
}
|
||||
|
||||
function parsePrimaryExpression(): Expression {
|
||||
switch (token) {
|
||||
case SyntaxKind.ThisKeyword:
|
||||
|
||||
+21
-6
@@ -155,6 +155,7 @@ module ts {
|
||||
ArrayType,
|
||||
TupleType,
|
||||
UnionType,
|
||||
ParenType,
|
||||
// Expression
|
||||
ArrayLiteral,
|
||||
ObjectLiteral,
|
||||
@@ -225,7 +226,7 @@ module ts {
|
||||
FirstFutureReservedWord = ImplementsKeyword,
|
||||
LastFutureReservedWord = YieldKeyword,
|
||||
FirstTypeNode = TypeReference,
|
||||
LastTypeNode = UnionType,
|
||||
LastTypeNode = ParenType,
|
||||
FirstPunctuation = OpenBraceToken,
|
||||
LastPunctuation = CaretEqualsToken,
|
||||
FirstToken = EndOfFileToken,
|
||||
@@ -345,6 +346,10 @@ module ts {
|
||||
types: NodeArray<TypeNode>;
|
||||
}
|
||||
|
||||
export interface ParenTypeNode extends TypeNode {
|
||||
type: TypeNode;
|
||||
}
|
||||
|
||||
export interface StringLiteralTypeNode extends TypeNode {
|
||||
text: string;
|
||||
}
|
||||
@@ -651,18 +656,14 @@ module ts {
|
||||
getTypeOfNode(node: Node): Type;
|
||||
getApparentType(type: Type): ApparentType;
|
||||
typeToString(type: Type, enclosingDeclaration?: Node, flags?: TypeFormatFlags): string;
|
||||
writeType(type: Type, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags): void;
|
||||
symbolToString(symbol: Symbol, enclosingDeclaration?: Node, meaning?: SymbolFlags): string;
|
||||
writeSymbol(symbol: Symbol, writer: SymbolWriter, enclosingDeclaration?: Node, meaning?: SymbolFlags, flags?: SymbolFormatFlags): void;
|
||||
getSymbolDisplayBuilder(): SymbolDisplayBuilder;
|
||||
getFullyQualifiedName(symbol: Symbol): string;
|
||||
getAugmentedPropertiesOfApparentType(type: Type): Symbol[];
|
||||
getRootSymbols(symbol: Symbol): Symbol[];
|
||||
getContextualType(node: Node): Type;
|
||||
getResolvedSignature(node: CallExpression, candidatesOutArray?: Signature[]): Signature;
|
||||
getSignatureFromDeclaration(declaration: SignatureDeclaration): Signature;
|
||||
writeSignature(signatures: Signature, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags): void;
|
||||
writeTypeParameter(tp: TypeParameter, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags): void;
|
||||
writeTypeParametersOfSymbol(symbol: Symbol, writer: SymbolWriter, enclosingDeclaraiton?: Node, flags?: TypeFormatFlags): void;
|
||||
isImplementationOfOverload(node: FunctionDeclaration): boolean;
|
||||
isUndefinedSymbol(symbol: Symbol): boolean;
|
||||
isArgumentsSymbol(symbol: Symbol): boolean;
|
||||
@@ -675,6 +676,18 @@ module ts {
|
||||
getAliasedSymbol(symbol: Symbol): Symbol;
|
||||
}
|
||||
|
||||
export interface SymbolDisplayBuilder {
|
||||
buildTypeDisplay(type: Type, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags): void;
|
||||
buildSymbolDisplay(symbol: Symbol, writer: SymbolWriter, enclosingDeclaration?: Node, meaning?: SymbolFlags, flags?: SymbolFormatFlags): void;
|
||||
buildSignatureDisplay(signatures: Signature, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags): void;
|
||||
buildParameterDisplay(parameter: Symbol, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags): void;
|
||||
buildTypeParameterDisplay(tp: TypeParameter, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags): void;
|
||||
buildTypeParameterDisplayFromSymbol(symbol: Symbol, writer: SymbolWriter, enclosingDeclaraiton?: Node, flags?: TypeFormatFlags): void;
|
||||
buildDisplayForParametersAndDelimiters(parameters: Symbol[], writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags): void;
|
||||
buildDisplayForTypeParametersAndDelimiters(typeParameters: TypeParameter[], writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags): void;
|
||||
buildReturnTypeDisplay(signature: Signature, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags): void;
|
||||
}
|
||||
|
||||
export interface SymbolWriter {
|
||||
writeKeyword(text: string): void;
|
||||
writeOperator(text: string): void;
|
||||
@@ -702,6 +715,7 @@ module ts {
|
||||
WriteArrowStyleSignature = 0x00000008, // Write arrow style signature
|
||||
WriteOwnNameForAnyLike = 0x00000010, // Write symbol's own name instead of 'any' for any like types (eg. unknown, __resolving__ etc)
|
||||
WriteTypeArgumentsOfSignature = 0x00000020, // Write the type arguments instead of type parameters of the signature
|
||||
InElementType = 0x00000040, // Writing an array or union element type
|
||||
}
|
||||
|
||||
export enum SymbolFormatFlags {
|
||||
@@ -1017,6 +1031,7 @@ module ts {
|
||||
|
||||
export interface InferenceContext {
|
||||
typeParameters: TypeParameter[]; // Type parameters for which inferences are made
|
||||
inferUnionTypes: boolean; // Infer union types for disjoint candidates (otherwise undefinedType)
|
||||
inferenceCount: number; // Incremented for every inference made (whether new or not)
|
||||
inferences: Type[][]; // Inferences made for each type parameter
|
||||
inferredTypes: Type[]; // Inferred type for each type parameter
|
||||
|
||||
@@ -61,9 +61,11 @@ class CompilerBaselineRunner extends RunnerBase {
|
||||
var otherFiles: { unitName: string; content: string }[];
|
||||
var harnessCompiler: Harness.Compiler.HarnessCompiler;
|
||||
|
||||
var declToBeCompiled: { unitName: string; content: string }[] = [];
|
||||
var declOtherFiles: { unitName: string; content: string }[] = [];
|
||||
var declResult: Harness.Compiler.CompilerResult;
|
||||
var declFileCompilationResult: {
|
||||
declInputFiles: { unitName: string; content: string }[];
|
||||
declOtherFiles: { unitName: string; content: string }[];
|
||||
declResult: Harness.Compiler.CompilerResult;
|
||||
};
|
||||
|
||||
var createNewInstance = false;
|
||||
|
||||
@@ -147,9 +149,7 @@ class CompilerBaselineRunner extends RunnerBase {
|
||||
toBeCompiled = undefined;
|
||||
otherFiles = undefined;
|
||||
harnessCompiler = undefined;
|
||||
declToBeCompiled = undefined;
|
||||
declOtherFiles = undefined;
|
||||
declResult = undefined;
|
||||
declFileCompilationResult = undefined;
|
||||
});
|
||||
|
||||
function getByteOrderMarkText(file: Harness.Compiler.GeneratedFile): string {
|
||||
@@ -173,61 +173,18 @@ class CompilerBaselineRunner extends RunnerBase {
|
||||
|
||||
// Source maps?
|
||||
it('Correct sourcemap content for ' + fileName, () => {
|
||||
if (result.sourceMapRecord) {
|
||||
if (options.sourceMap) {
|
||||
Harness.Baseline.runBaseline('Correct sourcemap content for ' + fileName, justName.replace(/\.ts$/, '.sourcemap.txt'), () => {
|
||||
return result.sourceMapRecord;
|
||||
return result.getSourceMapRecord();
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// Compile .d.ts files
|
||||
it('Correct compiler generated.d.ts for ' + fileName, () => {
|
||||
if (options.declaration && result.errors.length === 0 && result.declFilesCode.length !== result.files.length) {
|
||||
throw new Error('There were no errors and declFiles generated did not match number of js files generated');
|
||||
}
|
||||
|
||||
// if the .d.ts is non-empty, confirm it compiles correctly as well
|
||||
if (options.declaration && result.errors.length === 0 && result.declFilesCode.length > 0) {
|
||||
function addDtsFile(file: { unitName: string; content: string }, dtsFiles: { unitName: string; content: string }[]) {
|
||||
if (Harness.Compiler.isDTS(file.unitName)) {
|
||||
dtsFiles.push(file);
|
||||
}
|
||||
else {
|
||||
var declFile = findResultCodeFile(file.unitName);
|
||||
// Look if there is --out file corresponding to this ts file
|
||||
if (!declFile && options.out) {
|
||||
declFile = findResultCodeFile(options.out);
|
||||
if (!declFile || findUnit(declFile.fileName, declToBeCompiled) ||
|
||||
findUnit(declFile.fileName, declOtherFiles)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (declFile) {
|
||||
dtsFiles.push({ unitName: declFile.fileName, content: declFile.code });
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
function findResultCodeFile(fileName: string) {
|
||||
return ts.forEach(result.declFilesCode,
|
||||
declFile => declFile.fileName === (fileName.substr(0, fileName.length - ".ts".length) + ".d.ts")
|
||||
? declFile : undefined);
|
||||
}
|
||||
|
||||
function findUnit(fileName: string, units: { unitName: string; content: string }[]) {
|
||||
return ts.forEach(units, unit => unit.unitName === fileName ? unit : undefined);
|
||||
}
|
||||
}
|
||||
|
||||
ts.forEach(toBeCompiled, file => addDtsFile(file, declToBeCompiled));
|
||||
ts.forEach(otherFiles, file => addDtsFile(file, declOtherFiles));
|
||||
harnessCompiler.compileFiles(declToBeCompiled, declOtherFiles, function (compileResult) {
|
||||
declResult = compileResult;
|
||||
}, function (settings) {
|
||||
harnessCompiler.setCompilerSettings(tcSettings);
|
||||
});
|
||||
}
|
||||
declFileCompilationResult = harnessCompiler.compileDeclarationFiles(toBeCompiled, otherFiles, result, function (settings) {
|
||||
harnessCompiler.setCompilerSettings(tcSettings);
|
||||
}, options);
|
||||
});
|
||||
|
||||
|
||||
@@ -267,10 +224,10 @@ class CompilerBaselineRunner extends RunnerBase {
|
||||
}
|
||||
}
|
||||
|
||||
if (declResult && declResult.errors.length) {
|
||||
if (declFileCompilationResult && declFileCompilationResult.declResult.errors.length) {
|
||||
jsCode += '\r\n\r\n//// [DtsFileErrors]\r\n';
|
||||
jsCode += '\r\n\r\n';
|
||||
jsCode += getErrorBaseline(declToBeCompiled, declOtherFiles, declResult);
|
||||
jsCode += getErrorBaseline(declFileCompilationResult.declInputFiles, declFileCompilationResult.declOtherFiles, declFileCompilationResult.declResult);
|
||||
}
|
||||
|
||||
if (jsCode.length > 0) {
|
||||
|
||||
+86
-13
@@ -139,6 +139,7 @@ module Harness {
|
||||
deleteFile(filename: string): void;
|
||||
listFiles(path: string, filter: RegExp, options?: { recursive?: boolean }): string[];
|
||||
log(text: string): void;
|
||||
getMemoryUsage? (): number;
|
||||
}
|
||||
|
||||
module IOImpl {
|
||||
@@ -275,6 +276,13 @@ module Harness {
|
||||
|
||||
return filesInFolder(path);
|
||||
}
|
||||
|
||||
export var getMemoryUsage: typeof IO.getMemoryUsage = () => {
|
||||
if (global.gc) {
|
||||
global.gc();
|
||||
}
|
||||
return process.memoryUsage().heapUsed;
|
||||
}
|
||||
}
|
||||
|
||||
export module Network {
|
||||
@@ -806,15 +814,81 @@ module Harness {
|
||||
});
|
||||
this.lastErrors = errors;
|
||||
|
||||
var result = new CompilerResult(fileOutputs, errors, []);
|
||||
// Covert the source Map data into the baseline
|
||||
result.updateSourceMapRecord(program, emitResult ? emitResult.sourceMaps : undefined);
|
||||
var result = new CompilerResult(fileOutputs, errors, program, sys.getCurrentDirectory(), emitResult ? emitResult.sourceMaps : undefined);
|
||||
onComplete(result, checker);
|
||||
|
||||
// reset what newline means in case the last test changed it
|
||||
sys.newLine = '\r\n';
|
||||
return options;
|
||||
}
|
||||
|
||||
public compileDeclarationFiles(inputFiles: { unitName: string; content: string; }[],
|
||||
otherFiles: { unitName: string; content: string; }[],
|
||||
result: CompilerResult,
|
||||
settingsCallback?: (settings: ts.CompilerOptions) => void,
|
||||
options?: ts.CompilerOptions) {
|
||||
if (options.declaration && result.errors.length === 0 && result.declFilesCode.length !== result.files.length) {
|
||||
throw new Error('There were no errors and declFiles generated did not match number of js files generated');
|
||||
}
|
||||
|
||||
// if the .d.ts is non-empty, confirm it compiles correctly as well
|
||||
if (options.declaration && result.errors.length === 0 && result.declFilesCode.length > 0) {
|
||||
var declInputFiles: { unitName: string; content: string }[] = [];
|
||||
var declOtherFiles: { unitName: string; content: string }[] = [];
|
||||
var declResult: Harness.Compiler.CompilerResult;
|
||||
|
||||
ts.forEach(inputFiles, file => addDtsFile(file, declInputFiles));
|
||||
ts.forEach(otherFiles, file => addDtsFile(file, declOtherFiles));
|
||||
this.compileFiles(declInputFiles, declOtherFiles, function (compileResult) {
|
||||
declResult = compileResult;
|
||||
}, settingsCallback, options);
|
||||
|
||||
return { declInputFiles: declInputFiles, declOtherFiles: declOtherFiles, declResult: declResult };
|
||||
}
|
||||
|
||||
function addDtsFile(file: { unitName: string; content: string }, dtsFiles: { unitName: string; content: string }[]) {
|
||||
if (isDTS(file.unitName)) {
|
||||
dtsFiles.push(file);
|
||||
}
|
||||
else if (isTS(file.unitName)) {
|
||||
var declFile = findResultCodeFile(file.unitName);
|
||||
if (!findUnit(declFile.fileName, declInputFiles) && !findUnit(declFile.fileName, declOtherFiles)) {
|
||||
dtsFiles.push({ unitName: declFile.fileName, content: declFile.code });
|
||||
}
|
||||
}
|
||||
|
||||
function findResultCodeFile(fileName: string) {
|
||||
var dTsFileName = ts.forEach(result.program.getSourceFiles(), sourceFile => {
|
||||
if (sourceFile.filename === fileName) {
|
||||
// Is this file going to be emitted separately
|
||||
var sourceFileName: string;
|
||||
if (ts.isExternalModule(sourceFile) || !options.out) {
|
||||
if (options.outDir) {
|
||||
var sourceFilePath = ts.getNormalizedPathFromPathComponents(ts.getNormalizedPathComponents(sourceFile.filename, result.currentDirectoryForProgram));
|
||||
sourceFilePath = sourceFilePath.replace(result.program.getCommonSourceDirectory(), "");
|
||||
sourceFileName = ts.combinePaths(options.outDir, sourceFilePath);
|
||||
}
|
||||
else {
|
||||
sourceFileName = sourceFile.filename;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Goes to single --out file
|
||||
sourceFileName = options.out;
|
||||
}
|
||||
|
||||
return ts.removeFileExtension(sourceFileName) + ".d.ts";
|
||||
}
|
||||
});
|
||||
|
||||
return ts.forEach(result.declFilesCode, declFile => declFile.fileName === dTsFileName ? declFile : undefined);
|
||||
}
|
||||
|
||||
function findUnit(fileName: string, units: { unitName: string; content: string; }[]) {
|
||||
return ts.forEach(units, unit => unit.unitName === fileName ? unit : undefined);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function getMinimalDiagnostic(err: ts.Diagnostic): HarnessDiagnostic {
|
||||
@@ -950,10 +1024,6 @@ module Harness {
|
||||
}
|
||||
*/
|
||||
|
||||
/** Recreate the harness compiler instance to its default settings */
|
||||
export function recreate(options?: { useMinimalDefaultLib: boolean; noImplicitAny: boolean; }) {
|
||||
}
|
||||
|
||||
/** The harness' compiler instance used when tests are actually run. Reseting or changing settings of this compiler instance must be done within a test case (i.e., describe/it) */
|
||||
var harnessCompiler: HarnessCompiler;
|
||||
|
||||
@@ -993,6 +1063,10 @@ module Harness {
|
||||
return str.substr(str.length - end.length) === end;
|
||||
}
|
||||
|
||||
export function isTS(fileName: string) {
|
||||
return stringEndsWith(fileName, '.ts');
|
||||
}
|
||||
|
||||
export function isDTS(fileName: string) {
|
||||
return stringEndsWith(fileName, '.d.ts');
|
||||
}
|
||||
@@ -1011,10 +1085,10 @@ module Harness {
|
||||
public errors: HarnessDiagnostic[] = [];
|
||||
public declFilesCode: GeneratedFile[] = [];
|
||||
public sourceMaps: GeneratedFile[] = [];
|
||||
public sourceMapRecord: string;
|
||||
|
||||
/** @param fileResults an array of strings for the fileName and an ITextWriter with its code */
|
||||
constructor(fileResults: GeneratedFile[], errors: HarnessDiagnostic[], sourceMapRecordLines: string[]) {
|
||||
constructor(fileResults: GeneratedFile[], errors: HarnessDiagnostic[], public program: ts.Program,
|
||||
public currentDirectoryForProgram: string, private sourceMapData: ts.SourceMapData[]) {
|
||||
var lines: string[] = [];
|
||||
|
||||
fileResults.forEach(emittedFile => {
|
||||
@@ -1032,12 +1106,11 @@ module Harness {
|
||||
});
|
||||
|
||||
this.errors = errors;
|
||||
this.sourceMapRecord = sourceMapRecordLines.join('\r\n');
|
||||
}
|
||||
|
||||
public updateSourceMapRecord(program: ts.Program, sourceMapData: ts.SourceMapData[]) {
|
||||
if (sourceMapData) {
|
||||
this.sourceMapRecord = Harness.SourceMapRecoder.getSourceMapRecord(sourceMapData, program, this.files);
|
||||
public getSourceMapRecord() {
|
||||
if (this.sourceMapData) {
|
||||
return Harness.SourceMapRecoder.getSourceMapRecord(this.sourceMapData, this.program, this.files);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -419,6 +419,16 @@ class ProjectRunner extends RunnerBase {
|
||||
// })
|
||||
//});
|
||||
}
|
||||
|
||||
after(() => {
|
||||
// Mocha holds onto the closure environment of the describe callback even after the test is done.
|
||||
// Therefore we have to clean out large objects after the test is done.
|
||||
nodeCompilerResult = undefined;
|
||||
amdCompilerResult = undefined;
|
||||
testCase = undefined;
|
||||
testFileText = undefined;
|
||||
testCaseJustName = undefined;
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
+138
-111
@@ -46,144 +46,171 @@ module RWC {
|
||||
}
|
||||
|
||||
export function runRWCTest(jsonPath: string) {
|
||||
var harnessCompiler = Harness.Compiler.getCompiler();
|
||||
var opts: ts.ParsedCommandLine;
|
||||
describe("Testing a RWC project: " + jsonPath, () => {
|
||||
var inputFiles: { unitName: string; content: string; }[] = [];
|
||||
var otherFiles: { unitName: string; content: string; }[] = [];
|
||||
var compilerResult: Harness.Compiler.CompilerResult;
|
||||
var compilerOptions: ts.CompilerOptions;
|
||||
var baselineOpts: Harness.Baseline.BaselineOptions = { Subfolder: 'rwc' };
|
||||
var baseName = /(.*)\/(.*).json/.exec(Harness.Path.switchToForwardSlashes(jsonPath))[2];
|
||||
// Compile .d.ts files
|
||||
var declFileCompilationResult: {
|
||||
declInputFiles: { unitName: string; content: string }[];
|
||||
declOtherFiles: { unitName: string; content: string }[];
|
||||
declResult: Harness.Compiler.CompilerResult;
|
||||
};
|
||||
|
||||
var ioLog: IOLog = JSON.parse(Harness.IO.readFile(jsonPath));
|
||||
var errors = '';
|
||||
|
||||
it('has parsable options', () => {
|
||||
runWithIOLog(ioLog, () => {
|
||||
opts = ts.parseCommandLine(ioLog.arguments);
|
||||
assert.equal(opts.errors.length, 0);
|
||||
});
|
||||
});
|
||||
|
||||
var inputFiles: { unitName: string; content: string; }[] = [];
|
||||
var otherFiles: { unitName: string; content: string; }[] = [];
|
||||
var compilerResult: Harness.Compiler.CompilerResult;
|
||||
it('can compile', () => {
|
||||
runWithIOLog(ioLog, () => {
|
||||
harnessCompiler.reset();
|
||||
|
||||
// Load the files
|
||||
ts.forEach(opts.filenames, fileName => {
|
||||
inputFiles.push(getHarnessCompilerInputUnit(fileName));
|
||||
});
|
||||
|
||||
if (!opts.options.noLib) {
|
||||
// Find the lib.d.ts file in the input file and add it to the input files list
|
||||
var libFile = ts.forEach(ioLog.filesRead, fileRead=> Harness.isLibraryFile(fileRead.path) ? fileRead.path : undefined);
|
||||
if (libFile) {
|
||||
inputFiles.push(getHarnessCompilerInputUnit(libFile));
|
||||
}
|
||||
}
|
||||
|
||||
ts.forEach(ioLog.filesRead, fileRead => {
|
||||
var resolvedPath = Harness.Path.switchToForwardSlashes(sys.resolvePath(fileRead.path));
|
||||
var inInputList = ts.forEach(inputFiles, inputFile=> inputFile.unitName === resolvedPath);
|
||||
if (!inInputList) {
|
||||
// Add the file to other files
|
||||
otherFiles.push(getHarnessCompilerInputUnit(fileRead.path));
|
||||
}
|
||||
});
|
||||
|
||||
// do not use lib since we already read it in above
|
||||
opts.options.noLib = true;
|
||||
|
||||
// Emit the results
|
||||
harnessCompiler.compileFiles(inputFiles, otherFiles, compileResult => {
|
||||
compilerResult = compileResult;
|
||||
}, /*settingsCallback*/ undefined, opts.options);
|
||||
after(() => {
|
||||
// Mocha holds onto the closure environment of the describe callback even after the test is done.
|
||||
// Therefore we have to clean out large objects after the test is done.
|
||||
inputFiles = undefined;
|
||||
otherFiles = undefined;
|
||||
compilerResult = undefined;
|
||||
compilerOptions = undefined;
|
||||
baselineOpts = undefined;
|
||||
baseName = undefined;
|
||||
declFileCompilationResult = undefined;
|
||||
});
|
||||
|
||||
function getHarnessCompilerInputUnit(fileName: string) {
|
||||
var resolvedPath = Harness.Path.switchToForwardSlashes(sys.resolvePath(fileName));
|
||||
try {
|
||||
var content = sys.readFile(resolvedPath);
|
||||
it('can compile', () => {
|
||||
var harnessCompiler = Harness.Compiler.getCompiler();
|
||||
var opts: ts.ParsedCommandLine;
|
||||
|
||||
var ioLog: IOLog = JSON.parse(Harness.IO.readFile(jsonPath));
|
||||
runWithIOLog(ioLog, () => {
|
||||
opts = ts.parseCommandLine(ioLog.arguments);
|
||||
assert.equal(opts.errors.length, 0);
|
||||
});
|
||||
|
||||
runWithIOLog(ioLog, () => {
|
||||
harnessCompiler.reset();
|
||||
|
||||
// Load the files
|
||||
ts.forEach(opts.filenames, fileName => {
|
||||
inputFiles.push(getHarnessCompilerInputUnit(fileName));
|
||||
});
|
||||
|
||||
if (!opts.options.noLib) {
|
||||
// Find the lib.d.ts file in the input file and add it to the input files list
|
||||
var libFile = ts.forEach(ioLog.filesRead, fileRead=> Harness.isLibraryFile(fileRead.path) ? fileRead.path : undefined);
|
||||
if (libFile) {
|
||||
inputFiles.push(getHarnessCompilerInputUnit(libFile));
|
||||
}
|
||||
}
|
||||
|
||||
ts.forEach(ioLog.filesRead, fileRead => {
|
||||
var resolvedPath = Harness.Path.switchToForwardSlashes(sys.resolvePath(fileRead.path));
|
||||
var inInputList = ts.forEach(inputFiles, inputFile=> inputFile.unitName === resolvedPath);
|
||||
if (!inInputList) {
|
||||
// Add the file to other files
|
||||
otherFiles.push(getHarnessCompilerInputUnit(fileRead.path));
|
||||
}
|
||||
});
|
||||
|
||||
// do not use lib since we already read it in above
|
||||
opts.options.noLib = true;
|
||||
|
||||
// Emit the results
|
||||
compilerOptions = harnessCompiler.compileFiles(inputFiles, otherFiles, compileResult => {
|
||||
compilerResult = compileResult;
|
||||
}, /*settingsCallback*/ undefined, opts.options);
|
||||
});
|
||||
|
||||
function getHarnessCompilerInputUnit(fileName: string) {
|
||||
var resolvedPath = Harness.Path.switchToForwardSlashes(sys.resolvePath(fileName));
|
||||
try {
|
||||
var content = sys.readFile(resolvedPath);
|
||||
}
|
||||
catch (e) {
|
||||
// Leave content undefined.
|
||||
}
|
||||
return { unitName: resolvedPath, content: content };
|
||||
}
|
||||
catch (e) {
|
||||
// Leave content undefined.
|
||||
}
|
||||
return { unitName: resolvedPath, content: content };
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// Baselines
|
||||
var baselineOpts: Harness.Baseline.BaselineOptions = { Subfolder: 'rwc' };
|
||||
var baseName = /(.*)\/(.*).json/.exec(Harness.Path.switchToForwardSlashes(jsonPath))[2];
|
||||
// Baselines
|
||||
it('Correct compiler generated.d.ts', () => {
|
||||
declFileCompilationResult = Harness.Compiler.getCompiler().compileDeclarationFiles(inputFiles, otherFiles, compilerResult, /*settingscallback*/ undefined, compilerOptions);
|
||||
});
|
||||
|
||||
it('has the expected emitted code', () => {
|
||||
Harness.Baseline.runBaseline('has the expected emitted code', baseName + '.output.js', () => {
|
||||
return collateOutputs(compilerResult.files, s => SyntacticCleaner.clean(s));
|
||||
}, false, baselineOpts);
|
||||
});
|
||||
|
||||
it('has the expected declaration file content', () => {
|
||||
Harness.Baseline.runBaseline('has the expected declaration file content', baseName + '.d.ts', () => {
|
||||
if (compilerResult.errors.length || !compilerResult.declFilesCode.length) {
|
||||
return null;
|
||||
}
|
||||
return collateOutputs(compilerResult.declFilesCode);
|
||||
}, false, baselineOpts);
|
||||
});
|
||||
|
||||
it('has the expected source maps', () => {
|
||||
Harness.Baseline.runBaseline('has the expected source maps', baseName + '.map', () => {
|
||||
if (!compilerResult.sourceMaps.length) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return collateOutputs(compilerResult.sourceMaps);
|
||||
}, false, baselineOpts);
|
||||
});
|
||||
|
||||
it('has correct source map record', () => {
|
||||
if (compilerResult.sourceMapRecord) {
|
||||
Harness.Baseline.runBaseline('has correct source map record', baseName + '.sourcemap.txt', () => {
|
||||
return compilerResult.sourceMapRecord;
|
||||
it('has the expected emitted code', () => {
|
||||
Harness.Baseline.runBaseline('has the expected emitted code', baseName + '.output.js', () => {
|
||||
return collateOutputs(compilerResult.files, s => SyntacticCleaner.clean(s));
|
||||
}, false, baselineOpts);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
it('has the expected errors', () => {
|
||||
Harness.Baseline.runBaseline('has the expected errors', baseName + '.errors.txt', () => {
|
||||
if (compilerResult.errors.length === 0) {
|
||||
return null;
|
||||
it('has the expected declaration file content', () => {
|
||||
Harness.Baseline.runBaseline('has the expected declaration file content', baseName + '.d.ts', () => {
|
||||
if (compilerResult.errors.length || !compilerResult.declFilesCode.length) {
|
||||
return null;
|
||||
}
|
||||
return collateOutputs(compilerResult.declFilesCode);
|
||||
}, false, baselineOpts);
|
||||
});
|
||||
|
||||
it('has the expected source maps', () => {
|
||||
Harness.Baseline.runBaseline('has the expected source maps', baseName + '.map', () => {
|
||||
if (!compilerResult.sourceMaps.length) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return collateOutputs(compilerResult.sourceMaps);
|
||||
}, false, baselineOpts);
|
||||
});
|
||||
|
||||
//it('has correct source map record', () => {
|
||||
// if (compilerOptions.sourceMap) {
|
||||
// Harness.Baseline.runBaseline('has correct source map record', baseName + '.sourcemap.txt', () => {
|
||||
// return compilerResult.getSourceMapRecord();
|
||||
// }, false, baselineOpts);
|
||||
// }
|
||||
//});
|
||||
|
||||
it('has the expected errors', () => {
|
||||
Harness.Baseline.runBaseline('has the expected errors', baseName + '.errors.txt', () => {
|
||||
if (compilerResult.errors.length === 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return Harness.Compiler.getErrorBaseline(inputFiles.concat(otherFiles), compilerResult.errors);
|
||||
}, false, baselineOpts);
|
||||
});
|
||||
|
||||
it('has no errors in generated declaration files', () => {
|
||||
if (compilerOptions.declaration && !compilerResult.errors.length) {
|
||||
Harness.Baseline.runBaseline('has no errors in generated declaration files', baseName + '.dts.errors.txt', () => {
|
||||
if (declFileCompilationResult.declResult.errors.length === 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return Harness.Compiler.minimalDiagnosticsToString(declFileCompilationResult.declResult.errors) +
|
||||
sys.newLine + sys.newLine +
|
||||
Harness.Compiler.getErrorBaseline(declFileCompilationResult.declInputFiles.concat(declFileCompilationResult.declOtherFiles), declFileCompilationResult.declResult.errors);
|
||||
}, false, baselineOpts);
|
||||
}
|
||||
});
|
||||
|
||||
return Harness.Compiler.getErrorBaseline(inputFiles.concat(otherFiles), compilerResult.errors);
|
||||
}, false, baselineOpts);
|
||||
// TODO: Type baselines (need to refactor out from compilerRunner)
|
||||
});
|
||||
|
||||
// TODO: Type baselines (need to refactor out from compilerRunner)
|
||||
}
|
||||
}
|
||||
|
||||
class RWCRunner extends RunnerBase {
|
||||
private runnerPath = "tests/runners/rwc";
|
||||
private sourcePath = "tests/cases/rwc/";
|
||||
|
||||
private harnessCompiler: Harness.Compiler.HarnessCompiler;
|
||||
private static sourcePath = "tests/cases/rwc/";
|
||||
|
||||
/** Setup the runner's tests so that they are ready to be executed by the harness
|
||||
* The first test should be a describe/it block that sets up the harness's compiler instance appropriately
|
||||
*/
|
||||
public initializeTests(): void {
|
||||
// Recreate the compiler with the default lib
|
||||
Harness.Compiler.recreate({ useMinimalDefaultLib: false, noImplicitAny: false });
|
||||
this.harnessCompiler = Harness.Compiler.getCompiler();
|
||||
|
||||
// Read in and evaluate the test list
|
||||
var testList = Harness.IO.listFiles(this.sourcePath, /.+\.json$/);
|
||||
var testList = Harness.IO.listFiles(RWCRunner.sourcePath, /.+\.json$/);
|
||||
for (var i = 0; i < testList.length; i++) {
|
||||
this.runTest(testList[i]);
|
||||
}
|
||||
}
|
||||
|
||||
private runTest(jsonFilename: string) {
|
||||
describe("Testing a RWC project: " + jsonFilename, () => {
|
||||
RWC.runRWCTest(jsonFilename);
|
||||
});
|
||||
RWC.runRWCTest(jsonFilename);
|
||||
}
|
||||
}
|
||||
@@ -1462,7 +1462,7 @@ module ts {
|
||||
}
|
||||
}
|
||||
|
||||
function mapToDisplayParts(writeDisplayParts: (writer: DisplayPartsSymbolWriter) => void): SymbolDisplayPart[] {
|
||||
export function mapToDisplayParts(writeDisplayParts: (writer: DisplayPartsSymbolWriter) => void): SymbolDisplayPart[] {
|
||||
writeDisplayParts(displayPartWriter);
|
||||
var result = displayPartWriter.displayParts();
|
||||
displayPartWriter.clear();
|
||||
@@ -1471,19 +1471,19 @@ module ts {
|
||||
|
||||
export function typeToDisplayParts(typechecker: TypeChecker, type: Type, enclosingDeclaration?: Node, flags?: TypeFormatFlags): SymbolDisplayPart[] {
|
||||
return mapToDisplayParts(writer => {
|
||||
typechecker.writeType(type, writer, enclosingDeclaration, flags);
|
||||
typechecker.getSymbolDisplayBuilder().buildTypeDisplay(type, writer, enclosingDeclaration, flags);
|
||||
});
|
||||
}
|
||||
|
||||
export function symbolToDisplayParts(typeChecker: TypeChecker, symbol: Symbol, enclosingDeclaration?: Node, meaning?: SymbolFlags, flags?: SymbolFormatFlags): SymbolDisplayPart[] {
|
||||
return mapToDisplayParts(writer => {
|
||||
typeChecker.writeSymbol(symbol, writer, enclosingDeclaration, meaning, flags);
|
||||
typeChecker.getSymbolDisplayBuilder().buildSymbolDisplay(symbol, writer, enclosingDeclaration, meaning, flags);
|
||||
});
|
||||
}
|
||||
|
||||
function signatureToDisplayParts(typechecker: TypeChecker, signature: Signature, enclosingDeclaration?: Node, flags?: TypeFormatFlags): SymbolDisplayPart[]{
|
||||
return mapToDisplayParts(writer => {
|
||||
typechecker.writeSignature(signature, writer, enclosingDeclaration, flags);
|
||||
typechecker.getSymbolDisplayBuilder().buildSignatureDisplay(signature, writer, enclosingDeclaration, flags);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -2694,7 +2694,7 @@ module ts {
|
||||
|
||||
// TODO(drosen): use contextual SemanticMeaning.
|
||||
function getSymbolKind(symbol: Symbol, typeResolver: TypeChecker): string {
|
||||
var flags = typeInfoResolver.getRootSymbols(symbol)[0].getFlags();
|
||||
var flags = symbol.getFlags();
|
||||
|
||||
if (flags & SymbolFlags.Class) return ScriptElementKind.classElement;
|
||||
if (flags & SymbolFlags.Enum) return ScriptElementKind.enumElement;
|
||||
@@ -2734,6 +2734,18 @@ module ts {
|
||||
if (flags & SymbolFlags.Property) return ScriptElementKind.memberVariableElement;
|
||||
if (flags & SymbolFlags.Constructor) return ScriptElementKind.constructorImplementationElement;
|
||||
|
||||
if (flags & SymbolFlags.UnionProperty) {
|
||||
return forEach(typeInfoResolver.getRootSymbols(symbol), rootSymbol => {
|
||||
var rootSymbolFlags = rootSymbol.getFlags();
|
||||
if (rootSymbolFlags & SymbolFlags.Property) {
|
||||
return ScriptElementKind.memberVariableElement;
|
||||
}
|
||||
if (rootSymbolFlags & SymbolFlags.GetAccessor) return ScriptElementKind.memberVariableElement;
|
||||
if (rootSymbolFlags & SymbolFlags.SetAccessor) return ScriptElementKind.memberVariableElement;
|
||||
Debug.assert(rootSymbolFlags & SymbolFlags.Method);
|
||||
}) || ScriptElementKind.memberFunctionElement;
|
||||
}
|
||||
|
||||
return ScriptElementKind.unknown;
|
||||
}
|
||||
|
||||
@@ -2785,7 +2797,7 @@ module ts {
|
||||
semanticMeaning = getMeaningFromLocation(location)) {
|
||||
var displayParts: SymbolDisplayPart[] = [];
|
||||
var documentation: SymbolDisplayPart[];
|
||||
var symbolFlags = typeResolver.getRootSymbols(symbol)[0].flags;
|
||||
var symbolFlags = symbol.flags;
|
||||
var symbolKind = getSymbolKindOfConstructorPropertyMethodAccessorFunctionOrVar(symbol, symbolFlags, typeResolver);
|
||||
var hasAddedSymbolInfo: boolean;
|
||||
// Class at constructor site need to be shown as constructor apart from property,method, vars
|
||||
@@ -3001,7 +3013,7 @@ module ts {
|
||||
// If the type is type parameter, format it specially
|
||||
if (type.symbol && type.symbol.flags & SymbolFlags.TypeParameter) {
|
||||
var typeParameterParts = mapToDisplayParts(writer => {
|
||||
typeResolver.writeTypeParameter(<TypeParameter>type, writer, enclosingDeclaration);
|
||||
typeResolver.getSymbolDisplayBuilder().buildTypeParameterDisplay(<TypeParameter>type, writer, enclosingDeclaration);
|
||||
});
|
||||
displayParts.push.apply(displayParts, typeParameterParts);
|
||||
}
|
||||
@@ -3013,7 +3025,8 @@ module ts {
|
||||
symbolFlags & SymbolFlags.Method ||
|
||||
symbolFlags & SymbolFlags.Constructor ||
|
||||
symbolFlags & SymbolFlags.Signature ||
|
||||
symbolFlags & SymbolFlags.Accessor) {
|
||||
symbolFlags & SymbolFlags.Accessor ||
|
||||
symbolKind === ScriptElementKind.memberFunctionElement) {
|
||||
var allSignatures = type.getCallSignatures();
|
||||
addSignatureDisplayParts(allSignatures[0], allSignatures);
|
||||
}
|
||||
@@ -3069,7 +3082,7 @@ module ts {
|
||||
|
||||
function writeTypeParametersOfSymbol(symbol: Symbol, enclosingDeclaration: Node) {
|
||||
var typeParameterParts = mapToDisplayParts(writer => {
|
||||
typeResolver.writeTypeParametersOfSymbol(symbol, writer, enclosingDeclaration);
|
||||
typeResolver.getSymbolDisplayBuilder().buildTypeParameterDisplayFromSymbol(symbol, writer, enclosingDeclaration);
|
||||
});
|
||||
displayParts.push.apply(displayParts, typeParameterParts);
|
||||
}
|
||||
|
||||
@@ -258,6 +258,13 @@ module ts.SignatureHelp {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
function getChildListThatStartsWithOpenerToken(parent: Node, openerToken: Node, sourceFile: SourceFile): Node {
|
||||
var children = parent.getChildren(sourceFile);
|
||||
var indexOfOpenerToken = children.indexOf(openerToken);
|
||||
Debug.assert(indexOfOpenerToken >= 0 && children.length > indexOfOpenerToken + 1);
|
||||
return children[indexOfOpenerToken + 1];
|
||||
}
|
||||
|
||||
/**
|
||||
* The selectedItemIndex could be negative for several reasons.
|
||||
* 1. There are too many arguments for all of the overloads
|
||||
@@ -287,74 +294,51 @@ module ts.SignatureHelp {
|
||||
|
||||
function createSignatureHelpItems(candidates: Signature[], bestSignature: Signature, argumentInfoOrTypeArgumentInfo: ListItemInfo): SignatureHelpItems {
|
||||
var argumentListOrTypeArgumentList = argumentInfoOrTypeArgumentInfo.list;
|
||||
var parent = <CallExpression>argumentListOrTypeArgumentList.parent;
|
||||
var isTypeParameterHelp = parent.typeArguments && parent.typeArguments.pos === argumentListOrTypeArgumentList.pos;
|
||||
Debug.assert(isTypeParameterHelp || parent.arguments.pos === argumentListOrTypeArgumentList.pos);
|
||||
|
||||
var callTargetNode = (<CallExpression>argumentListOrTypeArgumentList.parent).func;
|
||||
var callTargetSymbol = typeInfoResolver.getSymbolInfo(callTargetNode);
|
||||
var callTargetDisplayParts = callTargetSymbol && symbolToDisplayParts(typeInfoResolver, callTargetSymbol, /*enclosingDeclaration*/ undefined, /*meaning*/ undefined);
|
||||
var items: SignatureHelpItem[] = map(candidates, candidateSignature => {
|
||||
var parameters = candidateSignature.parameters;
|
||||
var parameterHelpItems: SignatureHelpParameter[] = parameters.length === 0 ? emptyArray : map(parameters, p => {
|
||||
var displayParts: SymbolDisplayPart[] = [];
|
||||
var signatureHelpParameters: SignatureHelpParameter[];
|
||||
var prefixParts: SymbolDisplayPart[] = [];
|
||||
var suffixParts: SymbolDisplayPart[] = [];
|
||||
|
||||
if (candidateSignature.hasRestParameter && parameters[parameters.length - 1] === p) {
|
||||
displayParts.push(punctuationPart(SyntaxKind.DotDotDotToken));
|
||||
}
|
||||
|
||||
displayParts.push(symbolPart(p.name, p));
|
||||
|
||||
var isOptional = !!(p.valueDeclaration.flags & NodeFlags.QuestionMark);
|
||||
if (isOptional) {
|
||||
displayParts.push(punctuationPart(SyntaxKind.QuestionToken));
|
||||
}
|
||||
|
||||
displayParts.push(punctuationPart(SyntaxKind.ColonToken));
|
||||
displayParts.push(spacePart());
|
||||
|
||||
var typeParts = typeToDisplayParts(typeInfoResolver, typeInfoResolver.getTypeOfSymbol(p), argumentListOrTypeArgumentList);
|
||||
displayParts.push.apply(displayParts, typeParts);
|
||||
|
||||
return {
|
||||
name: p.name,
|
||||
documentation: p.getDocumentationComment(),
|
||||
displayParts: displayParts,
|
||||
isOptional: isOptional
|
||||
};
|
||||
});
|
||||
|
||||
var callTargetNode = (<CallExpression>argumentListOrTypeArgumentList.parent).func;
|
||||
var callTargetSymbol = typeInfoResolver.getSymbolInfo(callTargetNode);
|
||||
|
||||
var prefixParts = callTargetSymbol ? symbolToDisplayParts(typeInfoResolver, callTargetSymbol, /*enclosingDeclaration*/ undefined, /*meaning*/ undefined) : [];
|
||||
|
||||
var separatorParts = [punctuationPart(SyntaxKind.CommaToken), spacePart()];
|
||||
|
||||
// TODO(jfreeman): Constraints?
|
||||
if (candidateSignature.typeParameters && candidateSignature.typeParameters.length) {
|
||||
prefixParts.push(punctuationPart(SyntaxKind.LessThanToken));
|
||||
|
||||
for (var i = 0, n = candidateSignature.typeParameters.length; i < n; i++) {
|
||||
if (i) {
|
||||
prefixParts.push.apply(prefixParts, separatorParts);
|
||||
}
|
||||
|
||||
var tp = candidateSignature.typeParameters[i].symbol;
|
||||
prefixParts.push(symbolPart(tp.name, tp));
|
||||
}
|
||||
|
||||
prefixParts.push(punctuationPart(SyntaxKind.GreaterThanToken));
|
||||
if (callTargetDisplayParts) {
|
||||
prefixParts.push.apply(prefixParts, callTargetDisplayParts);
|
||||
}
|
||||
|
||||
prefixParts.push(punctuationPart(SyntaxKind.OpenParenToken));
|
||||
if (isTypeParameterHelp) {
|
||||
prefixParts.push(punctuationPart(SyntaxKind.LessThanToken));
|
||||
var typeParameters = candidateSignature.typeParameters;
|
||||
signatureHelpParameters = typeParameters && typeParameters.length > 0 ? map(typeParameters, createSignatureHelpParameterForTypeParameter) : emptyArray;
|
||||
suffixParts.push(punctuationPart(SyntaxKind.GreaterThanToken));
|
||||
var parameterParts = mapToDisplayParts(writer =>
|
||||
typeInfoResolver.getSymbolDisplayBuilder().buildDisplayForParametersAndDelimiters(candidateSignature.parameters, writer, argumentListOrTypeArgumentList));
|
||||
suffixParts.push.apply(suffixParts, parameterParts);
|
||||
}
|
||||
else {
|
||||
var typeParameterParts = mapToDisplayParts(writer =>
|
||||
typeInfoResolver.getSymbolDisplayBuilder().buildDisplayForTypeParametersAndDelimiters(candidateSignature.typeParameters, writer, argumentListOrTypeArgumentList));
|
||||
prefixParts.push.apply(prefixParts, typeParameterParts);
|
||||
prefixParts.push(punctuationPart(SyntaxKind.OpenParenToken));
|
||||
var parameters = candidateSignature.parameters;
|
||||
signatureHelpParameters = parameters.length > 0 ? map(parameters, createSignatureHelpParameterForParameter) : emptyArray;
|
||||
suffixParts.push(punctuationPart(SyntaxKind.CloseParenToken));
|
||||
}
|
||||
|
||||
var suffixParts = [punctuationPart(SyntaxKind.CloseParenToken)];
|
||||
suffixParts.push(punctuationPart(SyntaxKind.ColonToken));
|
||||
suffixParts.push(spacePart());
|
||||
|
||||
var typeParts = typeToDisplayParts(typeInfoResolver, candidateSignature.getReturnType(), argumentListOrTypeArgumentList);
|
||||
suffixParts.push.apply(suffixParts, typeParts);
|
||||
var returnTypeParts = mapToDisplayParts(writer =>
|
||||
typeInfoResolver.getSymbolDisplayBuilder().buildReturnTypeDisplay(candidateSignature, writer, argumentListOrTypeArgumentList));
|
||||
suffixParts.push.apply(suffixParts, returnTypeParts);
|
||||
|
||||
return {
|
||||
isVariadic: candidateSignature.hasRestParameter,
|
||||
prefixDisplayParts: prefixParts,
|
||||
suffixDisplayParts: suffixParts,
|
||||
separatorDisplayParts: separatorParts,
|
||||
parameters: parameterHelpItems,
|
||||
separatorDisplayParts: [punctuationPart(SyntaxKind.CommaToken), spacePart()],
|
||||
parameters: signatureHelpParameters,
|
||||
documentation: candidateSignature.getDocumentationComment()
|
||||
};
|
||||
});
|
||||
@@ -400,12 +384,32 @@ module ts.SignatureHelp {
|
||||
argumentIndex: argumentIndex,
|
||||
argumentCount: argumentCount
|
||||
};
|
||||
|
||||
function createSignatureHelpParameterForParameter(parameter: Symbol): SignatureHelpParameter {
|
||||
var displayParts = mapToDisplayParts(writer =>
|
||||
typeInfoResolver.getSymbolDisplayBuilder().buildParameterDisplay(parameter, writer, argumentListOrTypeArgumentList));
|
||||
|
||||
var isOptional = !!(parameter.valueDeclaration.flags & NodeFlags.QuestionMark);
|
||||
|
||||
return {
|
||||
name: parameter.name,
|
||||
documentation: parameter.getDocumentationComment(),
|
||||
displayParts: displayParts,
|
||||
isOptional: isOptional
|
||||
};
|
||||
}
|
||||
|
||||
function createSignatureHelpParameterForTypeParameter(typeParameter: TypeParameter): SignatureHelpParameter {
|
||||
var displayParts = mapToDisplayParts(writer =>
|
||||
typeInfoResolver.getSymbolDisplayBuilder().buildTypeParameterDisplay(typeParameter, writer, argumentListOrTypeArgumentList));
|
||||
|
||||
return {
|
||||
name: typeParameter.symbol.name,
|
||||
documentation: emptyArray,
|
||||
displayParts: displayParts,
|
||||
isOptional: false
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function getChildListThatStartsWithOpenerToken(parent: Node, openerToken: Node, sourceFile: SourceFile): Node {
|
||||
var children = parent.getChildren(sourceFile);
|
||||
var indexOfOpenerToken = children.indexOf(openerToken);
|
||||
return children[indexOfOpenerToken + 1];
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user