Merge branch 'master' into alternateFixSuperInAsyncMethod

This commit is contained in:
Ron Buckton 2016-01-26 11:49:30 -08:00
commit da6aadbea8
61 changed files with 1130 additions and 319 deletions

View file

@ -169,7 +169,9 @@ var librarySourceMap = [
{ target: "lib.scriptHost.d.ts", sources: ["importcore.d.ts", "scriptHost.d.ts"], },
{ target: "lib.d.ts", sources: ["header.d.ts", "core.d.ts", "intl.d.ts", "dom.generated.d.ts", "webworker.importscripts.d.ts", "scriptHost.d.ts"], },
{ target: "lib.core.es6.d.ts", sources: ["header.d.ts", "core.d.ts", "es6.d.ts"]},
{ target: "lib.es6.d.ts", sources: ["header.d.ts", "es6.d.ts", "core.d.ts", "intl.d.ts", "dom.generated.d.ts", "dom.es6.d.ts", "webworker.importscripts.d.ts", "scriptHost.d.ts"] }
{ target: "lib.es6.d.ts", sources: ["header.d.ts", "es6.d.ts", "core.d.ts", "intl.d.ts", "dom.generated.d.ts", "dom.es6.d.ts", "webworker.importscripts.d.ts", "scriptHost.d.ts"] },
{ target: "lib.core.es7.d.ts", sources: ["header.d.ts", "core.d.ts", "es6.d.ts", "es7.d.ts"]},
{ target: "lib.es7.d.ts", sources: ["header.d.ts", "es6.d.ts", "es7.d.ts", "core.d.ts", "intl.d.ts", "dom.generated.d.ts", "dom.es6.d.ts", "webworker.importscripts.d.ts", "scriptHost.d.ts"] }
];
var libraryTargets = librarySourceMap.map(function (f) {

View file

@ -3885,7 +3885,7 @@ function g(x: number) {
the inferred return type for 'f' and 'g' is Any because the functions reference themselves through a cycle with no return type annotations. Adding an explicit return type 'number' to either breaks the cycle and causes the return type 'number' to be inferred for the other.
An explicitly typed function whose return type isn't the Void or the Any type must have at least one return statement somewhere in its body. An exception to this rule is if the function implementation consists of a single 'throw' statement.
An explicitly typed function whose return type isn't the Void type, the Any type, or a union type containing the Void or Any type as a constituent must have at least one return statement somewhere in its body. An exception to this rule is if the function implementation consists of a single 'throw' statement.
The type of 'this' in a function implementation is the Any type.

View file

@ -2,7 +2,7 @@
"name": "typescript",
"author": "Microsoft Corp.",
"homepage": "http://typescriptlang.org/",
"version": "1.8.0",
"version": "1.9.0",
"license": "Apache-2.0",
"description": "TypeScript is a language for application scale JavaScript development",
"keywords": [

View file

@ -251,6 +251,15 @@ namespace ts {
case SyntaxKind.FunctionDeclaration:
case SyntaxKind.ClassDeclaration:
return node.flags & NodeFlags.Default ? "default" : undefined;
case SyntaxKind.JSDocFunctionType:
return isJSDocConstructSignature(node) ? "__new" : "__call";
case SyntaxKind.Parameter:
// Parameters with names are handled at the top of this function. Parameters
// without names can only come from JSDocFunctionTypes.
Debug.assert(node.parent.kind === SyntaxKind.JSDocFunctionType);
let functionType = <JSDocFunctionType>node.parent;
let index = indexOf(functionType.parameters, node);
return "p" + index;
}
}
@ -421,7 +430,6 @@ namespace ts {
addToContainerChain(container);
}
else if (containerFlags & ContainerFlags.IsBlockScopedContainer) {
blockScopeContainer = node;
blockScopeContainer.locals = undefined;
@ -459,6 +467,10 @@ namespace ts {
labelStack = labelIndexMap = implicitLabels = undefined;
}
if (isInJavaScriptFile(node) && node.jsDocComment) {
bind(node.jsDocComment);
}
bindReachableStatement(node);
if (currentReachabilityState === Reachability.Reachable && isFunctionLikeKind(kind) && nodeIsPresent((<FunctionLikeDeclaration>node).body)) {
@ -722,8 +734,9 @@ namespace ts {
case SyntaxKind.ClassDeclaration:
case SyntaxKind.InterfaceDeclaration:
case SyntaxKind.EnumDeclaration:
case SyntaxKind.TypeLiteral:
case SyntaxKind.ObjectLiteralExpression:
case SyntaxKind.TypeLiteral:
case SyntaxKind.JSDocRecordType:
return ContainerFlags.IsContainer;
case SyntaxKind.CallSignature:
@ -809,6 +822,7 @@ namespace ts {
case SyntaxKind.TypeLiteral:
case SyntaxKind.ObjectLiteralExpression:
case SyntaxKind.InterfaceDeclaration:
case SyntaxKind.JSDocRecordType:
// Interface/Object-types always have their children added to the 'members' of
// their container. They are only accessible through an instance of their
// container, and are never in scope otherwise (even inside the body of the
@ -829,6 +843,7 @@ namespace ts {
case SyntaxKind.FunctionDeclaration:
case SyntaxKind.FunctionExpression:
case SyntaxKind.ArrowFunction:
case SyntaxKind.JSDocFunctionType:
case SyntaxKind.TypeAliasDeclaration:
// All the children of these container types are never visible through another
// symbol (i.e. through another symbol's 'exports' or 'members'). Instead,
@ -910,7 +925,7 @@ namespace ts {
}
}
function bindFunctionOrConstructorType(node: SignatureDeclaration) {
function bindFunctionOrConstructorType(node: SignatureDeclaration): void {
// For a given function symbol "<...>(...) => T" we want to generate a symbol identical
// to the one we would get for: { <...>(...): T }
//
@ -985,7 +1000,7 @@ namespace ts {
declareModuleMember(node, symbolFlags, symbolExcludes);
break;
}
// fall through.
// fall through.
default:
if (!blockScopeContainer.locals) {
blockScopeContainer.locals = {};
@ -1264,12 +1279,14 @@ namespace ts {
return bindVariableDeclarationOrBindingElement(<VariableDeclaration | BindingElement>node);
case SyntaxKind.PropertyDeclaration:
case SyntaxKind.PropertySignature:
case SyntaxKind.JSDocRecordMember:
return bindPropertyOrMethodOrAccessor(<Declaration>node, SymbolFlags.Property | ((<PropertyDeclaration>node).questionToken ? SymbolFlags.Optional : SymbolFlags.None), SymbolFlags.PropertyExcludes);
case SyntaxKind.PropertyAssignment:
case SyntaxKind.ShorthandPropertyAssignment:
return bindPropertyOrMethodOrAccessor(<Declaration>node, SymbolFlags.Property, SymbolFlags.PropertyExcludes);
case SyntaxKind.EnumMember:
return bindPropertyOrMethodOrAccessor(<Declaration>node, SymbolFlags.EnumMember, SymbolFlags.EnumMemberExcludes);
case SyntaxKind.CallSignature:
case SyntaxKind.ConstructSignature:
case SyntaxKind.IndexSignature:
@ -1292,8 +1309,10 @@ namespace ts {
return bindPropertyOrMethodOrAccessor(<Declaration>node, SymbolFlags.SetAccessor, SymbolFlags.SetAccessorExcludes);
case SyntaxKind.FunctionType:
case SyntaxKind.ConstructorType:
case SyntaxKind.JSDocFunctionType:
return bindFunctionOrConstructorType(<SignatureDeclaration>node);
case SyntaxKind.TypeLiteral:
case SyntaxKind.JSDocRecordType:
return bindAnonymousDeclaration(<TypeLiteralNode>node, SymbolFlags.TypeLiteral, "__type");
case SyntaxKind.ObjectLiteralExpression:
return bindObjectLiteralExpression(<ObjectLiteralExpression>node);

View file

@ -557,7 +557,9 @@ namespace ts {
// - Type parameters of a function are in scope in the entire function declaration, including the parameter
// list and return type. However, local types are only in scope in the function body.
// - parameters are only in the scope of function body
if (meaning & result.flags & SymbolFlags.Type) {
// This restriction does not apply to JSDoc comment types because they are parented
// at a higher level than type parameters would normally be
if (meaning & result.flags & SymbolFlags.Type && lastLocation.kind !== SyntaxKind.JSDocComment) {
useResult = result.flags & SymbolFlags.TypeParameter
// type parameters are visible in parameter list, return type and type parameter list
? lastLocation === (<FunctionLikeDeclaration>location).type ||
@ -2591,8 +2593,54 @@ namespace ts {
return type;
}
function getTypeForVariableLikeDeclarationFromJSDocComment(declaration: VariableLikeDeclaration) {
const jsDocType = getJSDocTypeForVariableLikeDeclarationFromJSDocComment(declaration);
if (jsDocType) {
return getTypeFromTypeNode(jsDocType);
}
}
function getJSDocTypeForVariableLikeDeclarationFromJSDocComment(declaration: VariableLikeDeclaration): JSDocType {
// First, see if this node has an @type annotation on it directly.
const typeTag = getJSDocTypeTag(declaration);
if (typeTag) {
return typeTag.typeExpression.type;
}
if (declaration.kind === SyntaxKind.VariableDeclaration &&
declaration.parent.kind === SyntaxKind.VariableDeclarationList &&
declaration.parent.parent.kind === SyntaxKind.VariableStatement) {
// @type annotation might have been on the variable statement, try that instead.
const annotation = getJSDocTypeTag(declaration.parent.parent);
if (annotation) {
return annotation.typeExpression.type;
}
}
else if (declaration.kind === SyntaxKind.Parameter) {
// If it's a parameter, see if the parent has a jsdoc comment with an @param
// annotation.
const paramTag = getCorrespondingJSDocParameterTag(<ParameterDeclaration>declaration);
if (paramTag && paramTag.typeExpression) {
return paramTag.typeExpression.type;
}
}
return undefined;
}
// Return the inferred type for a variable, parameter, or property declaration
function getTypeForVariableLikeDeclaration(declaration: VariableLikeDeclaration): Type {
if (declaration.parserContextFlags & ParserContextFlags.JavaScriptFile) {
// If this is a variable in a JavaScript file, then use the JSDoc type (if it has
// one as its type), otherwise fallback to the below standard TS codepaths to
// try to figure it out.
const type = getTypeForVariableLikeDeclarationFromJSDocComment(declaration);
if (type && type !== unknownType) {
return type;
}
}
// A variable declared in a for..in statement is always of type string
if (declaration.parent.parent.kind === SyntaxKind.ForInStatement) {
return stringType;
@ -3910,6 +3958,17 @@ namespace ts {
return getIndexTypeOfStructuredType(getApparentType(type), kind);
}
function getTypeParametersFromJSDocTemplate(declaration: SignatureDeclaration): TypeParameter[] {
if (declaration.parserContextFlags & ParserContextFlags.JavaScriptFile) {
const templateTag = getJSDocTemplateTag(declaration);
if (templateTag) {
return getTypeParametersFromDeclaration(templateTag.typeParameters);
}
}
return undefined;
}
// Return list of type parameters with duplicates removed (duplicate identifier errors are generated in the actual
// type checking functions).
function getTypeParametersFromDeclaration(typeParameterDeclarations: TypeParameterDeclaration[]): TypeParameter[] {
@ -3934,6 +3993,23 @@ namespace ts {
}
function isOptionalParameter(node: ParameterDeclaration) {
if (node.parserContextFlags & ParserContextFlags.JavaScriptFile) {
if (node.type && node.type.kind === SyntaxKind.JSDocOptionalType) {
return true;
}
const paramTag = getCorrespondingJSDocParameterTag(node);
if (paramTag) {
if (paramTag.isBracketed) {
return true;
}
if (paramTag.typeExpression) {
return paramTag.typeExpression.type.kind === SyntaxKind.JSDocOptionalType;
}
}
}
if (hasQuestionToken(node)) {
return true;
}
@ -3974,12 +4050,20 @@ namespace ts {
getDeclaredTypeOfClassOrInterface(getMergedSymbol((<ClassDeclaration>declaration.parent).symbol))
: undefined;
const typeParameters = classType ? classType.localTypeParameters :
declaration.typeParameters ? getTypeParametersFromDeclaration(declaration.typeParameters) : undefined;
declaration.typeParameters ? getTypeParametersFromDeclaration(declaration.typeParameters) :
getTypeParametersFromJSDocTemplate(declaration);
const parameters: Symbol[] = [];
let hasStringLiterals = false;
let minArgumentCount = -1;
for (let i = 0, n = declaration.parameters.length; i < n; i++) {
const isJSConstructSignature = isJSDocConstructSignature(declaration);
let returnType: Type = undefined;
// If this is a JSDoc construct signature, then skip the first parameter in the
// parameter list. The first parameter represents the return type of the construct
// signature.
for (let i = isJSConstructSignature ? 1 : 0, n = declaration.parameters.length; i < n; i++) {
const param = declaration.parameters[i];
let paramSymbol = param.symbol;
// Include parameter symbol instead of property symbol in the signature
if (paramSymbol && !!(paramSymbol.flags & SymbolFlags.Property) && !isBindingPattern(param.name)) {
@ -3987,6 +4071,7 @@ namespace ts {
paramSymbol = resolvedSymbol;
}
parameters.push(paramSymbol);
if (param.type && param.type.kind === SyntaxKind.StringLiteralType) {
hasStringLiterals = true;
}
@ -4006,14 +4091,24 @@ namespace ts {
minArgumentCount = declaration.parameters.length;
}
let returnType: Type;
if (classType) {
if (isJSConstructSignature) {
minArgumentCount--;
returnType = getTypeFromTypeNode(declaration.parameters[0].type);
}
else if (classType) {
returnType = classType;
}
else if (declaration.type) {
returnType = getTypeFromTypeNode(declaration.type);
}
else {
if (declaration.parserContextFlags & ParserContextFlags.JavaScriptFile) {
const type = getReturnTypeFromJSDocComment(declaration);
if (type && type !== unknownType) {
returnType = type;
}
}
// TypeScript 1.0 spec (April 2014):
// If only one accessor includes a type annotation, the other behaves as if it had the same type annotation.
if (declaration.kind === SyntaxKind.GetAccessor && !hasDynamicName(declaration)) {
@ -4050,6 +4145,7 @@ namespace ts {
case SyntaxKind.SetAccessor:
case SyntaxKind.FunctionExpression:
case SyntaxKind.ArrowFunction:
case SyntaxKind.JSDocFunctionType:
// Don't include signature if node is the implementation of an overloaded function. A node is considered
// an implementation node if it has a body and the previous node is of the same kind and immediately
// precedes the implementation node (i.e. has the same parent and ends where the implementation starts).
@ -4269,7 +4365,7 @@ namespace ts {
}
// Get type from reference to class or interface
function getTypeFromClassOrInterfaceReference(node: TypeReferenceNode | ExpressionWithTypeArguments, symbol: Symbol): Type {
function getTypeFromClassOrInterfaceReference(node: TypeReferenceNode | ExpressionWithTypeArguments | JSDocTypeReference, symbol: Symbol): Type {
const type = <InterfaceType>getDeclaredTypeOfSymbol(symbol);
const typeParameters = type.localTypeParameters;
if (typeParameters) {
@ -4292,7 +4388,7 @@ namespace ts {
// Get type from reference to type alias. When a type alias is generic, the declared type of the type alias may include
// references to the type parameters of the alias. We replace those with the actual type arguments by instantiating the
// declared type. Instantiations are cached using the type identities of the type arguments as the key.
function getTypeFromTypeAliasReference(node: TypeReferenceNode | ExpressionWithTypeArguments, symbol: Symbol): Type {
function getTypeFromTypeAliasReference(node: TypeReferenceNode | ExpressionWithTypeArguments | JSDocTypeReference, symbol: Symbol): Type {
const type = getDeclaredTypeOfSymbol(symbol);
const links = getSymbolLinks(symbol);
const typeParameters = links.typeParameters;
@ -4313,7 +4409,7 @@ namespace ts {
}
// Get type from reference to named type that cannot be generic (enum or type parameter)
function getTypeFromNonGenericTypeReference(node: TypeReferenceNode | ExpressionWithTypeArguments, symbol: Symbol): Type {
function getTypeFromNonGenericTypeReference(node: TypeReferenceNode | ExpressionWithTypeArguments | JSDocTypeReference, symbol: Symbol): Type {
if (node.typeArguments) {
error(node, Diagnostics.Type_0_is_not_generic, symbolToString(symbol));
return unknownType;
@ -4321,18 +4417,83 @@ namespace ts {
return getDeclaredTypeOfSymbol(symbol);
}
function getTypeFromTypeReference(node: TypeReferenceNode | ExpressionWithTypeArguments): Type {
function getTypeReferenceName(node: TypeReferenceNode | ExpressionWithTypeArguments | JSDocTypeReference): LeftHandSideExpression | EntityName {
switch (node.kind) {
case SyntaxKind.TypeReference:
return (<TypeReferenceNode>node).typeName;
case SyntaxKind.JSDocTypeReference:
return (<JSDocTypeReference>node).name;
case SyntaxKind.ExpressionWithTypeArguments:
// We only support expressions that are simple qualified names. For other
// expressions this produces undefined.
if (isSupportedExpressionWithTypeArguments(<ExpressionWithTypeArguments>node)) {
return (<ExpressionWithTypeArguments>node).expression;
}
// fall through;
}
return undefined;
}
function resolveTypeReferenceName(
node: TypeReferenceNode | ExpressionWithTypeArguments | JSDocTypeReference,
typeReferenceName: LeftHandSideExpression | EntityName) {
if (!typeReferenceName) {
return unknownSymbol;
}
return resolveEntityName(typeReferenceName, SymbolFlags.Type) || unknownSymbol;
}
function getTypeReferenceType(node: TypeReferenceNode | ExpressionWithTypeArguments | JSDocTypeReference, symbol: Symbol) {
if (symbol === unknownSymbol) {
return unknownType;
}
if (symbol.flags & (SymbolFlags.Class | SymbolFlags.Interface)) {
return getTypeFromClassOrInterfaceReference(node, symbol);
}
if (symbol.flags & SymbolFlags.TypeAlias) {
return getTypeFromTypeAliasReference(node, symbol);
}
if (symbol.flags & SymbolFlags.Value && node.kind === SyntaxKind.JSDocTypeReference) {
// A JSDocTypeReference may have resolved to a value (as opposed to a type). In
// that case, the type of this reference is just the type of the value we resolved
// to.
return getTypeOfSymbol(symbol);
}
return getTypeFromNonGenericTypeReference(node, symbol);
}
function getTypeFromTypeReference(node: TypeReferenceNode | ExpressionWithTypeArguments | JSDocTypeReference): Type {
const links = getNodeLinks(node);
if (!links.resolvedType) {
// We only support expressions that are simple qualified names. For other expressions this produces undefined.
const typeNameOrExpression = node.kind === SyntaxKind.TypeReference ? (<TypeReferenceNode>node).typeName :
isSupportedExpressionWithTypeArguments(<ExpressionWithTypeArguments>node) ? (<ExpressionWithTypeArguments>node).expression :
undefined;
const symbol = typeNameOrExpression && resolveEntityName(typeNameOrExpression, SymbolFlags.Type) || unknownSymbol;
const type = symbol === unknownSymbol ? unknownType :
symbol.flags & (SymbolFlags.Class | SymbolFlags.Interface) ? getTypeFromClassOrInterfaceReference(node, symbol) :
symbol.flags & SymbolFlags.TypeAlias ? getTypeFromTypeAliasReference(node, symbol) :
getTypeFromNonGenericTypeReference(node, symbol);
let symbol: Symbol;
let type: Type;
if (node.kind === SyntaxKind.JSDocTypeReference) {
const typeReferenceName = getTypeReferenceName(node);
symbol = resolveTypeReferenceName(node, typeReferenceName);
type = getTypeReferenceType(node, symbol);
links.resolvedSymbol = symbol;
links.resolvedType = type;
}
else {
// We only support expressions that are simple qualified names. For other expressions this produces undefined.
const typeNameOrExpression = node.kind === SyntaxKind.TypeReference ? (<TypeReferenceNode>node).typeName :
isSupportedExpressionWithTypeArguments(<ExpressionWithTypeArguments>node) ? (<ExpressionWithTypeArguments>node).expression :
undefined;
symbol = typeNameOrExpression && resolveEntityName(typeNameOrExpression, SymbolFlags.Type) || unknownSymbol;
type = symbol === unknownSymbol ? unknownType :
symbol.flags & (SymbolFlags.Class | SymbolFlags.Interface) ? getTypeFromClassOrInterfaceReference(node, symbol) :
symbol.flags & SymbolFlags.TypeAlias ? getTypeFromTypeAliasReference(node, symbol) :
getTypeFromNonGenericTypeReference(node, symbol);
}
// Cache both the resolved symbol and the resolved type. The resolved symbol is needed in when we check the
// type reference in checkTypeReferenceOrExpressionWithTypeArguments.
links.resolvedSymbol = symbol;
@ -4627,6 +4788,24 @@ namespace ts {
return links.resolvedType;
}
function getTypeFromJSDocVariadicType(node: JSDocVariadicType): Type {
const links = getNodeLinks(node);
if (!links.resolvedType) {
const type = getTypeFromTypeNode(node.type);
links.resolvedType = type ? createArrayType(type) : unknownType;
}
return links.resolvedType;
}
function getTypeFromJSDocTupleType(node: JSDocTupleType): Type {
const links = getNodeLinks(node);
if (!links.resolvedType) {
const types = map(node.types, getTypeFromTypeNode);
links.resolvedType = createTupleType(types);
}
return links.resolvedType;
}
function getThisType(node: TypeNode): Type {
const container = getThisContainer(node, /*includeArrowFunctions*/ false);
const parent = container && container.parent;
@ -4670,6 +4849,8 @@ namespace ts {
function getTypeFromTypeNode(node: TypeNode): Type {
switch (node.kind) {
case SyntaxKind.AnyKeyword:
case SyntaxKind.JSDocAllType:
case SyntaxKind.JSDocUnknownType:
return anyType;
case SyntaxKind.StringKeyword:
return stringType;
@ -4686,6 +4867,7 @@ namespace ts {
case SyntaxKind.StringLiteralType:
return getTypeFromStringLiteralTypeNode(<StringLiteralTypeNode>node);
case SyntaxKind.TypeReference:
case SyntaxKind.JSDocTypeReference:
return getTypeFromTypeReference(<TypeReferenceNode>node);
case SyntaxKind.TypePredicate:
return getTypeFromPredicateTypeNode(<TypePredicateNode>node);
@ -4694,18 +4876,27 @@ namespace ts {
case SyntaxKind.TypeQuery:
return getTypeFromTypeQueryNode(<TypeQueryNode>node);
case SyntaxKind.ArrayType:
case SyntaxKind.JSDocArrayType:
return getTypeFromArrayTypeNode(<ArrayTypeNode>node);
case SyntaxKind.TupleType:
return getTypeFromTupleTypeNode(<TupleTypeNode>node);
case SyntaxKind.UnionType:
case SyntaxKind.JSDocUnionType:
return getTypeFromUnionTypeNode(<UnionTypeNode>node);
case SyntaxKind.IntersectionType:
return getTypeFromIntersectionTypeNode(<IntersectionTypeNode>node);
case SyntaxKind.ParenthesizedType:
return getTypeFromTypeNode((<ParenthesizedTypeNode>node).type);
case SyntaxKind.JSDocNullableType:
case SyntaxKind.JSDocNonNullableType:
case SyntaxKind.JSDocConstructorType:
case SyntaxKind.JSDocThisType:
case SyntaxKind.JSDocOptionalType:
return getTypeFromTypeNode((<ParenthesizedTypeNode | JSDocTypeReferencingNode>node).type);
case SyntaxKind.FunctionType:
case SyntaxKind.ConstructorType:
case SyntaxKind.TypeLiteral:
case SyntaxKind.JSDocFunctionType:
case SyntaxKind.JSDocRecordType:
return getTypeFromTypeLiteralOrFunctionOrConstructorTypeNode(node);
// This function assumes that an identifier or qualified name is a type expression
// Callers should first ensure this by calling isTypeNode
@ -4713,6 +4904,10 @@ namespace ts {
case SyntaxKind.QualifiedName:
const symbol = getSymbolAtLocation(node);
return symbol && getDeclaredTypeOfSymbol(symbol);
case SyntaxKind.JSDocTupleType:
return getTypeFromJSDocTupleType(<JSDocTupleType>node);
case SyntaxKind.JSDocVariadicType:
return getTypeFromJSDocVariadicType(<JSDocVariadicType>node);
default:
return unknownType;
}
@ -7087,18 +7282,25 @@ namespace ts {
return container.flags & NodeFlags.Static ? getTypeOfSymbol(symbol) : (<InterfaceType>getDeclaredTypeOfSymbol(symbol)).thisType;
}
// If this is a function in a JS file, it might be a class method. Check if it's the RHS
// of a x.prototype.y = function [name]() { .... }
if (isInJavaScriptFile(node) && container.kind === SyntaxKind.FunctionExpression) {
if (getSpecialPropertyAssignmentKind(container.parent) === SpecialPropertyAssignmentKind.PrototypeProperty) {
// Get the 'x' of 'x.prototype.y = f' (here, 'f' is 'container')
const className = (((container.parent as BinaryExpression) // x.protoype.y = f
.left as PropertyAccessExpression) // x.prototype.y
.expression as PropertyAccessExpression) // x.prototype
.expression; // x
const classSymbol = checkExpression(className).symbol;
if (classSymbol && classSymbol.members && (classSymbol.flags & SymbolFlags.Function)) {
return getInferredClassType(classSymbol);
if (isInJavaScriptFile(node)) {
const type = getTypeForThisExpressionFromJSDoc(container);
if (type && type !== unknownType) {
return type;
}
// If this is a function in a JS file, it might be a class method. Check if it's the RHS
// of a x.prototype.y = function [name]() { .... }
if (container.kind === SyntaxKind.FunctionExpression) {
if (getSpecialPropertyAssignmentKind(container.parent) === SpecialPropertyAssignmentKind.PrototypeProperty) {
// Get the 'x' of 'x.prototype.y = f' (here, 'f' is 'container')
const className = (((container.parent as BinaryExpression) // x.protoype.y = f
.left as PropertyAccessExpression) // x.prototype.y
.expression as PropertyAccessExpression) // x.prototype
.expression; // x
const classSymbol = checkExpression(className).symbol;
if (classSymbol && classSymbol.members && (classSymbol.flags & SymbolFlags.Function)) {
return getInferredClassType(classSymbol);
}
}
}
}
@ -7106,6 +7308,16 @@ namespace ts {
return anyType;
}
function getTypeForThisExpressionFromJSDoc(node: Node) {
const typeTag = getJSDocTypeTag(node);
if (typeTag && typeTag.typeExpression.type.kind === SyntaxKind.JSDocFunctionType) {
const jsDocFunctionType = <JSDocFunctionType>typeTag.typeExpression.type;
if (jsDocFunctionType.parameters.length > 0 && jsDocFunctionType.parameters[0].type.kind === SyntaxKind.JSDocThisType) {
return getTypeFromTypeNode(jsDocFunctionType.parameters[0].type);
}
}
}
function isInConstructorArgumentInitializer(node: Node, constructorDecl: Node): boolean {
for (let n = node; n && n !== constructorDecl; n = n.parent) {
if (n.kind === SyntaxKind.Parameter) {
@ -9978,7 +10190,8 @@ namespace ts {
if (declaration &&
declaration.kind !== SyntaxKind.Constructor &&
declaration.kind !== SyntaxKind.ConstructSignature &&
declaration.kind !== SyntaxKind.ConstructorType) {
declaration.kind !== SyntaxKind.ConstructorType &&
!isJSDocConstructSignature(declaration)) {
// When resolved signature is a call signature (and not a construct signature) the result type is any, unless
// the declaring function had members created through 'x.prototype.y = expr' or 'this.y = expr' psuedodeclarations
@ -10098,6 +10311,13 @@ namespace ts {
}
}
function getReturnTypeFromJSDocComment(func: SignatureDeclaration | FunctionDeclaration): Type {
const returnTag = getJSDocReturnTag(func);
if (returnTag) {
return getTypeFromTypeNode(returnTag.typeExpression.type);
}
}
function createPromiseType(promisedType: Type): Type {
// creates a `Promise<T>` type where `T` is the promisedType argument
const globalPromiseType = getGlobalPromiseType();
@ -10248,7 +10468,8 @@ namespace ts {
/*
*TypeScript Specification 1.0 (6.3) - July 2014
* An explicitly typed function whose return type isn't the Void or the Any type
* An explicitly typed function whose return type isn't the Void type,
* the Any type, or a union type containing the Void or Any type as a constituent
* must have at least one return statement somewhere in its body.
* An exception to this rule is if the function implementation consists of a single 'throw' statement.
* @param returnType - return type of the function, can be undefined if return type is not explicitly specified
@ -10259,7 +10480,7 @@ namespace ts {
}
// Functions with with an explicitly specified 'void' or 'any' return type don't need any return expressions.
if (returnType === voidType || isTypeAny(returnType)) {
if (returnType === voidType || isTypeAny(returnType) || (returnType && (returnType.flags & TypeFlags.Union) && someConstituentTypeHasKind(returnType, TypeFlags.Any | TypeFlags.Void))) {
return;
}

View file

@ -493,8 +493,8 @@ namespace ts {
* @param basePath A root directory to resolve relative path entries in the config
* file to. e.g. outDir
*/
export function parseJsonConfigFileContent(json: any, host: ParseConfigHost, basePath: string, existingOptions: CompilerOptions = {}): ParsedCommandLine {
const { options: optionsFromJsonConfigFile, errors } = convertCompilerOptionsFromJson(json["compilerOptions"], basePath);
export function parseJsonConfigFileContent(json: any, host: ParseConfigHost, basePath: string, existingOptions: CompilerOptions = {}, configFileName?: string): ParsedCommandLine {
const { options: optionsFromJsonConfigFile, errors } = convertCompilerOptionsFromJson(json["compilerOptions"], basePath, configFileName);
const options = extend(existingOptions, optionsFromJsonConfigFile);
return {
@ -523,7 +523,7 @@ namespace ts {
for (const extension of supportedExtensions) {
const filesInDirWithExtension = host.readDirectory(basePath, extension, exclude);
for (const fileName of filesInDirWithExtension) {
// .ts extension would read the .d.ts extension files too but since .d.ts is lower priority extension,
// .ts extension would read the .d.ts extension files too but since .d.ts is lower priority extension,
// lets pick them when its turn comes up
if (extension === ".ts" && fileExtensionIs(fileName, ".d.ts")) {
continue;
@ -547,10 +547,15 @@ namespace ts {
}
}
export function convertCompilerOptionsFromJson(jsonOptions: any, basePath: string): { options: CompilerOptions, errors: Diagnostic[] } {
export function convertCompilerOptionsFromJson(jsonOptions: any, basePath: string, configFileName?: string): { options: CompilerOptions, errors: Diagnostic[] } {
const options: CompilerOptions = {};
const errors: Diagnostic[] = [];
if (configFileName && getBaseFileName(configFileName) === "jsconfig.json") {
options.module = ModuleKind.CommonJS;
options.allowJs = true;
}
if (!jsonOptions) {
return { options, errors };
}

View file

@ -6145,6 +6145,7 @@ const _super = (function (geti, seti) {
if (contains(externalImports, node)) {
const isExportedImport = node.kind === SyntaxKind.ImportEqualsDeclaration && (node.flags & NodeFlags.Export) !== 0;
const namespaceDeclaration = getNamespaceDeclarationNode(node);
const varOrConst = (languageVersion <= ScriptTarget.ES5) ? "var " : "const ";
if (modulekind !== ModuleKind.AMD) {
emitLeadingComments(node);
@ -6152,7 +6153,9 @@ const _super = (function (geti, seti) {
if (namespaceDeclaration && !isDefaultImport(node)) {
// import x = require("foo")
// import * as x from "foo"
if (!isExportedImport) write("var ");
if (!isExportedImport) {
write(varOrConst);
};
emitModuleMemberName(namespaceDeclaration);
write(" = ");
}
@ -6164,7 +6167,7 @@ const _super = (function (geti, seti) {
// import d, { x, y } from "foo"
const isNakedImport = SyntaxKind.ImportDeclaration && !(<ImportDeclaration>node).importClause;
if (!isNakedImport) {
write("var ");
write(varOrConst);
write(getGeneratedNameForNode(<ImportDeclaration>node));
write(" = ");
}
@ -6191,7 +6194,7 @@ const _super = (function (geti, seti) {
}
else if (namespaceDeclaration && isDefaultImport(node)) {
// import d, * as x from "foo"
write("var ");
write(varOrConst);
emitModuleMemberName(namespaceDeclaration);
write(" = ");
write(getGeneratedNameForNode(<ImportDeclaration>node));

View file

@ -546,7 +546,7 @@ namespace ts {
function getLanguageVariant(fileName: string) {
// .tsx and .jsx files are treated as jsx language variant.
return fileExtensionIs(fileName, ".tsx") || fileExtensionIs(fileName, ".jsx") ? LanguageVariant.JSX : LanguageVariant.Standard;
return fileExtensionIs(fileName, ".tsx") || fileExtensionIs(fileName, ".jsx") || fileExtensionIs(fileName, ".js") ? LanguageVariant.JSX : LanguageVariant.Standard;
}
function initializeState(fileName: string, _sourceText: string, languageVersion: ScriptTarget, isJavaScriptFile: boolean, _syntaxCursor: IncrementalParser.SyntaxCursor) {
@ -611,44 +611,24 @@ namespace ts {
fixupParentReferences(sourceFile);
}
// If this is a javascript file, proactively see if we can get JSDoc comments for
// relevant nodes in the file. We'll use these to provide typing informaion if they're
// available.
if (isSourceFileJavaScript(sourceFile)) {
addJSDocComments();
}
return sourceFile;
}
function addJSDocComments() {
forEachChild(sourceFile, visit);
return;
function visit(node: Node) {
// Add additional cases as necessary depending on how we see JSDoc comments used
// in the wild.
switch (node.kind) {
case SyntaxKind.VariableStatement:
case SyntaxKind.FunctionDeclaration:
case SyntaxKind.Parameter:
addJSDocComment(node);
}
forEachChild(node, visit);
}
}
function addJSDocComment(node: Node) {
const comments = getLeadingCommentRangesOfNode(node, sourceFile);
if (comments) {
for (const comment of comments) {
const jsDocComment = JSDocParser.parseJSDocComment(node, comment.pos, comment.end - comment.pos);
if (jsDocComment) {
node.jsDocComment = jsDocComment;
function addJSDocComment<T extends Node>(node: T): T {
if (contextFlags & ParserContextFlags.JavaScriptFile) {
const comments = getLeadingCommentRangesOfNode(node, sourceFile);
if (comments) {
for (const comment of comments) {
const jsDocComment = JSDocParser.parseJSDocComment(node, comment.pos, comment.end - comment.pos);
if (jsDocComment) {
node.jsDocComment = jsDocComment;
}
}
}
}
return node;
}
export function fixupParentReferences(sourceFile: Node) {
@ -2067,7 +2047,8 @@ namespace ts {
// contexts. In addition, parameter initializers are semantically disallowed in
// overload signatures. So parameter initializers are transitively disallowed in
// ambient contexts.
return finishNode(node);
return addJSDocComment(finishNode(node));
}
function parseBindingElementInitializer(inParameter: boolean) {
@ -4773,7 +4754,7 @@ namespace ts {
setModifiers(node, modifiers);
node.declarationList = parseVariableDeclarationList(/*inForStatementInitializer*/ false);
parseSemicolon();
return finishNode(node);
return addJSDocComment(finishNode(node));
}
function parseFunctionDeclaration(fullStart: number, decorators: NodeArray<Decorator>, modifiers: ModifiersArray): FunctionDeclaration {
@ -4787,7 +4768,7 @@ namespace ts {
const isAsync = !!(node.flags & NodeFlags.Async);
fillSignature(SyntaxKind.ColonToken, /*yieldContext*/ isGenerator, /*awaitContext*/ isAsync, /*requireCompleteParameterList*/ false, node);
node.body = parseFunctionBlockOrSemicolon(isGenerator, isAsync, Diagnostics.or_expected);
return finishNode(node);
return addJSDocComment(finishNode(node));
}
function parseConstructorDeclaration(pos: number, decorators: NodeArray<Decorator>, modifiers: ModifiersArray): ConstructorDeclaration {
@ -5624,23 +5605,19 @@ namespace ts {
export function parseJSDocTypeExpressionForTests(content: string, start: number, length: number) {
initializeState("file.js", content, ScriptTarget.Latest, /*isJavaScriptFile*/ true, /*_syntaxCursor:*/ undefined);
const jsDocTypeExpression = parseJSDocTypeExpression(start, length);
scanner.setText(content, start, length);
token = scanner.scan();
const jsDocTypeExpression = parseJSDocTypeExpression();
const diagnostics = parseDiagnostics;
clearState();
return jsDocTypeExpression ? { jsDocTypeExpression, diagnostics } : undefined;
}
// Parses out a JSDoc type expression. The starting position should be right at the open
// curly in the type expression. Returns 'undefined' if it encounters any errors while parsing.
// Parses out a JSDoc type expression.
/* @internal */
export function parseJSDocTypeExpression(start: number, length: number): JSDocTypeExpression {
scanner.setText(sourceText, start, length);
// Prime the first token for us to start processing.
token = nextToken();
const result = <JSDocTypeExpression>createNode(SyntaxKind.JSDocTypeExpression);
export function parseJSDocTypeExpression(): JSDocTypeExpression {
const result = <JSDocTypeExpression>createNode(SyntaxKind.JSDocTypeExpression, scanner.getTokenPos());
parseExpected(SyntaxKind.OpenBraceToken);
result.type = parseJSDocTopLevelType();
@ -5938,7 +5915,8 @@ namespace ts {
export function parseIsolatedJSDocComment(content: string, start: number, length: number) {
initializeState("file.js", content, ScriptTarget.Latest, /*isJavaScriptFile*/ true, /*_syntaxCursor:*/ undefined);
const jsDocComment = parseJSDocComment(/*parent:*/ undefined, start, length);
sourceFile = <SourceFile>{ languageVariant: LanguageVariant.Standard, text: content };
const jsDocComment = parseJSDocCommentWorker(start, length);
const diagnostics = parseDiagnostics;
clearState();
@ -5946,12 +5924,19 @@ namespace ts {
}
export function parseJSDocComment(parent: Node, start: number, length: number): JSDocComment {
const saveToken = token;
const saveParseDiagnosticsLength = parseDiagnostics.length;
const saveParseErrorBeforeNextFinishedNode = parseErrorBeforeNextFinishedNode;
const comment = parseJSDocCommentWorker(start, length);
if (comment) {
fixupParentReferences(comment);
comment.parent = parent;
}
token = saveToken;
parseDiagnostics.length = saveParseDiagnosticsLength;
parseErrorBeforeNextFinishedNode = saveParseErrorBeforeNextFinishedNode;
return comment;
}
@ -5966,69 +5951,69 @@ namespace ts {
Debug.assert(end <= content.length);
let tags: NodeArray<JSDocTag>;
let pos: number;
// NOTE(cyrusn): This is essentially a handwritten scanner for JSDocComments. I
// considered using an actual Scanner, but this would complicate things. The
// scanner would need to know it was in a Doc Comment. Otherwise, it would then
// produce comments *inside* the doc comment. In the end it was just easier to
// write a simple scanner rather than go that route.
if (length >= "/** */".length) {
if (content.charCodeAt(start) === CharacterCodes.slash &&
content.charCodeAt(start + 1) === CharacterCodes.asterisk &&
content.charCodeAt(start + 2) === CharacterCodes.asterisk &&
content.charCodeAt(start + 3) !== CharacterCodes.asterisk) {
let result: JSDocComment;
// Check for /** (JSDoc opening part)
if (content.charCodeAt(start) === CharacterCodes.slash &&
content.charCodeAt(start + 1) === CharacterCodes.asterisk &&
content.charCodeAt(start + 2) === CharacterCodes.asterisk &&
content.charCodeAt(start + 3) !== CharacterCodes.asterisk) {
// + 3 for leading /**, - 5 in total for /** */
scanner.scanRange(start + 3, length - 5, () => {
// Initially we can parse out a tag. We also have seen a starting asterisk.
// This is so that /** * @type */ doesn't parse.
let canParseTag = true;
let seenAsterisk = true;
for (pos = start + "/**".length; pos < end; ) {
const ch = content.charCodeAt(pos);
pos++;
nextJSDocToken();
while (token !== SyntaxKind.EndOfFileToken) {
switch (token) {
case SyntaxKind.AtToken:
if (canParseTag) {
parseTag();
}
// This will take us to the end of the line, so it's OK to parse a tag on the next pass through the loop
seenAsterisk = false;
break;
if (ch === CharacterCodes.at && canParseTag) {
parseTag();
case SyntaxKind.NewLineTrivia:
// After a line break, we can parse a tag, and we haven't seen an asterisk on the next line yet
canParseTag = true;
seenAsterisk = false;
break;
// Once we parse out a tag, we cannot keep parsing out tags on this line.
canParseTag = false;
continue;
}
case SyntaxKind.AsteriskToken:
if (seenAsterisk) {
// If we've already seen an asterisk, then we can no longer parse a tag on this line
canParseTag = false;
}
// Ignore the first asterisk on a line
seenAsterisk = true;
break;
if (isLineBreak(ch)) {
// After a line break, we can parse a tag, and we haven't seen as asterisk
// on the next line yet.
canParseTag = true;
seenAsterisk = false;
continue;
}
if (isWhiteSpace(ch)) {
// Whitespace doesn't affect any of our parsing.
continue;
}
// Ignore the first asterisk on a line.
if (ch === CharacterCodes.asterisk) {
if (seenAsterisk) {
// If we've already seen an asterisk, then we can no longer parse a tag
// on this line.
case SyntaxKind.Identifier:
// Anything else is doc comment text. We can't do anything with it. Because it
// wasn't a tag, we can no longer parse a tag on this line until we hit the next
// line break.
canParseTag = false;
}
seenAsterisk = true;
continue;
break;
case SyntaxKind.EndOfFileToken:
break;
}
// Anything else is doc comment text. We can't do anything with it. Because it
// wasn't a tag, we can no longer parse a tag on this line until we hit the next
// line break.
canParseTag = false;
nextJSDocToken();
}
}
result = createJSDocComment();
});
}
return createJSDocComment();
return result;
function createJSDocComment(): JSDocComment {
if (!tags) {
@ -6041,17 +6026,18 @@ namespace ts {
}
function skipWhitespace(): void {
while (pos < end && isWhiteSpace(content.charCodeAt(pos))) {
pos++;
while (token === SyntaxKind.WhitespaceTrivia || token === SyntaxKind.NewLineTrivia) {
nextJSDocToken();
}
}
function parseTag(): void {
Debug.assert(content.charCodeAt(pos - 1) === CharacterCodes.at);
const atToken = createNode(SyntaxKind.AtToken, pos - 1);
atToken.end = pos;
Debug.assert(token === SyntaxKind.AtToken);
const atToken = createNode(SyntaxKind.AtToken, scanner.getTokenPos());
atToken.end = scanner.getTextPos();
nextJSDocToken();
const tagName = scanIdentifier();
const tagName = parseJSDocIdentifier();
if (!tagName) {
return;
}
@ -6082,7 +6068,7 @@ namespace ts {
const result = <JSDocTag>createNode(SyntaxKind.JSDocTag, atToken.pos);
result.atToken = atToken;
result.tagName = tagName;
return finishNode(result, pos);
return finishNode(result);
}
function addTag(tag: JSDocTag): void {
@ -6098,14 +6084,11 @@ namespace ts {
}
function tryParseTypeExpression(): JSDocTypeExpression {
skipWhitespace();
if (content.charCodeAt(pos) !== CharacterCodes.openBrace) {
if (token !== SyntaxKind.OpenBraceToken) {
return undefined;
}
const typeExpression = parseJSDocTypeExpression(pos, end - pos);
pos = typeExpression.end;
const typeExpression = parseJSDocTypeExpression();
return typeExpression;
}
@ -6115,18 +6098,25 @@ namespace ts {
skipWhitespace();
let name: Identifier;
let isBracketed: boolean;
if (content.charCodeAt(pos) === CharacterCodes.openBracket) {
pos++;
skipWhitespace();
name = scanIdentifier();
// Looking for something like '[foo]' or 'foo'
if (parseOptionalToken(SyntaxKind.OpenBracketToken)) {
name = parseJSDocIdentifier();
isBracketed = true;
// May have an optional default, e.g. '[foo = 42]'
if (parseOptionalToken(SyntaxKind.EqualsToken)) {
parseExpression();
}
parseExpected(SyntaxKind.CloseBracketToken);
}
else {
name = scanIdentifier();
else if (token === SyntaxKind.Identifier) {
name = parseJSDocIdentifier();
}
if (!name) {
parseErrorAtPosition(pos, 0, Diagnostics.Identifier_expected);
parseErrorAtPosition(scanner.getStartPos(), 0, Diagnostics.Identifier_expected);
return undefined;
}
let preName: Identifier, postName: Identifier;
@ -6148,95 +6138,90 @@ namespace ts {
result.typeExpression = typeExpression;
result.postParameterName = postName;
result.isBracketed = isBracketed;
return finishNode(result, pos);
return finishNode(result);
}
function handleReturnTag(atToken: Node, tagName: Identifier): JSDocReturnTag {
if (forEach(tags, t => t.kind === SyntaxKind.JSDocReturnTag)) {
parseErrorAtPosition(tagName.pos, pos - tagName.pos, Diagnostics._0_tag_already_specified, tagName.text);
parseErrorAtPosition(tagName.pos, scanner.getTokenPos() - tagName.pos, Diagnostics._0_tag_already_specified, tagName.text);
}
const result = <JSDocReturnTag>createNode(SyntaxKind.JSDocReturnTag, atToken.pos);
result.atToken = atToken;
result.tagName = tagName;
result.typeExpression = tryParseTypeExpression();
return finishNode(result, pos);
return finishNode(result);
}
function handleTypeTag(atToken: Node, tagName: Identifier): JSDocTypeTag {
if (forEach(tags, t => t.kind === SyntaxKind.JSDocTypeTag)) {
parseErrorAtPosition(tagName.pos, pos - tagName.pos, Diagnostics._0_tag_already_specified, tagName.text);
parseErrorAtPosition(tagName.pos, scanner.getTokenPos() - tagName.pos, Diagnostics._0_tag_already_specified, tagName.text);
}
const result = <JSDocTypeTag>createNode(SyntaxKind.JSDocTypeTag, atToken.pos);
result.atToken = atToken;
result.tagName = tagName;
result.typeExpression = tryParseTypeExpression();
return finishNode(result, pos);
return finishNode(result);
}
function handleTemplateTag(atToken: Node, tagName: Identifier): JSDocTemplateTag {
if (forEach(tags, t => t.kind === SyntaxKind.JSDocTemplateTag)) {
parseErrorAtPosition(tagName.pos, pos - tagName.pos, Diagnostics._0_tag_already_specified, tagName.text);
parseErrorAtPosition(tagName.pos, scanner.getTokenPos() - tagName.pos, Diagnostics._0_tag_already_specified, tagName.text);
}
// Type parameter list looks like '@template T,U,V'
const typeParameters = <NodeArray<TypeParameterDeclaration>>[];
typeParameters.pos = pos;
typeParameters.pos = scanner.getStartPos();
while (true) {
skipWhitespace();
const startPos = pos;
const name = scanIdentifier();
const name = parseJSDocIdentifier();
if (!name) {
parseErrorAtPosition(startPos, 0, Diagnostics.Identifier_expected);
parseErrorAtPosition(scanner.getStartPos(), 0, Diagnostics.Identifier_expected);
return undefined;
}
const typeParameter = <TypeParameterDeclaration>createNode(SyntaxKind.TypeParameter, name.pos);
typeParameter.name = name;
finishNode(typeParameter, pos);
finishNode(typeParameter);
typeParameters.push(typeParameter);
skipWhitespace();
if (content.charCodeAt(pos) !== CharacterCodes.comma) {
if (token === SyntaxKind.CommaToken) {
nextJSDocToken();
}
else {
break;
}
pos++;
}
typeParameters.end = pos;
const result = <JSDocTemplateTag>createNode(SyntaxKind.JSDocTemplateTag, atToken.pos);
result.atToken = atToken;
result.tagName = tagName;
result.typeParameters = typeParameters;
return finishNode(result, pos);
finishNode(result);
typeParameters.end = result.end;
return result;
}
function scanIdentifier(): Identifier {
const startPos = pos;
for (; pos < end; pos++) {
const ch = content.charCodeAt(pos);
if (pos === startPos && isIdentifierStart(ch, ScriptTarget.Latest)) {
continue;
}
else if (pos > startPos && isIdentifierPart(ch, ScriptTarget.Latest)) {
continue;
}
function nextJSDocToken(): SyntaxKind {
return token = scanner.scanJSDocToken();
}
break;
}
if (startPos === pos) {
function parseJSDocIdentifier(): Identifier {
if (token !== SyntaxKind.Identifier) {
parseErrorAtCurrentToken(Diagnostics.Identifier_expected);
return undefined;
}
const result = <Identifier>createNode(SyntaxKind.Identifier, startPos);
result.text = content.substring(startPos, pos);
return finishNode(result, pos);
const pos = scanner.getTokenPos();
const end = scanner.getTextPos();
const result = <Identifier>createNode(SyntaxKind.Identifier, pos);
result.text = content.substring(pos, end);
finishNode(result, end);
nextJSDocToken();
return result;
}
}
}

View file

@ -12,7 +12,7 @@ namespace ts {
const emptyArray: any[] = [];
export const version = "1.8.0";
export const version = "1.9.0";
export function findConfigFile(searchPath: string, fileExists: (fileName: string) => boolean): string {
let fileName = "tsconfig.json";

View file

@ -29,6 +29,7 @@ namespace ts {
scanJsxIdentifier(): SyntaxKind;
reScanJsxToken(): SyntaxKind;
scanJsxToken(): SyntaxKind;
scanJSDocToken(): SyntaxKind;
scan(): SyntaxKind;
// Sets the text for the scanner to scan. An optional subrange starting point and length
// can be provided to have the scanner only scan a portion of the text.
@ -42,6 +43,10 @@ namespace ts {
// is returned from this function.
lookAhead<T>(callback: () => T): T;
// Invokes the callback with the scanner set to scan the specified range. When the callback
// returns, the scanner is restored to the state it was in before scanRange was called.
scanRange<T>(start: number, length: number, callback: () => T): T;
// Invokes the provided callback. If the callback returns something falsy, then it restores
// the scanner to the state it was in immediately prior to invoking the callback. If the
// callback returns something truthy, then the scanner state is not rolled back. The result
@ -750,6 +755,7 @@ namespace ts {
scanJsxIdentifier,
reScanJsxToken,
scanJsxToken,
scanJSDocToken,
scan,
setText,
setScriptTarget,
@ -758,6 +764,7 @@ namespace ts {
setTextPos,
tryScan,
lookAhead,
scanRange,
};
function error(message: DiagnosticMessage, length?: number): void {
@ -1665,6 +1672,60 @@ namespace ts {
return token;
}
function scanJSDocToken(): SyntaxKind {
if (pos >= end) {
return token = SyntaxKind.EndOfFileToken;
}
startPos = pos;
// Eat leading whitespace
let ch = text.charCodeAt(pos);
while (pos < end) {
ch = text.charCodeAt(pos);
if (isWhiteSpace(ch)) {
pos++;
}
else {
break;
}
}
tokenPos = pos;
switch (ch) {
case CharacterCodes.at:
return pos += 1, token = SyntaxKind.AtToken;
case CharacterCodes.lineFeed:
case CharacterCodes.carriageReturn:
return pos += 1, token = SyntaxKind.NewLineTrivia;
case CharacterCodes.asterisk:
return pos += 1, token = SyntaxKind.AsteriskToken;
case CharacterCodes.openBrace:
return pos += 1, token = SyntaxKind.OpenBraceToken;
case CharacterCodes.closeBrace:
return pos += 1, token = SyntaxKind.CloseBraceToken;
case CharacterCodes.openBracket:
return pos += 1, token = SyntaxKind.OpenBracketToken;
case CharacterCodes.closeBracket:
return pos += 1, token = SyntaxKind.CloseBracketToken;
case CharacterCodes.equals:
return pos += 1, token = SyntaxKind.EqualsToken;
case CharacterCodes.comma:
return pos += 1, token = SyntaxKind.CommaToken;
}
if (isIdentifierStart(ch, ScriptTarget.Latest)) {
pos++;
while (isIdentifierPart(text.charCodeAt(pos), ScriptTarget.Latest) && pos < end) {
pos++;
}
return token = SyntaxKind.Identifier;
}
else {
return pos += 1, token = SyntaxKind.Unknown;
}
}
function speculationHelper<T>(callback: () => T, isLookahead: boolean): T {
const savePos = pos;
const saveStartPos = startPos;
@ -1687,6 +1748,33 @@ namespace ts {
return result;
}
function scanRange<T>(start: number, length: number, callback: () => T): T {
const saveEnd = end;
const savePos = pos;
const saveStartPos = startPos;
const saveTokenPos = tokenPos;
const saveToken = token;
const savePrecedingLineBreak = precedingLineBreak;
const saveTokenValue = tokenValue;
const saveHasExtendedUnicodeEscape = hasExtendedUnicodeEscape;
const saveTokenIsUnterminated = tokenIsUnterminated;
setText(text, start, length);
const result = callback();
end = saveEnd;
pos = savePos;
startPos = saveStartPos;
tokenPos = saveTokenPos;
token = saveToken;
precedingLineBreak = savePrecedingLineBreak;
tokenValue = saveTokenValue;
hasExtendedUnicodeEscape = saveHasExtendedUnicodeEscape;
tokenIsUnterminated = saveTokenIsUnterminated;
return result;
}
function lookAhead<T>(callback: () => T): T {
return speculationHelper(callback, /*isLookahead*/ true);
}

View file

@ -340,7 +340,7 @@ namespace ts {
if (sys.watchDirectory && configFileName) {
const directory = ts.getDirectoryPath(configFileName);
directoryWatcher = sys.watchDirectory(
// When the configFileName is just "tsconfig.json", the watched directory should be
// When the configFileName is just "tsconfig.json", the watched directory should be
// the current direcotry; if there is a given "project" parameter, then the configFileName
// is an absolute file name.
directory == "" ? "." : directory,

View file

@ -312,11 +312,11 @@ namespace ts {
// Top-level nodes
SourceFile,
// JSDoc nodes.
// JSDoc nodes
JSDocTypeExpression,
// The * type.
// The * type
JSDocAllType,
// The ? type.
// The ? type
JSDocUnknownType,
JSDocArrayType,
JSDocUnionType,
@ -1004,7 +1004,7 @@ namespace ts {
}
// @kind(SyntaxKind.CallExpression)
export interface CallExpression extends LeftHandSideExpression {
export interface CallExpression extends LeftHandSideExpression, Declaration {
expression: LeftHandSideExpression;
typeArguments?: NodeArray<TypeNode>;
arguments: NodeArray<Expression>;
@ -1483,6 +1483,8 @@ namespace ts {
type: JSDocType;
}
export type JSDocTypeReferencingNode = JSDocThisType | JSDocConstructorType | JSDocVariadicType | JSDocOptionalType | JSDocNullableType | JSDocNonNullableType;
// @kind(SyntaxKind.JSDocRecordMember)
export interface JSDocRecordMember extends PropertySignature {
name: Identifier | LiteralExpression;

View file

@ -1064,7 +1064,7 @@ namespace ts {
/**
* Returns true if the node is a CallExpression to the identifier 'require' with
* exactly one string literal argument.
* exactly one argument.
* This function does not test if the node is in a JavaScript file or not.
*/
export function isRequireCall(expression: Node): expression is CallExpression {
@ -1072,8 +1072,7 @@ namespace ts {
return expression.kind === SyntaxKind.CallExpression &&
(<CallExpression>expression).expression.kind === SyntaxKind.Identifier &&
(<Identifier>(<CallExpression>expression).expression).text === "require" &&
(<CallExpression>expression).arguments.length === 1 &&
(<CallExpression>expression).arguments[0].kind === SyntaxKind.StringLiteral;
(<CallExpression>expression).arguments.length === 1;
}
/// Given a BinaryExpression, returns SpecialPropertyAssignmentKind for the various kinds of property
@ -1153,26 +1152,56 @@ namespace ts {
(<JSDocFunctionType>node).parameters[0].type.kind === SyntaxKind.JSDocConstructorType;
}
function getJSDocTag(node: Node, kind: SyntaxKind): JSDocTag {
if (node && node.jsDocComment) {
for (const tag of node.jsDocComment.tags) {
if (tag.kind === kind) {
return tag;
}
function getJSDocTag(node: Node, kind: SyntaxKind, checkParentVariableStatement: boolean): JSDocTag {
if (!node) {
return undefined;
}
const jsDocComment = getJSDocComment(node, checkParentVariableStatement);
if (!jsDocComment) {
return undefined;
}
for (const tag of jsDocComment.tags) {
if (tag.kind === kind) {
return tag;
}
}
}
function getJSDocComment(node: Node, checkParentVariableStatement: boolean): JSDocComment {
if (node.jsDocComment) {
return node.jsDocComment;
}
// Try to recognize this pattern when node is initializer of variable declaration and JSDoc comments are on containing variable statement.
// /**
// * @param {number} name
// * @returns {number}
// */
// var x = function(name) { return name.length; }
if (checkParentVariableStatement) {
const isInitializerOfVariableDeclarationInStatement =
node.parent.kind === SyntaxKind.VariableDeclaration &&
(<VariableDeclaration>node.parent).initializer === node &&
node.parent.parent.parent.kind === SyntaxKind.VariableStatement;
const variableStatementNode = isInitializerOfVariableDeclarationInStatement ? node.parent.parent.parent : undefined;
return variableStatementNode && variableStatementNode.jsDocComment;
}
return undefined;
}
export function getJSDocTypeTag(node: Node): JSDocTypeTag {
return <JSDocTypeTag>getJSDocTag(node, SyntaxKind.JSDocTypeTag);
return <JSDocTypeTag>getJSDocTag(node, SyntaxKind.JSDocTypeTag, /*checkParentVariableStatement*/ false);
}
export function getJSDocReturnTag(node: Node): JSDocReturnTag {
return <JSDocReturnTag>getJSDocTag(node, SyntaxKind.JSDocReturnTag);
return <JSDocReturnTag>getJSDocTag(node, SyntaxKind.JSDocReturnTag, /*checkParentVariableStatement*/ true);
}
export function getJSDocTemplateTag(node: Node): JSDocTemplateTag {
return <JSDocTemplateTag>getJSDocTag(node, SyntaxKind.JSDocTemplateTag);
return <JSDocTemplateTag>getJSDocTag(node, SyntaxKind.JSDocTemplateTag, /*checkParentVariableStatement*/ false);
}
export function getCorrespondingJSDocParameterTag(parameter: ParameterDeclaration): JSDocParameterTag {
@ -1181,19 +1210,21 @@ namespace ts {
// annotation.
const parameterName = (<Identifier>parameter.name).text;
const docComment = parameter.parent.jsDocComment;
if (docComment) {
return <JSDocParameterTag>forEach(docComment.tags, t => {
if (t.kind === SyntaxKind.JSDocParameterTag) {
const parameterTag = <JSDocParameterTag>t;
const jsDocComment = getJSDocComment(parameter.parent, /*checkParentVariableStatement*/ true);
if (jsDocComment) {
for (const tag of jsDocComment.tags) {
if (tag.kind === SyntaxKind.JSDocParameterTag) {
const parameterTag = <JSDocParameterTag>tag;
const name = parameterTag.preParameterName || parameterTag.postParameterName;
if (name.text === parameterName) {
return t;
return parameterTag;
}
}
});
}
}
}
return undefined;
}
export function hasRestParameter(s: SignatureDeclaration): boolean {

View file

@ -572,6 +572,31 @@ namespace FourSlash {
}
}
public verifyCompletionListStartsWithItemsInOrder(items: string[]): void {
if (items.length === 0) {
return;
}
const entries = this.getCompletionListAtCaret().entries;
assert.isTrue(items.length <= entries.length, `Amount of expected items in completion list [ ${items.length} ] is greater than actual number of items in list [ ${entries.length} ]`);
for (let i = 0; i < items.length; i++) {
assert.equal(entries[i].name, items[i], `Unexpected item in completion list`);
}
}
public noItemsWithSameNameButDifferentKind(): void {
const completions = this.getCompletionListAtCaret();
const uniqueItems: ts.Map<string> = {};
for (const item of completions.entries) {
if (!ts.hasProperty(uniqueItems, item.name)) {
uniqueItems[item.name] = item.kind;
}
else {
assert.equal(item.kind, uniqueItems[item.name], `Items should have the same kind, got ${item.kind} and ${uniqueItems[item.name]}`);
}
}
}
public verifyMemberListIsEmpty(negative: boolean) {
const members = this.getMemberListAtCaret();
if ((!members || members.entries.length === 0) && negative) {

2
src/lib/es6.d.ts vendored
View file

@ -819,7 +819,6 @@ interface MapConstructor {
declare var Map: MapConstructor;
interface WeakMap<K, V> {
clear(): void;
delete(key: K): boolean;
get(key: K): V;
has(key: K): boolean;
@ -859,7 +858,6 @@ declare var Set: SetConstructor;
interface WeakSet<T> {
add(value: T): WeakSet<T>;
clear(): void;
delete(value: T): boolean;
has(value: T): boolean;
[Symbol.toStringTag]: "WeakSet";

89
src/lib/es7.d.ts vendored Normal file
View file

@ -0,0 +1,89 @@
interface Array<T> {
/**
* Determines whether an array includes a certain element, returning true or false as appropriate.
* @param searchElement The element to search for.
* @param fromIndex The position in this array at which to begin searching for searchElement.
*/
includes(searchElement: T, fromIndex?: number): boolean;
}
interface Int8Array {
/**
* Determines whether an array includes a certain element, returning true or false as appropriate.
* @param searchElement The element to search for.
* @param fromIndex The position in this array at which to begin searching for searchElement.
*/
includes(searchElement: number, fromIndex?: number): boolean;
}
interface Uint8Array {
/**
* Determines whether an array includes a certain element, returning true or false as appropriate.
* @param searchElement The element to search for.
* @param fromIndex The position in this array at which to begin searching for searchElement.
*/
includes(searchElement: number, fromIndex?: number): boolean;
}
interface Uint8ClampedArray {
/**
* Determines whether an array includes a certain element, returning true or false as appropriate.
* @param searchElement The element to search for.
* @param fromIndex The position in this array at which to begin searching for searchElement.
*/
includes(searchElement: number, fromIndex?: number): boolean;
}
interface Int16Array {
/**
* Determines whether an array includes a certain element, returning true or false as appropriate.
* @param searchElement The element to search for.
* @param fromIndex The position in this array at which to begin searching for searchElement.
*/
includes(searchElement: number, fromIndex?: number): boolean;
}
interface Uint16Array {
/**
* Determines whether an array includes a certain element, returning true or false as appropriate.
* @param searchElement The element to search for.
* @param fromIndex The position in this array at which to begin searching for searchElement.
*/
includes(searchElement: number, fromIndex?: number): boolean;
}
interface Int32Array {
/**
* Determines whether an array includes a certain element, returning true or false as appropriate.
* @param searchElement The element to search for.
* @param fromIndex The position in this array at which to begin searching for searchElement.
*/
includes(searchElement: number, fromIndex?: number): boolean;
}
interface Uint32Array {
/**
* Determines whether an array includes a certain element, returning true or false as appropriate.
* @param searchElement The element to search for.
* @param fromIndex The position in this array at which to begin searching for searchElement.
*/
includes(searchElement: number, fromIndex?: number): boolean;
}
interface Float32Array {
/**
* Determines whether an array includes a certain element, returning true or false as appropriate.
* @param searchElement The element to search for.
* @param fromIndex The position in this array at which to begin searching for searchElement.
*/
includes(searchElement: number, fromIndex?: number): boolean;
}
interface Float64Array {
/**
* Determines whether an array includes a certain element, returning true or false as appropriate.
* @param searchElement The element to search for.
* @param fromIndex The position in this array at which to begin searching for searchElement.
*/
includes(searchElement: number, fromIndex?: number): boolean;
}

View file

@ -120,7 +120,7 @@ namespace ts.server {
if (!resolution) {
const existingResolution = currentResolutionsInFile && ts.lookUp(currentResolutionsInFile, moduleName);
if (moduleResolutionIsValid(existingResolution)) {
// ok, it is safe to use existing module resolution results
// ok, it is safe to use existing module resolution results
resolution = existingResolution;
}
else {
@ -145,8 +145,8 @@ namespace ts.server {
}
if (resolution.resolvedModule) {
// TODO: consider checking failedLookupLocations
// TODO: use lastCheckTime to track expiration for module name resolution
// TODO: consider checking failedLookupLocations
// TODO: use lastCheckTime to track expiration for module name resolution
return true;
}
@ -483,7 +483,7 @@ namespace ts.server {
openFileRootsConfigured: ScriptInfo[] = [];
// a path to directory watcher map that detects added tsconfig files
directoryWatchersForTsconfig: ts.Map<FileWatcher> = {};
// count of how many projects are using the directory watcher. If the
// count of how many projects are using the directory watcher. If the
// number becomes 0 for a watcher, then we should close it.
directoryWatchersRefCount: ts.Map<number> = {};
hostConfiguration: HostConfiguration;
@ -564,11 +564,11 @@ namespace ts.server {
// We check if the project file list has changed. If so, we update the project.
if (!arrayIsEqualTo(currentRootFiles && currentRootFiles.sort(), newRootFiles && newRootFiles.sort())) {
// For configured projects, the change is made outside the tsconfig file, and
// it is not likely to affect the project for other files opened by the client. We can
// it is not likely to affect the project for other files opened by the client. We can
// just update the current project.
this.updateConfiguredProject(project);
// Call updateProjectStructure to clean up inferred projects we may have
// Call updateProjectStructure to clean up inferred projects we may have
// created for the new files
this.updateProjectStructure();
}
@ -792,8 +792,8 @@ namespace ts.server {
* @param info The file that has been closed or newly configured
*/
closeOpenFile(info: ScriptInfo) {
// Closing file should trigger re-reading the file content from disk. This is
// because the user may chose to discard the buffer content before saving
// Closing file should trigger re-reading the file content from disk. This is
// because the user may chose to discard the buffer content before saving
// to the disk, and the server's version of the file can be out of sync.
info.svc.reloadFromFile(info.fileName);
@ -891,8 +891,8 @@ namespace ts.server {
}
/**
* This function is to update the project structure for every projects.
* It is called on the premise that all the configured projects are
* This function is to update the project structure for every projects.
* It is called on the premise that all the configured projects are
* up to date.
*/
updateProjectStructure() {
@ -946,7 +946,7 @@ namespace ts.server {
if (rootFile.defaultProject && rootFile.defaultProject.isConfiguredProject()) {
// If the root file has already been added into a configured project,
// meaning the original inferred project is gone already.
// meaning the original inferred project is gone already.
if (!rootedProject.isConfiguredProject()) {
this.removeProject(rootedProject);
}
@ -1026,10 +1026,16 @@ namespace ts.server {
// the newly opened file.
findConfigFile(searchPath: string): string {
while (true) {
const fileName = ts.combinePaths(searchPath, "tsconfig.json");
if (this.host.fileExists(fileName)) {
return fileName;
const tsconfigFileName = ts.combinePaths(searchPath, "tsconfig.json");
if (this.host.fileExists(tsconfigFileName)) {
return tsconfigFileName;
}
const jsconfigFileName = ts.combinePaths(searchPath, "jsconfig.json");
if (this.host.fileExists(jsconfigFileName)) {
return jsconfigFileName;
}
const parentPath = ts.getDirectoryPath(searchPath);
if (parentPath === searchPath) {
break;
@ -1053,9 +1059,9 @@ namespace ts.server {
}
/**
* This function tries to search for a tsconfig.json for the given file. If we found it,
* This function tries to search for a tsconfig.json for the given file. If we found it,
* we first detect if there is already a configured project created for it: if so, we re-read
* the tsconfig file content and update the project; otherwise we create a new one.
* the tsconfig file content and update the project; otherwise we create a new one.
*/
openOrUpdateConfiguredProjectForFile(fileName: string) {
const searchPath = ts.normalizePath(getDirectoryPath(fileName));
@ -1180,7 +1186,7 @@ namespace ts.server {
return { succeeded: false, error: rawConfig.error };
}
else {
const parsedCommandLine = ts.parseJsonConfigFileContent(rawConfig.config, this.host, dirPath);
const parsedCommandLine = ts.parseJsonConfigFileContent(rawConfig.config, this.host, dirPath, /*existingOptions*/ {}, configFilename);
Debug.assert(!!parsedCommandLine.fileNames);
if (parsedCommandLine.errors && (parsedCommandLine.errors.length > 0)) {
@ -1259,7 +1265,7 @@ namespace ts.server {
info = this.openFile(fileName, /*openedByClient*/ false);
}
else {
// if the root file was opened by client, it would belong to either
// if the root file was opened by client, it would belong to either
// openFileRoots or openFileReferenced.
if (info.isOpen) {
if (this.openFileRoots.indexOf(info) >= 0) {

View file

@ -792,7 +792,9 @@ namespace ts.server {
}
private closeClientFile(fileName: string) {
if (!fileName) { return; }
if (!fileName) {
return;
}
const file = ts.normalizePath(fileName);
this.projectService.closeClientFile(file);
}

View file

@ -7179,8 +7179,7 @@ namespace ts {
const indentationStr = sourceFile.text.substr(lineStart, posLineAndChar.character);
// TODO: call a helper method instead once PR #4133 gets merged in.
const newLine = host.getNewLine ? host.getNewLine() : "\r\n";
const newLine = getNewLineOrDefaultFromHost(host);
let docParams = "";
for (let i = 0, numParams = parameters.length; i < numParams; i++) {

View file

@ -946,7 +946,8 @@ namespace ts {
};
}
const configFile = parseJsonConfigFileContent(result.config, this.host, getDirectoryPath(normalizeSlashes(fileName)));
const normalizedFileName = normalizeSlashes(fileName);
const configFile = parseJsonConfigFileContent(result.config, this.host, getDirectoryPath(normalizedFileName), /*existingOptions*/ {}, normalizedFileName);
return {
options: configFile.options,
@ -1056,6 +1057,6 @@ namespace TypeScript.Services {
// TODO: it should be moved into a namespace though.
/* @internal */
const toolsVersion = "1.8";
const toolsVersion = "1.9";
/* tslint:enable:no-unused-variable */

View file

@ -24,7 +24,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
step((generator = generator.apply(thisArg, _arguments)).next());
});
};
var task_1 = require("./task");
const task_1 = require("./task");
class Test {
example() {
return __awaiter(this, void 0, task_1.Task, function* () { return; });

View file

@ -31,16 +31,16 @@ Object.defineProperty(exports, "__esModule", { value: true });
exports.default = {};
//// [es6ImportDefaultBindingFollowedWithNamedImport_1.js]
"use strict";
var es6ImportDefaultBindingFollowedWithNamedImport_0_1 = require("./es6ImportDefaultBindingFollowedWithNamedImport_0");
const es6ImportDefaultBindingFollowedWithNamedImport_0_1 = require("./es6ImportDefaultBindingFollowedWithNamedImport_0");
var x1 = es6ImportDefaultBindingFollowedWithNamedImport_0_1.a;
var es6ImportDefaultBindingFollowedWithNamedImport_0_2 = require("./es6ImportDefaultBindingFollowedWithNamedImport_0");
const es6ImportDefaultBindingFollowedWithNamedImport_0_2 = require("./es6ImportDefaultBindingFollowedWithNamedImport_0");
var x1 = es6ImportDefaultBindingFollowedWithNamedImport_0_2.a;
var es6ImportDefaultBindingFollowedWithNamedImport_0_3 = require("./es6ImportDefaultBindingFollowedWithNamedImport_0");
const es6ImportDefaultBindingFollowedWithNamedImport_0_3 = require("./es6ImportDefaultBindingFollowedWithNamedImport_0");
var x1 = es6ImportDefaultBindingFollowedWithNamedImport_0_3.x;
var x1 = es6ImportDefaultBindingFollowedWithNamedImport_0_3.a;
var es6ImportDefaultBindingFollowedWithNamedImport_0_4 = require("./es6ImportDefaultBindingFollowedWithNamedImport_0");
const es6ImportDefaultBindingFollowedWithNamedImport_0_4 = require("./es6ImportDefaultBindingFollowedWithNamedImport_0");
var x1 = es6ImportDefaultBindingFollowedWithNamedImport_0_4.x;
var es6ImportDefaultBindingFollowedWithNamedImport_0_5 = require("./es6ImportDefaultBindingFollowedWithNamedImport_0");
const es6ImportDefaultBindingFollowedWithNamedImport_0_5 = require("./es6ImportDefaultBindingFollowedWithNamedImport_0");
var x1 = es6ImportDefaultBindingFollowedWithNamedImport_0_5.m;

View file

@ -15,7 +15,7 @@ import * as nameSpaceBinding2 from "./es6ImportNameSpaceImport_0"; // elide this
exports.a = 10;
//// [es6ImportNameSpaceImport_1.js]
"use strict";
var nameSpaceBinding = require("./es6ImportNameSpaceImport_0");
const nameSpaceBinding = require("./es6ImportNameSpaceImport_0");
var x = nameSpaceBinding.a;

View file

@ -53,26 +53,26 @@ exports.z2 = 10;
exports.aaaa = 10;
//// [es6ImportNamedImport_1.js]
"use strict";
var es6ImportNamedImport_0_1 = require("./es6ImportNamedImport_0");
const es6ImportNamedImport_0_1 = require("./es6ImportNamedImport_0");
var xxxx = es6ImportNamedImport_0_1.a;
var es6ImportNamedImport_0_2 = require("./es6ImportNamedImport_0");
const es6ImportNamedImport_0_2 = require("./es6ImportNamedImport_0");
var xxxx = es6ImportNamedImport_0_2.a;
var es6ImportNamedImport_0_3 = require("./es6ImportNamedImport_0");
const es6ImportNamedImport_0_3 = require("./es6ImportNamedImport_0");
var xxxx = es6ImportNamedImport_0_3.x;
var xxxx = es6ImportNamedImport_0_3.a;
var es6ImportNamedImport_0_4 = require("./es6ImportNamedImport_0");
const es6ImportNamedImport_0_4 = require("./es6ImportNamedImport_0");
var xxxx = es6ImportNamedImport_0_4.x;
var es6ImportNamedImport_0_5 = require("./es6ImportNamedImport_0");
const es6ImportNamedImport_0_5 = require("./es6ImportNamedImport_0");
var xxxx = es6ImportNamedImport_0_5.m;
var es6ImportNamedImport_0_6 = require("./es6ImportNamedImport_0");
const es6ImportNamedImport_0_6 = require("./es6ImportNamedImport_0");
var xxxx = es6ImportNamedImport_0_6.a1;
var xxxx = es6ImportNamedImport_0_6.x1;
var es6ImportNamedImport_0_7 = require("./es6ImportNamedImport_0");
const es6ImportNamedImport_0_7 = require("./es6ImportNamedImport_0");
var xxxx = es6ImportNamedImport_0_7.a1;
var xxxx = es6ImportNamedImport_0_7.x1;
var es6ImportNamedImport_0_8 = require("./es6ImportNamedImport_0");
const es6ImportNamedImport_0_8 = require("./es6ImportNamedImport_0");
var z111 = es6ImportNamedImport_0_8.z1;
var es6ImportNamedImport_0_9 = require("./es6ImportNamedImport_0");
const es6ImportNamedImport_0_9 = require("./es6ImportNamedImport_0");
var z2 = es6ImportNamedImport_0_9.z2; // z2 shouldn't give redeclare error

View file

@ -13,7 +13,7 @@ export = a;
exports.a = 10;
//// [es6ImportNamedImportInExportAssignment_1.js]
"use strict";
var es6ImportNamedImportInExportAssignment_0_1 = require("./es6ImportNamedImportInExportAssignment_0");
const es6ImportNamedImportInExportAssignment_0_1 = require("./es6ImportNamedImportInExportAssignment_0");
module.exports = es6ImportNamedImportInExportAssignment_0_1.a;

View file

@ -67,7 +67,7 @@ exports.M = t1_1.M;
exports.a = t1_1.a;
//// [t3.js]
"use strict";
var t1_1 = require("./t1");
const t1_1 = require("./t1");
exports.v = t1_1.v;
exports.f = t1_1.f;
exports.C = t1_1.C;

View file

@ -24,6 +24,6 @@ exports.y = t1_1.x;
exports.x = t1_1.y;
//// [t3.js]
"use strict";
var t1_1 = require("./t1");
const t1_1 = require("./t1");
exports.y = t1_1.x;
exports.x = t1_1.y;

View file

@ -69,7 +69,7 @@ exports.M = t1_1.M1;
exports.a = t1_1.a1;
//// [t3.js]
"use strict";
var t1_1 = require("./t1");
const t1_1 = require("./t1");
exports.v = t1_1.v1;
exports.f = t1_1.f1;
exports.C = t1_1.C1;

View file

@ -45,24 +45,24 @@ Object.defineProperty(exports, "__esModule", { value: true });
exports.default = "hello";
//// [t3.js]
"use strict";
var a = require("./t1");
const a = require("./t1");
exports.a = a;
a.default;
var t1_1 = require("./t1");
const t1_1 = require("./t1");
exports.b = t1_1.default;
t1_1.default;
var c = require("./t1");
const c = require("./t1");
exports.c = c;
c.default;
var t1_2 = require("./t1");
const t1_2 = require("./t1");
exports.d = t1_2.default;
t1_2.default;
var t1_3 = require("./t1"), e2 = t1_3;
const t1_3 = require("./t1"), e2 = t1_3;
exports.e1 = t1_3.default;
exports.e2 = e2;
t1_3.default;
e2.default;
var t1_4 = require("./t1");
const t1_4 = require("./t1");
exports.f1 = t1_4.default;
exports.f2 = t1_4.default;
t1_4.default;

View file

@ -1,9 +1,10 @@
tests/cases/compiler/functionsMissingReturnStatementsAndExpressions.ts(3,16): error TS2355: A function whose declared type is neither 'void' nor 'any' must return a value.
tests/cases/compiler/functionsMissingReturnStatementsAndExpressions.ts(95,16): error TS2378: A 'get' accessor must return a value.
tests/cases/compiler/functionsMissingReturnStatementsAndExpressions.ts(118,5): error TS1003: Identifier expected.
tests/cases/compiler/functionsMissingReturnStatementsAndExpressions.ts(101,17): error TS2355: A function whose declared type is neither 'void' nor 'any' must return a value.
tests/cases/compiler/functionsMissingReturnStatementsAndExpressions.ts(106,16): error TS2378: A 'get' accessor must return a value.
tests/cases/compiler/functionsMissingReturnStatementsAndExpressions.ts(129,5): error TS1003: Identifier expected.
==== tests/cases/compiler/functionsMissingReturnStatementsAndExpressions.ts (3 errors) ====
==== tests/cases/compiler/functionsMissingReturnStatementsAndExpressions.ts (4 errors) ====
function f1(): string {
@ -98,6 +99,19 @@ tests/cases/compiler/functionsMissingReturnStatementsAndExpressions.ts(118,5): e
return "Okay, not type annotated.";
}
function f19(): void | number {
// Okay; function return type is union containing void
}
function f20(): any | number {
// Okay; function return type is union containing any
}
function f21(): number | string {
~~~~~~~~~~~~~~~
!!! error TS2355: A function whose declared type is neither 'void' nor 'any' must return a value.
// Not okay; union does not contain void or any
}
class C {
public get m1() {

View file

@ -91,6 +91,17 @@ function f18() {
return "Okay, not type annotated.";
}
function f19(): void | number {
// Okay; function return type is union containing void
}
function f20(): any | number {
// Okay; function return type is union containing any
}
function f21(): number | string {
// Not okay; union does not contain void or any
}
class C {
public get m1() {
@ -191,6 +202,15 @@ function f17() {
function f18() {
return "Okay, not type annotated.";
}
function f19() {
// Okay; function return type is union containing void
}
function f20() {
// Okay; function return type is union containing any
}
function f21() {
// Not okay; union does not contain void or any
}
var C = (function () {
function C() {
}

View file

@ -1,14 +1,11 @@
error TS5055: Cannot write file 'tests/cases/compiler/a.js' because it would overwrite input file.
tests/cases/compiler/a.js(3,6): error TS1223: 'type' tag already specified.
!!! error TS5055: Cannot write file 'tests/cases/compiler/a.js' because it would overwrite input file.
==== tests/cases/compiler/a.js (1 errors) ====
==== tests/cases/compiler/a.js (0 errors) ====
/**
* @type {number}
* @type {string}
~~~~
!!! error TS1223: 'type' tag already specified.
*/
var v;

View file

@ -1,9 +1,12 @@
error TS5055: Cannot write file 'tests/cases/compiler/a.js' because it would overwrite input file.
tests/cases/compiler/a.js(1,10): error TS8016: 'type assertion expressions' can only be used in a .ts file.
tests/cases/compiler/a.js(1,10): error TS17008: JSX element 'string' has no corresponding closing tag.
tests/cases/compiler/a.js(1,27): error TS1005: '</' expected.
!!! error TS5055: Cannot write file 'tests/cases/compiler/a.js' because it would overwrite input file.
==== tests/cases/compiler/a.js (1 errors) ====
==== tests/cases/compiler/a.js (2 errors) ====
var v = <string>undefined;
~~~~~~
!!! error TS8016: 'type assertion expressions' can only be used in a .ts file.
!!! error TS17008: JSX element 'string' has no corresponding closing tag.
!!! error TS1005: '</' expected.

View file

@ -20,8 +20,8 @@ use(foo);
exports.x = 1;
//// [test.js]
"use strict";
var existingModule_1 = require('./existingModule');
var missingModule_1 = require('./missingModule');
const existingModule_1 = require('./existingModule');
const missingModule_1 = require('./missingModule');
const test = { x: existingModule_1.x, foo: missingModule_1.foo };
use(existingModule_1.x);
use(missingModule_1.foo);

View file

@ -92,6 +92,17 @@ function f18() {
return "Okay, not type annotated.";
}
function f19(): void | number {
// Okay; function return type is union containing void
}
function f20(): any | number {
// Okay; function return type is union containing any
}
function f21(): number | string {
// Not okay; union does not contain void or any
}
class C {
public get m1() {

View file

@ -23,11 +23,8 @@
////// @pa/*7*/
////var v7;
////
/////** @param { n/*8*/ } */
/////** @return { n/*8*/ } */
////var v8;
////
/////** @return { n/*9*/ } */
////var v9;
goTo.marker('1');
verify.completionListContains("constructor");
@ -57,6 +54,3 @@ verify.completionListIsEmpty();
goTo.marker('8');
verify.completionListContains('number');
goTo.marker('9');
verify.completionListContains('number');

View file

@ -0,0 +1,10 @@
///<reference path="fourslash.ts" />
// @allowNonTsExtensions: true
// @Filename: Foo.js
/////** @type {number} */
////var v;
////v./**/
goTo.marker();
verify.completionListContains("toExponential", /*displayText:*/ undefined, /*documentation*/ undefined, "method");

View file

@ -0,0 +1,11 @@
///<reference path="fourslash.ts" />
// @allowNonTsExtensions: true
// @Filename: Foo.js
/////**
//// * @type {function(this:number)}
//// */
////function f() { this./**/ }
goTo.marker();
verify.completionListContains("toExponential", /*displayText:*/ undefined, /*documentation*/ undefined, "method");

View file

@ -0,0 +1,11 @@
///<reference path="fourslash.ts" />
// @allowNonTsExtensions: true
// @Filename: Foo.js
/////** @type {number|string} */
////var v;
////v./**/
goTo.marker();
verify.completionListContains("toExponential", /*displayText:*/ undefined, /*documentation*/ undefined, "method");
verify.completionListContains("charCodeAt", /*displayText:*/ undefined, /*documentation*/ undefined, "method");

View file

@ -0,0 +1,36 @@
///<reference path="fourslash.ts" />
// @allowNonTsExtensions: true
// @Filename: Foo.js
/////**
//// * @param {number} input
//// * @param {string} currency
//// * @returns {number}
//// */
////var convert = function(input, currency) {
//// switch(currency./*1*/) {
//// case "USD":
//// input./*2*/;
//// case "EUR":
//// return "" + rateToUsd.EUR;
//// case "CNY":
//// return {} + rateToUsd.CNY;
//// }
////}
////convert(1, "")./*3*/
/////**
//// * @param {number} x
//// */
////var test1 = function(x) { return x./*4*/ }, test2 = function(a) { return a./*5*/ };
goTo.marker("1");
verify.completionListContains("charCodeAt", /*displayText:*/ undefined, /*documentation*/ undefined, "method");
goTo.marker("2");
verify.completionListContains("toExponential", /*displayText:*/ undefined, /*documentation*/ undefined, "method");
goTo.marker("3");
verify.completionListContains("toExponential", /*displayText:*/ undefined, /*documentation*/ undefined, "method");
goTo.marker("4");
verify.completionListContains("toExponential", /*displayText:*/ undefined, /*documentation*/ undefined, "method");
goTo.marker("5");
verify.completionListContains("test1", /*displayText:*/ undefined, /*documentation*/ undefined, "warning");

View file

@ -0,0 +1,26 @@
/// <reference path="fourslash.ts" />
// @allowNonTsExtensions: true
// @Filename: file1.js
////var file1Identifier = 1;
////interface Foo { FooProp: number };
// @Filename: file2.js
////var file2Identifier1 = 2;
////var file2Identifier2 = 2;
/////*1*/
////file2Identifier2./*2*/
goTo.marker("1");
verify.completionListContains("file2Identifier1");
verify.completionListContains("file2Identifier2");
verify.completionListContains("file1Identifier");
verify.not.completionListContains("FooProp");
goTo.marker("2");
verify.completionListContains("file2Identifier1");
verify.completionListContains("file2Identifier2");
verify.not.completionListContains("file1Identifier")
verify.not.completionListContains("FooProp");

View file

@ -0,0 +1,13 @@
/// <reference path="fourslash.ts" />
// @allowNonTsExtensions: true
// @Filename: file1.js
/////// <reference no-default-lib="true"/>
////interface Number {
//// toExponential(fractionDigits?: number): string;
////}
////var x = 1;
////x./*1*/
goTo.marker("1");
verify.completionListContains("toExponential", /*displayText:*/ undefined, /*documentation*/ undefined, "method");

View file

@ -0,0 +1,29 @@
/// <reference path="fourslash.ts" />
// @allowNonTsExtensions: true
// @Filename: refFile1.ts
//// export var V = 1;
// @Filename: refFile2.ts
//// export var V = "123"
// @Filename: refFile3.ts
//// export var V = "123"
// @Filename: main.js
//// import ref1 = require("refFile1");
//// var ref2 = require("refFile2");
//// ref1.V./*1*/;
//// ref2.V./*2*/;
//// var v = { x: require("refFile3") };
//// v.x./*3*/;
//// v.x.V./*4*/;
goTo.marker("1");
verify.completionListContains("toExponential");
goTo.marker("2");
verify.completionListContains("toLowerCase");
goTo.marker("3");
verify.completionListContains("V");
goTo.marker("4");
verify.completionListContains("toLowerCase");

View file

@ -0,0 +1,10 @@
///<reference path="fourslash.ts" />
// @allowNonTsExtensions: true
// @Filename: Foo.js
/////** @type {(number|string)} */
////var v;
////v./**/
goTo.marker();
verify.completionListContains("valueOf", /*displayText:*/ undefined, /*documentation*/ undefined, "method");

View file

@ -0,0 +1,10 @@
///<reference path="fourslash.ts" />
// @allowNonTsExtensions: true
// @Filename: Foo.js
/////** @type {Array.<number>} */
////var v;
////v./**/
goTo.marker();
verify.completionListContains("concat", /*displayText:*/ undefined, /*documentation*/ undefined, "method");

View file

@ -0,0 +1,10 @@
///<reference path="fourslash.ts" />
// @allowNonTsExtensions: true
// @Filename: Foo.js
/////** @return {number} */
////function foo(a,b) { }
////foo(1,2)./**/
goTo.marker();
verify.completionListContains("toExponential", /*displayText:*/ undefined, /*documentation*/ undefined, "method");

View file

@ -0,0 +1,15 @@
///<reference path="fourslash.ts" />
// @allowNonTsExtensions: true
// @Filename: Foo.js
//// /**
//// * @template T
//// * @param {T} a
//// * @return {T} */
//// function foo(a) { }
//// let x = /*1*/foo;
//// foo(1)./**/
goTo.marker('1');
goTo.marker();
verify.completionListContains("toExponential", /*displayText:*/ undefined, /*documentation*/ undefined, "method");

View file

@ -0,0 +1,13 @@
///<reference path="fourslash.ts" />
// @allowNonTsExtensions: true
// @Filename: Foo.js
/////**
//// * @param {...number} a
//// */
////function foo(a) {
//// a./**/
////}
goTo.marker();
verify.completionListContains("concat", /*displayText:*/ undefined, /*documentation*/ undefined, "method");

View file

@ -0,0 +1,13 @@
///<reference path="fourslash.ts" />
// @allowNonTsExtensions: true
// @Filename: Foo.js
/////**
//// * @param {...number} a
//// */
////function foo(a) {
//// a[0]./**/
////}
goTo.marker();
verify.completionListContains("toExponential", /*displayText:*/ undefined, /*documentation*/ undefined, "method");

View file

@ -0,0 +1,12 @@
///<reference path="fourslash.ts" />
// @allowNonTsExtensions: true
// @Filename: Foo.js
/////**
//// * @type {function(): number}
//// */
////var v;
////v()./**/
goTo.marker();
verify.completionListContains("toExponential", /*displayText:*/ undefined, /*documentation*/ undefined, "method");

View file

@ -0,0 +1,12 @@
///<reference path="fourslash.ts" />
// @allowNonTsExtensions: true
// @Filename: Foo.js
/////**
//// * @type {function(new:number)}
//// */
////var v;
////new v()./**/
goTo.marker();
verify.completionListContains("toExponential", /*displayText:*/ undefined, /*documentation*/ undefined, "method");

View file

@ -0,0 +1,9 @@
/// <reference path='fourslash.ts'/>
// @allowNonTsExtensions: true
// @Filename: Foo.js
/////** @type {function(new:string,number)} */
////var /**/v;
goTo.marker();
verify.quickInfoIs('var v: new (p1: number) => string');

View file

@ -0,0 +1,9 @@
/// <reference path='fourslash.ts'/>
// @allowNonTsExtensions: true
// @Filename: Foo.js
/////** @param {number} [a] */
////function /**/f(a) { }
goTo.marker();
verify.quickInfoIs('function f(a?: number): void');

View file

@ -0,0 +1,9 @@
/// <reference path='fourslash.ts'/>
// @allowNonTsExtensions: true
// @Filename: Foo.js
/////** @param {number[]} [a] */
////function /**/f(a) { }
goTo.marker();
verify.quickInfoIs('function f(a?: number[]): void');

View file

@ -0,0 +1,9 @@
/// <reference path='fourslash.ts'/>
// @allowNonTsExtensions: true
// @Filename: Foo.js
/////** @param {[number,string]} [a] */
////function /**/f(a) { }
goTo.marker();
verify.quickInfoIs('function f(a?: [number, string]): void');

View file

@ -0,0 +1,9 @@
/// <reference path='fourslash.ts'/>
// @allowNonTsExtensions: true
// @Filename: Foo.js
/////** @param {{b:number}} [a] */
////function /**/f(a) { }
goTo.marker();
verify.quickInfoIs('function f(a?: {\n b: number;\n}): void');

View file

@ -0,0 +1,9 @@
/// <reference path='fourslash.ts'/>
// @allowNonTsExtensions: true
// @Filename: Foo.js
/////** @type {function(this:number)} */
////function f() { /**/this }
goTo.marker();
verify.quickInfoIs('number');

View file

@ -1,16 +0,0 @@
/// <reference path="fourslash.ts" />
// @allowJs: true
// @Filename: a.js
//// var v = <string>undefined;
verify.getSyntacticDiagnostics(`[]`);
verify.getSemanticDiagnostics(`[
{
"message": "'type assertion expressions' can only be used in a .ts file.",
"start": 9,
"length": 6,
"category": "error",
"code": 8016
}
]`);

View file

@ -0,0 +1,12 @@
///<reference path="fourslash.ts" />
// Error: Having more function parameters than entries in the dependency array
// @allowNonTsExtensions: true
// @Filename: Foo.js
//// define('mod1', ['a'], /**/function(a, b) {
////
//// });
// TODO: what should happen?
goTo.marker();

View file

@ -1,4 +1,5 @@
/// <reference path="..\..\..\src\harness\external\mocha.d.ts" />
/// <reference path="..\..\..\src\harness\external\chai.d.ts" />
/// <reference path="..\..\..\src\compiler\parser.ts" />
/// <reference path="..\..\..\src\harness\harness.ts" />
@ -985,15 +986,29 @@ module ts {
describe("DocComments", () => {
function parsesCorrectly(content: string, expected: string) {
let comment = parseIsolatedJSDocComment(content);
Debug.assert(comment && comment.diagnostics.length === 0);
if (!comment) {
Debug.fail('Comment failed to parse entirely');
}
if (comment.diagnostics.length > 0) {
Debug.fail('Comment has at least one diagnostic: ' + comment.diagnostics[0].messageText);
}
let result = JSON.stringify(comment.jsDocComment, (k, v) => {
return v && v.pos !== undefined
? JSON.parse(Utils.sourceFileToJSON(v))
: v;
}, " ");
}, 4);
assert.equal(result, expected);
if (result !== expected) {
// Turn on a human-readable diff
if (typeof require !== 'undefined') {
require('chai').config.showDiff = true;
chai.expect(JSON.parse(result)).equal(JSON.parse(expected));
}
else {
assert.equal(result, expected);
}
}
}
function parsesIncorrectly(content: string) {
@ -1577,7 +1592,7 @@ module ts {
"0": {
"kind": "JSDocParameterTag",
"pos": 8,
"end": 30,
"end": 31,
"atToken": {
"kind": "AtToken",
"pos": 8,
@ -1609,7 +1624,7 @@ module ts {
},
"length": 1,
"pos": 8,
"end": 30
"end": 31
}
}`);
});
@ -1627,7 +1642,7 @@ module ts {
"0": {
"kind": "JSDocParameterTag",
"pos": 8,
"end": 31,
"end": 36,
"atToken": {
"kind": "AtToken",
"pos": 8,
@ -1659,7 +1674,7 @@ module ts {
},
"length": 1,
"pos": 8,
"end": 31
"end": 36
}
}`);
});
@ -2113,7 +2128,7 @@ module ts {
"0": {
"kind": "JSDocTemplateTag",
"pos": 8,
"end": 24,
"end": 23,
"atToken": {
"kind": "AtToken",
"pos": 8,
@ -2150,12 +2165,12 @@ module ts {
},
"length": 2,
"pos": 17,
"end": 24
"end": 23
}
},
"length": 1,
"pos": 8,
"end": 24
"end": 23
}
}`);
});