mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-02-19 08:24:15 -06:00
Simple case and scoping
This commit is contained in:
parent
89350b35f0
commit
df91ef0b38
@ -404,6 +404,13 @@ namespace ts {
|
||||
// This node will now be set as the parent of all of its children as we recurse into them.
|
||||
parent = node;
|
||||
|
||||
// Binding of JsDocComment should be done before the current block scope container changes.
|
||||
// because the scope of JsDocComment should not be affected by whether the current node is a
|
||||
// container or not.
|
||||
if (isInJavaScriptFile(node) && node.jsDocComment) {
|
||||
bind(node.jsDocComment);
|
||||
}
|
||||
|
||||
// Depending on what kind of node this is, we may have to adjust the current container
|
||||
// and block-container. If the current node is a container, then it is automatically
|
||||
// considered the current block-container as well. Also, for containers that we know
|
||||
@ -468,10 +475,6 @@ 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)) {
|
||||
@ -857,7 +860,7 @@ namespace ts {
|
||||
// their container in the tree. To accomplish this, we simply add their declared
|
||||
// symbol to the 'locals' of the container. These symbols can then be found as
|
||||
// the type checker walks up the containers, checking them for matching names.
|
||||
return declareSymbol(container.locals, undefined, node, symbolFlags, symbolExcludes);
|
||||
return declareSymbol(container.locals, /*parent*/ undefined, node, symbolFlags, symbolExcludes);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1343,6 +1346,7 @@ namespace ts {
|
||||
return bindClassLikeDeclaration(<ClassLikeDeclaration>node);
|
||||
case SyntaxKind.InterfaceDeclaration:
|
||||
return bindBlockScopedDeclaration(<Declaration>node, SymbolFlags.Interface, SymbolFlags.InterfaceExcludes);
|
||||
case SyntaxKind.JSDocTypedefTag:
|
||||
case SyntaxKind.TypeAliasDeclaration:
|
||||
return bindBlockScopedDeclaration(<Declaration>node, SymbolFlags.TypeAlias, SymbolFlags.TypeAliasExcludes);
|
||||
case SyntaxKind.EnumDeclaration:
|
||||
|
||||
@ -3403,7 +3403,7 @@ namespace ts {
|
||||
return <InterfaceType>links.declaredType;
|
||||
}
|
||||
|
||||
function getDeclaredTypeOfTypeAlias(symbol: Symbol): Type {
|
||||
function getDeclaredTypeOfTypeAlias(symbol: Symbol, node?: Node): Type {
|
||||
const links = getSymbolLinks(symbol);
|
||||
if (!links.declaredType) {
|
||||
// Note that we use the links object as the target here because the symbol object is used as the unique
|
||||
@ -3411,8 +3411,18 @@ namespace ts {
|
||||
if (!pushTypeResolution(symbol, TypeSystemPropertyName.DeclaredType)) {
|
||||
return unknownType;
|
||||
}
|
||||
const declaration = <TypeAliasDeclaration>getDeclarationOfKind(symbol, SyntaxKind.TypeAliasDeclaration);
|
||||
let type = getTypeFromTypeNode(declaration.type);
|
||||
|
||||
let typeNode: TypeNode;
|
||||
let name: Identifier;
|
||||
if (node && (node.flags & NodeFlags.JavaScriptFile)) {
|
||||
const declaration = <JSDocTypedefTag>getDeclarationOfKind(symbol, SyntaxKind.JSDocTypedefTag);
|
||||
typeNode = declaration.typeExpression.type;
|
||||
}
|
||||
if (!typeNode) {
|
||||
const declaration = <TypeAliasDeclaration>getDeclarationOfKind(symbol, SyntaxKind.TypeAliasDeclaration);
|
||||
typeNode = declaration.type;
|
||||
}
|
||||
let type = getTypeFromTypeNode(typeNode);
|
||||
if (popTypeResolution()) {
|
||||
links.typeParameters = getLocalTypeParametersOfClassOrInterfaceOrTypeAlias(symbol);
|
||||
if (links.typeParameters) {
|
||||
@ -3424,7 +3434,7 @@ namespace ts {
|
||||
}
|
||||
else {
|
||||
type = unknownType;
|
||||
error(declaration.name, Diagnostics.Type_alias_0_circularly_references_itself, symbolToString(symbol));
|
||||
error(name, Diagnostics.Type_alias_0_circularly_references_itself, symbolToString(symbol));
|
||||
}
|
||||
links.declaredType = type;
|
||||
}
|
||||
@ -3462,13 +3472,13 @@ namespace ts {
|
||||
return links.declaredType;
|
||||
}
|
||||
|
||||
function getDeclaredTypeOfSymbol(symbol: Symbol): Type {
|
||||
function getDeclaredTypeOfSymbol(symbol: Symbol, node?: Node): Type {
|
||||
Debug.assert((symbol.flags & SymbolFlags.Instantiated) === 0);
|
||||
if (symbol.flags & (SymbolFlags.Class | SymbolFlags.Interface)) {
|
||||
return getDeclaredTypeOfClassOrInterface(symbol);
|
||||
}
|
||||
if (symbol.flags & SymbolFlags.TypeAlias) {
|
||||
return getDeclaredTypeOfTypeAlias(symbol);
|
||||
return getDeclaredTypeOfTypeAlias(symbol, node);
|
||||
}
|
||||
if (symbol.flags & SymbolFlags.Enum) {
|
||||
return getDeclaredTypeOfEnum(symbol);
|
||||
@ -4564,7 +4574,7 @@ namespace ts {
|
||||
// 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 | JSDocTypeReference, symbol: Symbol): Type {
|
||||
const type = getDeclaredTypeOfSymbol(symbol);
|
||||
const type = getDeclaredTypeOfSymbol(symbol, node);
|
||||
const links = getSymbolLinks(symbol);
|
||||
const typeParameters = links.typeParameters;
|
||||
if (typeParameters) {
|
||||
|
||||
@ -811,6 +811,10 @@
|
||||
"category": "Error",
|
||||
"code": 1249
|
||||
},
|
||||
"'{0}' tag cannot be used independently as a top level JSDoc tag.": {
|
||||
"category": "Error",
|
||||
"code": 1250
|
||||
},
|
||||
"'with' statements are not allowed in an async function block.": {
|
||||
"category": "Error",
|
||||
"code": 1300
|
||||
|
||||
@ -401,6 +401,8 @@ namespace ts {
|
||||
return visitNode(cbNode, (<JSDocTypeTag>node).typeExpression);
|
||||
case SyntaxKind.JSDocTemplateTag:
|
||||
return visitNodes(cbNodes, (<JSDocTemplateTag>node).typeParameters);
|
||||
case SyntaxKind.JSDocTypedefTag:
|
||||
return visitNode(cbNode, (<JSDocTypedefTag>node).typeExpression);
|
||||
}
|
||||
}
|
||||
|
||||
@ -886,7 +888,7 @@ namespace ts {
|
||||
|
||||
/** Invokes the provided callback then unconditionally restores the parser to the state it
|
||||
* was in immediately prior to invoking the callback. The result of invoking the callback
|
||||
* is returned from this function.
|
||||
* is returned from this function.
|
||||
*/
|
||||
function lookAhead<T>(callback: () => T): T {
|
||||
return speculationHelper(callback, /*isLookAhead*/ true);
|
||||
@ -2068,11 +2070,11 @@ namespace ts {
|
||||
}
|
||||
|
||||
function fillSignature(
|
||||
returnToken: SyntaxKind,
|
||||
yieldContext: boolean,
|
||||
awaitContext: boolean,
|
||||
requireCompleteParameterList: boolean,
|
||||
signature: SignatureDeclaration): void {
|
||||
returnToken: SyntaxKind,
|
||||
yieldContext: boolean,
|
||||
awaitContext: boolean,
|
||||
requireCompleteParameterList: boolean,
|
||||
signature: SignatureDeclaration): void {
|
||||
|
||||
const returnTokenRequired = returnToken === SyntaxKind.EqualsGreaterThanToken;
|
||||
signature.typeParameters = parseTypeParameters();
|
||||
@ -3341,8 +3343,8 @@ namespace ts {
|
||||
if (sourceFile.languageVariant !== LanguageVariant.JSX) {
|
||||
return false;
|
||||
}
|
||||
// We are in JSX context and the token is part of JSXElement.
|
||||
// Fall through
|
||||
// We are in JSX context and the token is part of JSXElement.
|
||||
// Fall through
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
@ -4044,9 +4046,9 @@ namespace ts {
|
||||
const isAsync = !!(node.flags & NodeFlags.Async);
|
||||
node.name =
|
||||
isGenerator && isAsync ? doInYieldAndAwaitContext(parseOptionalIdentifier) :
|
||||
isGenerator ? doInYieldContext(parseOptionalIdentifier) :
|
||||
isAsync ? doInAwaitContext(parseOptionalIdentifier) :
|
||||
parseOptionalIdentifier();
|
||||
isGenerator ? doInYieldContext(parseOptionalIdentifier) :
|
||||
isAsync ? doInAwaitContext(parseOptionalIdentifier) :
|
||||
parseOptionalIdentifier();
|
||||
|
||||
fillSignature(SyntaxKind.ColonToken, /*yieldContext*/ isGenerator, /*awaitContext*/ isAsync, /*requireCompleteParameterList*/ false, node);
|
||||
node.body = parseFunctionBlock(/*allowYield*/ isGenerator, /*allowAwait*/ isAsync, /*ignoreMissingOpenBrace*/ false);
|
||||
@ -4984,7 +4986,7 @@ namespace ts {
|
||||
|
||||
if (token === SyntaxKind.ConstKeyword && permitInvalidConstAsModifier) {
|
||||
// We need to ensure that any subsequent modifiers appear on the same line
|
||||
// so that when 'const' is a standalone declaration, we don't issue an error.
|
||||
// so that when 'const' is a standalone declaration, we don't issue an error.
|
||||
if (!tryParse(nextTokenIsOnSameLineAndCanFollowModifier)) {
|
||||
break;
|
||||
}
|
||||
@ -5247,7 +5249,7 @@ namespace ts {
|
||||
node.decorators = decorators;
|
||||
setModifiers(node, modifiers);
|
||||
if (token === SyntaxKind.GlobalKeyword) {
|
||||
// parse 'global' as name of global scope augmentation
|
||||
// parse 'global' as name of global scope augmentation
|
||||
node.name = parseIdentifier();
|
||||
node.flags |= NodeFlags.GlobalAugmentation;
|
||||
}
|
||||
@ -5829,7 +5831,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
function checkForEmptyTypeArgumentList(typeArguments: NodeArray<Node>) {
|
||||
if (parseDiagnostics.length === 0 && typeArguments && typeArguments.length === 0) {
|
||||
if (parseDiagnostics.length === 0 && typeArguments && typeArguments.length === 0) {
|
||||
const start = typeArguments.pos - "<".length;
|
||||
const end = skipTrivia(sourceText, typeArguments.end) + ">".length;
|
||||
return parseErrorAtPosition(start, end - start, Diagnostics.Type_argument_list_cannot_be_empty);
|
||||
@ -5990,6 +5992,7 @@ namespace ts {
|
||||
Debug.assert(end <= content.length);
|
||||
|
||||
let tags: NodeArray<JSDocTag>;
|
||||
let currentParentJSDocDeclaration: Declaration;
|
||||
|
||||
let result: JSDocComment;
|
||||
|
||||
@ -6097,6 +6100,11 @@ namespace ts {
|
||||
return handleTemplateTag(atToken, tagName);
|
||||
case "type":
|
||||
return handleTypeTag(atToken, tagName);
|
||||
case "typedef":
|
||||
return handleTypedefTag(atToken, tagName);
|
||||
case "property":
|
||||
case "prop":
|
||||
return handlePropertyTag(atToken, tagName);
|
||||
}
|
||||
}
|
||||
|
||||
@ -6204,6 +6212,56 @@ namespace ts {
|
||||
return finishNode(result);
|
||||
}
|
||||
|
||||
function handlePropertyTag(atToken: Node, tagName: Identifier): JSDocPropertyTag {
|
||||
if (!currentParentJSDocDeclaration) {
|
||||
parseErrorAtPosition(tagName.pos, scanner.getTokenPos() - tagName.pos, Diagnostics._0_tag_cannot_be_used_independently_as_a_top_level_JSDoc_tag, tagName.text);
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const typeExpression = tryParseTypeExpression();
|
||||
skipWhitespace();
|
||||
const name = parseJSDocIdentifier();
|
||||
if (!name) {
|
||||
parseErrorAtPosition(scanner.getStartPos(), /*length*/ 0, Diagnostics.Identifier_expected);
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const result = <JSDocPropertyTag>createNode(SyntaxKind.JSDocPropertyTag, atToken.pos);
|
||||
result.atToken = atToken;
|
||||
result.tagName = tagName;
|
||||
result.name = name;
|
||||
result.typeExpression = typeExpression;
|
||||
return finishNode(result);
|
||||
}
|
||||
|
||||
function handleTypedefTag(atToken: Node, tagName: Identifier): JSDocTypedefTag {
|
||||
const typeExpression = tryParseTypeExpression();
|
||||
skipWhitespace();
|
||||
const name = parseJSDocIdentifier();
|
||||
if (!name) {
|
||||
parseErrorAtPosition(scanner.getStartPos(), 0, Diagnostics.Identifier_expected);
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const result = <JSDocTypedefTag>createNode(SyntaxKind.JSDocTypedefTag, atToken.pos);
|
||||
result.atToken = atToken;
|
||||
result.tagName = tagName;
|
||||
result.name = name;
|
||||
result.typeExpression = typeExpression;
|
||||
|
||||
// if (typeExpression && typeExpression.type.kind === SyntaxKind.JSDocTypeReference) {
|
||||
// const jsDocTypeReference = <JSDocTypeReference>typeExpression.type;
|
||||
// if (jsDocTypeReference.name.kind === SyntaxKind.Identifier) {
|
||||
// const name = <Identifier>jsDocTypeReference.name;
|
||||
// if (name.text === "Object") {
|
||||
// currentParentJSDocDeclaration = declaration;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
function handleTemplateTag(atToken: Node, tagName: Identifier): JSDocTemplateTag {
|
||||
if (forEach(tags, t => t.kind === SyntaxKind.JSDocTemplateTag)) {
|
||||
parseErrorAtPosition(tagName.pos, scanner.getTokenPos() - tagName.pos, Diagnostics._0_tag_already_specified, tagName.text);
|
||||
|
||||
@ -342,6 +342,10 @@ namespace ts {
|
||||
JSDocReturnTag,
|
||||
JSDocTypeTag,
|
||||
JSDocTemplateTag,
|
||||
JSDocTypedefTag,
|
||||
JSDocPropertyTag,
|
||||
JSDocTypedefDeclaration,
|
||||
JSDocTypeLiteral,
|
||||
|
||||
// Synthesized list
|
||||
SyntaxList,
|
||||
@ -1510,6 +1514,29 @@ namespace ts {
|
||||
typeExpression: JSDocTypeExpression;
|
||||
}
|
||||
|
||||
// @kind(SyntaxKind.JSDocTypedefTag)
|
||||
export interface JSDocTypedefTag extends JSDocTag, Declaration {
|
||||
name: Identifier;
|
||||
typeExpression: JSDocTypeExpression;
|
||||
}
|
||||
|
||||
// @kind(SyntaxKind.JSDocPropertyTag)
|
||||
export interface JSDocPropertyTag extends JSDocTag, TypeElement {
|
||||
name: Identifier;
|
||||
typeExpression: JSDocTypeExpression;
|
||||
}
|
||||
|
||||
// @kind(SyntaxKind.JSDocTypedefDeclaration)
|
||||
export interface JSDocTypedefDeclaration extends Declaration {
|
||||
name: Identifier;
|
||||
type: TypeNode;
|
||||
}
|
||||
|
||||
// @kind(SyntaxKind.JSDocTypeLiteral)
|
||||
export interface JSDocTypeLiteral extends TypeNode {
|
||||
members: NodeArray<TypeElement>;
|
||||
}
|
||||
|
||||
// @kind(SyntaxKind.JSDocParameterTag)
|
||||
export interface JSDocParameterTag extends JSDocTag {
|
||||
preParameterName?: Identifier;
|
||||
@ -2094,7 +2121,7 @@ namespace ts {
|
||||
jsxFlags?: JsxFlags; // flags for knowing what kind of element/attributes we're dealing with
|
||||
resolvedJsxType?: Type; // resolved element attributes type of a JSX openinglike element
|
||||
hasSuperCall?: boolean; // recorded result when we try to find super-call. We only try to find one if this flag is undefined, indicating that we haven't made an attempt.
|
||||
superCall?: ExpressionStatement; // Cached first super-call found in the constructor. Used in checking whether super is called before this-accessing
|
||||
superCall?: ExpressionStatement; // Cached first super-call found in the constructor. Used in checking whether super is called before this-accessing
|
||||
}
|
||||
|
||||
export const enum TypeFlags {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user