mirror of
https://github.com/microsoft/TypeScript.git
synced 2025-11-18 17:21:48 +00:00
Merge remote-tracking branch 'origin/master' into useReturnedThisFromSuperCalls
This commit is contained in:
+2
-1
@@ -129,6 +129,7 @@ var servicesSources = [
|
||||
"documentRegistry.ts",
|
||||
"findAllReferences.ts",
|
||||
"goToDefinition.ts",
|
||||
"goToImplementation.ts",
|
||||
"jsDoc.ts",
|
||||
"jsTyping.ts",
|
||||
"navigateTo.ts",
|
||||
@@ -789,7 +790,7 @@ function cleanTestDirs() {
|
||||
|
||||
// used to pass data from jake command line directly to run.js
|
||||
function writeTestConfigFile(tests, light, taskConfigsFolder, workerCount, stackTraceLimit) {
|
||||
var testConfigContents = JSON.stringify({
|
||||
var testConfigContents = JSON.stringify({
|
||||
test: tests ? [tests] : undefined,
|
||||
light: light,
|
||||
workerCount: workerCount,
|
||||
|
||||
@@ -268,7 +268,7 @@ namespace ts {
|
||||
Debug.assert(node.parent.kind === SyntaxKind.JSDocFunctionType);
|
||||
let functionType = <JSDocFunctionType>node.parent;
|
||||
let index = indexOf(functionType.parameters, node);
|
||||
return "p" + index;
|
||||
return "arg" + index;
|
||||
case SyntaxKind.JSDocTypedefTag:
|
||||
const parentNode = node.parent && node.parent.parent;
|
||||
let nameFromParentNode: string;
|
||||
@@ -540,9 +540,7 @@ namespace ts {
|
||||
// because the scope of JsDocComment should not be affected by whether the current node is a
|
||||
// container or not.
|
||||
if (isInJavaScriptFile(node) && node.jsDocComments) {
|
||||
for (const jsDocComment of node.jsDocComments) {
|
||||
bind(jsDocComment);
|
||||
}
|
||||
forEach(node.jsDocComments, bind);
|
||||
}
|
||||
if (checkUnreachable(node)) {
|
||||
forEachChild(node, bind);
|
||||
|
||||
+31
-15
@@ -914,8 +914,8 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
// If we're in an external module, we can't reference symbols created from UMD export declarations
|
||||
if (result && isInExternalModule) {
|
||||
// If we're in an external module, we can't reference value symbols created from UMD export declarations
|
||||
if (result && isInExternalModule && (meaning & SymbolFlags.Value) === SymbolFlags.Value) {
|
||||
const decls = result.declarations;
|
||||
if (decls && decls.length === 1 && decls[0].kind === SyntaxKind.NamespaceExportDeclaration) {
|
||||
error(errorLocation, Diagnostics.Identifier_0_must_be_imported_from_a_module, name);
|
||||
@@ -1758,7 +1758,15 @@ namespace ts {
|
||||
return false;
|
||||
}
|
||||
|
||||
function isSymbolAccessible(symbol: Symbol, enclosingDeclaration: Node, meaning: SymbolFlags): SymbolAccessibilityResult {
|
||||
/**
|
||||
* Check if the given symbol in given enclosing declaration is accessible and mark all associated alias to be visible if requested
|
||||
*
|
||||
* @param symbol a Symbol to check if accessible
|
||||
* @param enclosingDeclaration a Node containing reference to the symbol
|
||||
* @param meaning a SymbolFlags to check if such meaning of the symbol is accessible
|
||||
* @param shouldComputeAliasToMakeVisible a boolean value to indicate whether to return aliases to be mark visible in case the symbol is accessible
|
||||
*/
|
||||
function isSymbolAccessible(symbol: Symbol, enclosingDeclaration: Node, meaning: SymbolFlags, shouldComputeAliasesToMakeVisible: boolean): SymbolAccessibilityResult {
|
||||
if (symbol && enclosingDeclaration && !(symbol.flags & SymbolFlags.TypeParameter)) {
|
||||
const initialSymbol = symbol;
|
||||
let meaningToLook = meaning;
|
||||
@@ -1766,7 +1774,7 @@ namespace ts {
|
||||
// Symbol is accessible if it by itself is accessible
|
||||
const accessibleSymbolChain = getAccessibleSymbolChain(symbol, enclosingDeclaration, meaningToLook, /*useOnlyExternalAliasing*/ false);
|
||||
if (accessibleSymbolChain) {
|
||||
const hasAccessibleDeclarations = hasVisibleDeclarations(accessibleSymbolChain[0]);
|
||||
const hasAccessibleDeclarations = hasVisibleDeclarations(accessibleSymbolChain[0], shouldComputeAliasesToMakeVisible);
|
||||
if (!hasAccessibleDeclarations) {
|
||||
return <SymbolAccessibilityResult>{
|
||||
accessibility: SymbolAccessibility.NotAccessible,
|
||||
@@ -1830,7 +1838,7 @@ namespace ts {
|
||||
return isAmbientModule(declaration) || (declaration.kind === SyntaxKind.SourceFile && isExternalOrCommonJsModule(<SourceFile>declaration));
|
||||
}
|
||||
|
||||
function hasVisibleDeclarations(symbol: Symbol): SymbolVisibilityResult {
|
||||
function hasVisibleDeclarations(symbol: Symbol, shouldComputeAliasToMakeVisible: boolean): SymbolVisibilityResult {
|
||||
let aliasesToMakeVisible: AnyImportSyntax[];
|
||||
if (forEach(symbol.declarations, declaration => !getIsDeclarationVisible(declaration))) {
|
||||
return undefined;
|
||||
@@ -1846,14 +1854,19 @@ namespace ts {
|
||||
if (anyImportSyntax &&
|
||||
!(getModifierFlags(anyImportSyntax) & ModifierFlags.Export) && // import clause without export
|
||||
isDeclarationVisible(<Declaration>anyImportSyntax.parent)) {
|
||||
getNodeLinks(declaration).isVisible = true;
|
||||
if (aliasesToMakeVisible) {
|
||||
if (!contains(aliasesToMakeVisible, anyImportSyntax)) {
|
||||
aliasesToMakeVisible.push(anyImportSyntax);
|
||||
// In function "buildTypeDisplay" where we decide whether to write type-alias or serialize types,
|
||||
// we want to just check if type- alias is accessible or not but we don't care about emitting those alias at that time
|
||||
// since we will do the emitting later in trackSymbol.
|
||||
if (shouldComputeAliasToMakeVisible) {
|
||||
getNodeLinks(declaration).isVisible = true;
|
||||
if (aliasesToMakeVisible) {
|
||||
if (!contains(aliasesToMakeVisible, anyImportSyntax)) {
|
||||
aliasesToMakeVisible.push(anyImportSyntax);
|
||||
}
|
||||
}
|
||||
else {
|
||||
aliasesToMakeVisible = [anyImportSyntax];
|
||||
}
|
||||
}
|
||||
else {
|
||||
aliasesToMakeVisible = [anyImportSyntax];
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -1888,7 +1901,7 @@ namespace ts {
|
||||
const symbol = resolveName(enclosingDeclaration, (<Identifier>firstIdentifier).text, meaning, /*nodeNotFoundErrorMessage*/ undefined, /*nameArg*/ undefined);
|
||||
|
||||
// Verify if the symbol is accessible
|
||||
return (symbol && hasVisibleDeclarations(symbol)) || <SymbolVisibilityResult>{
|
||||
return (symbol && hasVisibleDeclarations(symbol, /*shouldComputeAliasToMakeVisible*/ true)) || <SymbolVisibilityResult>{
|
||||
accessibility: SymbolAccessibility.NotAccessible,
|
||||
errorSymbolName: getTextOfNode(firstIdentifier),
|
||||
errorNode: firstIdentifier
|
||||
@@ -2163,7 +2176,9 @@ namespace ts {
|
||||
// The specified symbol flags need to be reinterpreted as type flags
|
||||
buildSymbolDisplay(type.symbol, writer, enclosingDeclaration, SymbolFlags.Type, SymbolFormatFlags.None, nextFlags);
|
||||
}
|
||||
else if (!(flags & TypeFormatFlags.InTypeAlias) && type.flags & (TypeFlags.Anonymous | TypeFlags.UnionOrIntersection) && type.aliasSymbol) {
|
||||
else if (!(flags & TypeFormatFlags.InTypeAlias) && type.flags & (TypeFlags.Anonymous | TypeFlags.UnionOrIntersection) && type.aliasSymbol &&
|
||||
isSymbolAccessible(type.aliasSymbol, enclosingDeclaration, SymbolFlags.Type, /*shouldComputeAliasesToMakeVisible*/ false).accessibility === SymbolAccessibility.Accessible) {
|
||||
// Only write out inferred type with its corresponding type-alias if type-alias is visible
|
||||
const typeArguments = type.aliasTypeArguments;
|
||||
writeSymbolTypeReference(type.aliasSymbol, typeArguments, 0, typeArguments ? typeArguments.length : 0, nextFlags);
|
||||
}
|
||||
@@ -5653,12 +5668,13 @@ namespace ts {
|
||||
case SyntaxKind.JSDocThisType:
|
||||
case SyntaxKind.JSDocOptionalType:
|
||||
return getTypeFromTypeNode((<ParenthesizedTypeNode | JSDocTypeReferencingNode>node).type);
|
||||
case SyntaxKind.JSDocRecordType:
|
||||
return getTypeFromTypeNode((node as JSDocRecordType).literal);
|
||||
case SyntaxKind.FunctionType:
|
||||
case SyntaxKind.ConstructorType:
|
||||
case SyntaxKind.TypeLiteral:
|
||||
case SyntaxKind.JSDocTypeLiteral:
|
||||
case SyntaxKind.JSDocFunctionType:
|
||||
case SyntaxKind.JSDocRecordType:
|
||||
return getTypeFromTypeLiteralOrFunctionOrConstructorTypeNode(node, aliasSymbol, aliasTypeArguments);
|
||||
// This function assumes that an identifier or qualified name is a type expression
|
||||
// Callers should first ensure this by calling isTypeNode
|
||||
|
||||
@@ -306,7 +306,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
function trackSymbol(symbol: Symbol, enclosingDeclaration?: Node, meaning?: SymbolFlags) {
|
||||
handleSymbolAccessibilityError(resolver.isSymbolAccessible(symbol, enclosingDeclaration, meaning));
|
||||
handleSymbolAccessibilityError(resolver.isSymbolAccessible(symbol, enclosingDeclaration, meaning, /*shouldComputeAliasesToMakeVisible*/ true));
|
||||
recordTypeReferenceDirectivesIfNecessary(resolver.getTypeReferenceDirectivesForSymbol(symbol, meaning));
|
||||
}
|
||||
|
||||
|
||||
+272
-142
@@ -379,7 +379,7 @@ namespace ts {
|
||||
case SyntaxKind.JSDocNullableType:
|
||||
return visitNode(cbNode, (<JSDocNullableType>node).type);
|
||||
case SyntaxKind.JSDocRecordType:
|
||||
return visitNodes(cbNodes, (<JSDocRecordType>node).members);
|
||||
return visitNode(cbNode, (<JSDocRecordType>node).literal);
|
||||
case SyntaxKind.JSDocTypeReference:
|
||||
return visitNode(cbNode, (<JSDocTypeReference>node).name) ||
|
||||
visitNodes(cbNodes, (<JSDocTypeReference>node).typeArguments);
|
||||
@@ -398,7 +398,7 @@ namespace ts {
|
||||
return visitNode(cbNode, (<JSDocRecordMember>node).name) ||
|
||||
visitNode(cbNode, (<JSDocRecordMember>node).type);
|
||||
case SyntaxKind.JSDocComment:
|
||||
return visitNodes(cbNodes, (<JSDocComment>node).tags);
|
||||
return visitNodes(cbNodes, (<JSDoc>node).tags);
|
||||
case SyntaxKind.JSDocParameterTag:
|
||||
return visitNode(cbNode, (<JSDocParameterTag>node).preParameterName) ||
|
||||
visitNode(cbNode, (<JSDocParameterTag>node).typeExpression) ||
|
||||
@@ -453,10 +453,10 @@ namespace ts {
|
||||
/* @internal */
|
||||
export function parseIsolatedJSDocComment(content: string, start?: number, length?: number) {
|
||||
const result = Parser.JSDocParser.parseIsolatedJSDocComment(content, start, length);
|
||||
if (result && result.jsDocComment) {
|
||||
if (result && result.jsDoc) {
|
||||
// because the jsDocComment was parsed out of the source file, it might
|
||||
// not be covered by the fixupParentReferences.
|
||||
Parser.fixupParentReferences(result.jsDocComment);
|
||||
Parser.fixupParentReferences(result.jsDoc);
|
||||
}
|
||||
|
||||
return result;
|
||||
@@ -655,20 +655,18 @@ namespace ts {
|
||||
|
||||
|
||||
function addJSDocComment<T extends Node>(node: T): T {
|
||||
if (contextFlags & NodeFlags.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) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!node.jsDocComments) {
|
||||
node.jsDocComments = [];
|
||||
}
|
||||
node.jsDocComments.push(jsDocComment);
|
||||
const comments = getJsDocCommentsFromText(node, sourceFile.text);
|
||||
if (comments) {
|
||||
for (const comment of comments) {
|
||||
const jsDoc = JSDocParser.parseJSDocComment(node, comment.pos, comment.end - comment.pos);
|
||||
if (!jsDoc) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!node.jsDocComments) {
|
||||
node.jsDocComments = [];
|
||||
}
|
||||
node.jsDocComments.push(jsDoc);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2204,7 +2202,7 @@ namespace ts {
|
||||
}
|
||||
fillSignature(SyntaxKind.ColonToken, /*yieldContext*/ false, /*awaitContext*/ false, /*requireCompleteParameterList*/ false, node);
|
||||
parseTypeMemberSemicolon();
|
||||
return finishNode(node);
|
||||
return addJSDocComment(finishNode(node));
|
||||
}
|
||||
|
||||
function isIndexSignature(): boolean {
|
||||
@@ -2294,7 +2292,7 @@ namespace ts {
|
||||
// [Yield] nor [Await]
|
||||
fillSignature(SyntaxKind.ColonToken, /*yieldContext*/ false, /*awaitContext*/ false, /*requireCompleteParameterList*/ false, method);
|
||||
parseTypeMemberSemicolon();
|
||||
return finishNode(method);
|
||||
return addJSDocComment(finishNode(method));
|
||||
}
|
||||
else {
|
||||
const property = <PropertySignature>createNode(SyntaxKind.PropertySignature, fullStart);
|
||||
@@ -2311,7 +2309,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
parseTypeMemberSemicolon();
|
||||
return finishNode(property);
|
||||
return addJSDocComment(finishNode(property));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2898,7 +2896,7 @@ namespace ts {
|
||||
node.equalsGreaterThanToken = parseExpectedToken(SyntaxKind.EqualsGreaterThanToken, /*reportAtCurrentPosition*/ false, Diagnostics._0_expected, "=>");
|
||||
node.body = parseArrowFunctionExpressionBody(/*isAsync*/ !!asyncModifier);
|
||||
|
||||
return finishNode(node);
|
||||
return addJSDocComment(finishNode(node));
|
||||
}
|
||||
|
||||
function tryParseParenthesizedArrowFunctionExpression(): Expression {
|
||||
@@ -2931,7 +2929,7 @@ namespace ts {
|
||||
? parseArrowFunctionExpressionBody(isAsync)
|
||||
: parseIdentifier();
|
||||
|
||||
return finishNode(arrowFunction);
|
||||
return addJSDocComment(finishNode(arrowFunction));
|
||||
}
|
||||
|
||||
// True -> We definitely expect a parenthesized arrow function here.
|
||||
@@ -4114,7 +4112,7 @@ namespace ts {
|
||||
|
||||
function tryParseAccessorDeclaration(fullStart: number, decorators: NodeArray<Decorator>, modifiers: NodeArray<Modifier>): AccessorDeclaration {
|
||||
if (parseContextualModifier(SyntaxKind.GetKeyword)) {
|
||||
return addJSDocComment(parseAccessorDeclaration(SyntaxKind.GetAccessor, fullStart, decorators, modifiers));
|
||||
return parseAccessorDeclaration(SyntaxKind.GetAccessor, fullStart, decorators, modifiers);
|
||||
}
|
||||
else if (parseContextualModifier(SyntaxKind.SetKeyword)) {
|
||||
return parseAccessorDeclaration(SyntaxKind.SetAccessor, fullStart, decorators, modifiers);
|
||||
@@ -4997,7 +4995,7 @@ namespace ts {
|
||||
: doOutsideOfContext(NodeFlags.YieldContext | NodeFlags.DisallowInContext, parseNonParameterInitializer);
|
||||
|
||||
parseSemicolon();
|
||||
return finishNode(property);
|
||||
return addJSDocComment(finishNode(property));
|
||||
}
|
||||
|
||||
function parsePropertyOrMethodDeclaration(fullStart: number, decorators: NodeArray<Decorator>, modifiers: NodeArray<Modifier>): ClassElement {
|
||||
@@ -5026,7 +5024,7 @@ namespace ts {
|
||||
node.name = parsePropertyName();
|
||||
fillSignature(SyntaxKind.ColonToken, /*yieldContext*/ false, /*awaitContext*/ false, /*requireCompleteParameterList*/ false, node);
|
||||
node.body = parseFunctionBlockOrSemicolon(/*isGenerator*/ false, /*isAsync*/ false);
|
||||
return finishNode(node);
|
||||
return addJSDocComment(finishNode(node));
|
||||
}
|
||||
|
||||
function isClassMemberModifier(idToken: SyntaxKind) {
|
||||
@@ -5264,7 +5262,7 @@ namespace ts {
|
||||
node.members = createMissingList<ClassElement>();
|
||||
}
|
||||
|
||||
return finishNode(node);
|
||||
return addJSDocComment(finishNode(node));
|
||||
}
|
||||
|
||||
function parseNameOfClassDeclarationOrExpression(): Identifier {
|
||||
@@ -5332,7 +5330,7 @@ namespace ts {
|
||||
node.typeParameters = parseTypeParameters();
|
||||
node.heritageClauses = parseHeritageClauses(/*isClassHeritageClause*/ false);
|
||||
node.members = parseObjectTypeMembers();
|
||||
return finishNode(node);
|
||||
return addJSDocComment(finishNode(node));
|
||||
}
|
||||
|
||||
function parseTypeAliasDeclaration(fullStart: number, decorators: NodeArray<Decorator>, modifiers: NodeArray<Modifier>): TypeAliasDeclaration {
|
||||
@@ -5356,7 +5354,7 @@ namespace ts {
|
||||
const node = <EnumMember>createNode(SyntaxKind.EnumMember, scanner.getStartPos());
|
||||
node.name = parsePropertyName();
|
||||
node.initializer = allowInAnd(parseNonParameterInitializer);
|
||||
return finishNode(node);
|
||||
return addJSDocComment(finishNode(node));
|
||||
}
|
||||
|
||||
function parseEnumDeclaration(fullStart: number, decorators: NodeArray<Decorator>, modifiers: NodeArray<Modifier>): EnumDeclaration {
|
||||
@@ -5372,7 +5370,7 @@ namespace ts {
|
||||
else {
|
||||
node.members = createMissingList<EnumMember>();
|
||||
}
|
||||
return finishNode(node);
|
||||
return addJSDocComment(finishNode(node));
|
||||
}
|
||||
|
||||
function parseModuleBlock(): ModuleBlock {
|
||||
@@ -5399,7 +5397,7 @@ namespace ts {
|
||||
node.body = parseOptional(SyntaxKind.DotToken)
|
||||
? parseModuleOrNamespaceDeclaration(getNodePos(), /*decorators*/ undefined, /*modifiers*/ undefined, NodeFlags.NestedNamespace | namespaceFlag)
|
||||
: parseModuleBlock();
|
||||
return finishNode(node);
|
||||
return addJSDocComment(finishNode(node));
|
||||
}
|
||||
|
||||
function parseAmbientExternalModuleDeclaration(fullStart: number, decorators: NodeArray<Decorator>, modifiers: NodeArray<Modifier>): ModuleDeclaration {
|
||||
@@ -5488,7 +5486,7 @@ namespace ts {
|
||||
parseExpected(SyntaxKind.EqualsToken);
|
||||
importEqualsDeclaration.moduleReference = parseModuleReference();
|
||||
parseSemicolon();
|
||||
return finishNode(importEqualsDeclaration);
|
||||
return addJSDocComment(finishNode(importEqualsDeclaration));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5809,6 +5807,7 @@ namespace ts {
|
||||
|
||||
export function parseJSDocTypeExpressionForTests(content: string, start: number, length: number) {
|
||||
initializeState("file.js", content, ScriptTarget.Latest, /*_syntaxCursor:*/ undefined, ScriptKind.JS);
|
||||
sourceFile = createSourceFile("file.js", ScriptTarget.Latest, ScriptKind.JS);
|
||||
scanner.setText(content, start, length);
|
||||
currentToken = scanner.scan();
|
||||
const jsDocTypeExpression = parseJSDocTypeExpression();
|
||||
@@ -6027,22 +6026,7 @@ namespace ts {
|
||||
|
||||
function parseJSDocRecordType(): JSDocRecordType {
|
||||
const result = <JSDocRecordType>createNode(SyntaxKind.JSDocRecordType);
|
||||
nextToken();
|
||||
result.members = parseDelimitedList(ParsingContext.JSDocRecordMembers, parseJSDocRecordMember);
|
||||
checkForTrailingComma(result.members);
|
||||
parseExpected(SyntaxKind.CloseBraceToken);
|
||||
return finishNode(result);
|
||||
}
|
||||
|
||||
function parseJSDocRecordMember(): JSDocRecordMember {
|
||||
const result = <JSDocRecordMember>createNode(SyntaxKind.JSDocRecordMember);
|
||||
result.name = parseSimplePropertyName();
|
||||
|
||||
if (token() === SyntaxKind.ColonToken) {
|
||||
nextToken();
|
||||
result.type = parseJSDocType();
|
||||
}
|
||||
|
||||
result.literal = parseTypeLiteral();
|
||||
return finishNode(result);
|
||||
}
|
||||
|
||||
@@ -6140,14 +6124,14 @@ namespace ts {
|
||||
export function parseIsolatedJSDocComment(content: string, start: number, length: number) {
|
||||
initializeState("file.js", content, ScriptTarget.Latest, /*_syntaxCursor:*/ undefined, ScriptKind.JS);
|
||||
sourceFile = <SourceFile>{ languageVariant: LanguageVariant.Standard, text: content };
|
||||
const jsDocComment = parseJSDocCommentWorker(start, length);
|
||||
const jsDoc = parseJSDocCommentWorker(start, length);
|
||||
const diagnostics = parseDiagnostics;
|
||||
clearState();
|
||||
|
||||
return jsDocComment ? { jsDocComment, diagnostics } : undefined;
|
||||
return jsDoc ? { jsDoc, diagnostics } : undefined;
|
||||
}
|
||||
|
||||
export function parseJSDocComment(parent: Node, start: number, length: number): JSDocComment {
|
||||
export function parseJSDocComment(parent: Node, start: number, length: number): JSDoc {
|
||||
const saveToken = currentToken;
|
||||
const saveParseDiagnosticsLength = parseDiagnostics.length;
|
||||
const saveParseErrorBeforeNextFinishedNode = parseErrorBeforeNextFinishedNode;
|
||||
@@ -6164,7 +6148,13 @@ namespace ts {
|
||||
return comment;
|
||||
}
|
||||
|
||||
export function parseJSDocCommentWorker(start: number, length: number): JSDocComment {
|
||||
const enum JSDocState {
|
||||
BeginningOfLine,
|
||||
SawAsterisk,
|
||||
SavingComments,
|
||||
}
|
||||
|
||||
export function parseJSDocCommentWorker(start: number, length: number): JSDoc {
|
||||
const content = sourceText;
|
||||
start = start || 0;
|
||||
const end = length === undefined ? content.length : start + length;
|
||||
@@ -6175,76 +6165,134 @@ namespace ts {
|
||||
Debug.assert(end <= content.length);
|
||||
|
||||
let tags: NodeArray<JSDocTag>;
|
||||
let result: JSDocComment;
|
||||
const comments: string[] = [];
|
||||
let result: JSDoc;
|
||||
|
||||
// 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) {
|
||||
if (!isJsDocStart(content, start)) {
|
||||
return result;
|
||||
}
|
||||
|
||||
// + 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 advanceToken = true;
|
||||
let state = JSDocState.SawAsterisk;
|
||||
let margin: number | undefined = undefined;
|
||||
// + 4 for leading '/** '
|
||||
let indent = start - Math.max(content.lastIndexOf("\n", start), 0) + 4;
|
||||
function pushComment(text: string) {
|
||||
if (!margin) {
|
||||
margin = indent;
|
||||
}
|
||||
comments.push(text);
|
||||
indent += text.length;
|
||||
}
|
||||
|
||||
// + 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;
|
||||
|
||||
nextJSDocToken();
|
||||
while (token() === SyntaxKind.WhitespaceTrivia) {
|
||||
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;
|
||||
|
||||
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;
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
if (token() === SyntaxKind.NewLineTrivia) {
|
||||
state = JSDocState.BeginningOfLine;
|
||||
nextJSDocToken();
|
||||
}
|
||||
while (token() !== SyntaxKind.EndOfFileToken) {
|
||||
switch (token()) {
|
||||
case SyntaxKind.AtToken:
|
||||
if (state === JSDocState.BeginningOfLine || state === JSDocState.SawAsterisk) {
|
||||
removeTrailingNewlines(comments);
|
||||
parseTag(indent);
|
||||
// NOTE: According to usejsdoc.org, a tag goes to end of line, except the last tag.
|
||||
// Real-world comments may break this rule, so "BeginningOfLine" will not be a real line beginning
|
||||
// for malformed examples like `/** @param {string} x @returns {number} the length */`
|
||||
state = JSDocState.BeginningOfLine;
|
||||
advanceToken = false;
|
||||
margin = undefined;
|
||||
indent++;
|
||||
}
|
||||
else {
|
||||
pushComment(scanner.getTokenText());
|
||||
}
|
||||
break;
|
||||
case SyntaxKind.NewLineTrivia:
|
||||
comments.push(scanner.getTokenText());
|
||||
state = JSDocState.BeginningOfLine;
|
||||
indent = 0;
|
||||
break;
|
||||
case SyntaxKind.AsteriskToken:
|
||||
const asterisk = scanner.getTokenText();
|
||||
if (state === JSDocState.SawAsterisk) {
|
||||
// If we've already seen an asterisk, then we can no longer parse a tag on this line
|
||||
state = JSDocState.SavingComments;
|
||||
pushComment(asterisk);
|
||||
}
|
||||
else {
|
||||
// Ignore the first asterisk on a line
|
||||
seenAsterisk = true;
|
||||
break;
|
||||
|
||||
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;
|
||||
break;
|
||||
|
||||
case SyntaxKind.EndOfFileToken:
|
||||
break;
|
||||
}
|
||||
|
||||
state = JSDocState.SawAsterisk;
|
||||
indent += asterisk.length;
|
||||
}
|
||||
break;
|
||||
case SyntaxKind.Identifier:
|
||||
// Anything else is doc comment text. We just save it. Because it
|
||||
// wasn't a tag, we can no longer parse a tag on this line until we hit the next
|
||||
// line break.
|
||||
pushComment(scanner.getTokenText());
|
||||
state = JSDocState.SavingComments;
|
||||
break;
|
||||
case SyntaxKind.WhitespaceTrivia:
|
||||
// only collect whitespace if we're already saving comments or have just crossed the comment indent margin
|
||||
const whitespace = scanner.getTokenText();
|
||||
if (state === JSDocState.SavingComments || margin !== undefined && indent + whitespace.length > margin) {
|
||||
comments.push(whitespace.slice(margin - indent - 1));
|
||||
}
|
||||
indent += whitespace.length;
|
||||
break;
|
||||
case SyntaxKind.EndOfFileToken:
|
||||
break;
|
||||
default:
|
||||
pushComment(scanner.getTokenText());
|
||||
break;
|
||||
}
|
||||
if (advanceToken) {
|
||||
nextJSDocToken();
|
||||
}
|
||||
else {
|
||||
advanceToken = true;
|
||||
}
|
||||
}
|
||||
removeLeadingNewlines(comments);
|
||||
removeTrailingNewlines(comments);
|
||||
result = createJSDocComment();
|
||||
|
||||
result = createJSDocComment();
|
||||
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
return result;
|
||||
|
||||
function createJSDocComment(): JSDocComment {
|
||||
if (!tags) {
|
||||
return undefined;
|
||||
function removeLeadingNewlines(comments: string[]) {
|
||||
while (comments.length && (comments[0] === "\n" || comments[0] === "\r")) {
|
||||
comments.shift();
|
||||
}
|
||||
}
|
||||
|
||||
const result = <JSDocComment>createNode(SyntaxKind.JSDocComment, start);
|
||||
function removeTrailingNewlines(comments: string[]) {
|
||||
while (comments.length && (comments[comments.length - 1] === "\n" || comments[comments.length - 1] === "\r")) {
|
||||
comments.pop();
|
||||
}
|
||||
}
|
||||
|
||||
function isJsDocStart(content: string, start: number) {
|
||||
return content.charCodeAt(start) === CharacterCodes.slash &&
|
||||
content.charCodeAt(start + 1) === CharacterCodes.asterisk &&
|
||||
content.charCodeAt(start + 2) === CharacterCodes.asterisk &&
|
||||
content.charCodeAt(start + 3) !== CharacterCodes.asterisk;
|
||||
}
|
||||
|
||||
function createJSDocComment(): JSDoc {
|
||||
const result = <JSDoc>createNode(SyntaxKind.JSDocComment, start);
|
||||
result.tags = tags;
|
||||
result.comment = comments.length ? comments.join("") : undefined;
|
||||
return finishNode(result, end);
|
||||
}
|
||||
|
||||
@@ -6254,78 +6302,154 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
function parseTag(): void {
|
||||
function parseTag(indent: number) {
|
||||
Debug.assert(token() === SyntaxKind.AtToken);
|
||||
const atToken = createNode(SyntaxKind.AtToken, scanner.getTokenPos());
|
||||
atToken.end = scanner.getTextPos();
|
||||
nextJSDocToken();
|
||||
|
||||
const tagName = parseJSDocIdentifierName();
|
||||
skipWhitespace();
|
||||
if (!tagName) {
|
||||
return;
|
||||
}
|
||||
|
||||
const tag = handleTag(atToken, tagName) || handleUnknownTag(atToken, tagName);
|
||||
addTag(tag);
|
||||
}
|
||||
|
||||
function handleTag(atToken: Node, tagName: Identifier): JSDocTag {
|
||||
let tag: JSDocTag;
|
||||
if (tagName) {
|
||||
switch (tagName.text) {
|
||||
case "param":
|
||||
return handleParamTag(atToken, tagName);
|
||||
tag = parseParamTag(atToken, tagName);
|
||||
break;
|
||||
case "return":
|
||||
case "returns":
|
||||
return handleReturnTag(atToken, tagName);
|
||||
tag = parseReturnTag(atToken, tagName);
|
||||
break;
|
||||
case "template":
|
||||
return handleTemplateTag(atToken, tagName);
|
||||
tag = parseTemplateTag(atToken, tagName);
|
||||
break;
|
||||
case "type":
|
||||
return handleTypeTag(atToken, tagName);
|
||||
tag = parseTypeTag(atToken, tagName);
|
||||
break;
|
||||
case "typedef":
|
||||
return handleTypedefTag(atToken, tagName);
|
||||
tag = parseTypedefTag(atToken, tagName);
|
||||
break;
|
||||
default:
|
||||
tag = parseUnknownTag(atToken, tagName);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
tag = parseUnknownTag(atToken, tagName);
|
||||
}
|
||||
|
||||
return undefined;
|
||||
if (!tag) {
|
||||
// a badly malformed tag should not be added to the list of tags
|
||||
return;
|
||||
}
|
||||
addTag(tag, parseTagComments(indent + tag.end - tag.pos));
|
||||
}
|
||||
|
||||
function handleUnknownTag(atToken: Node, tagName: Identifier) {
|
||||
function parseTagComments(indent: number) {
|
||||
const comments: string[] = [];
|
||||
let state = JSDocState.SawAsterisk;
|
||||
let margin: number | undefined;
|
||||
function pushComment(text: string) {
|
||||
if (!margin) {
|
||||
margin = indent;
|
||||
}
|
||||
comments.push(text);
|
||||
indent += text.length;
|
||||
}
|
||||
while (token() !== SyntaxKind.AtToken && token() !== SyntaxKind.EndOfFileToken) {
|
||||
switch (token()) {
|
||||
case SyntaxKind.NewLineTrivia:
|
||||
if (state >= JSDocState.SawAsterisk) {
|
||||
state = JSDocState.BeginningOfLine;
|
||||
comments.push(scanner.getTokenText());
|
||||
}
|
||||
indent = 0;
|
||||
break;
|
||||
case SyntaxKind.AtToken:
|
||||
// Done
|
||||
break;
|
||||
case SyntaxKind.WhitespaceTrivia:
|
||||
if (state === JSDocState.SavingComments) {
|
||||
pushComment(scanner.getTokenText());
|
||||
}
|
||||
else {
|
||||
const whitespace = scanner.getTokenText();
|
||||
// if the whitespace crosses the margin, take only the whitespace that passes the margin
|
||||
if (margin !== undefined && indent + whitespace.length > margin) {
|
||||
comments.push(whitespace.slice(margin - indent - 1));
|
||||
}
|
||||
indent += whitespace.length;
|
||||
}
|
||||
break;
|
||||
case SyntaxKind.AsteriskToken:
|
||||
if (state === JSDocState.BeginningOfLine) {
|
||||
// leading asterisks start recording on the *next* (non-whitespace) token
|
||||
state = JSDocState.SawAsterisk;
|
||||
indent += scanner.getTokenText().length;
|
||||
break;
|
||||
}
|
||||
// FALLTHROUGH otherwise to record the * as a comment
|
||||
default:
|
||||
state = JSDocState.SavingComments; // leading identifiers start recording as well
|
||||
pushComment(scanner.getTokenText());
|
||||
break;
|
||||
}
|
||||
if (token() === SyntaxKind.AtToken) {
|
||||
// Done
|
||||
break;
|
||||
}
|
||||
nextJSDocToken();
|
||||
}
|
||||
|
||||
removeLeadingNewlines(comments);
|
||||
removeTrailingNewlines(comments);
|
||||
return comments;
|
||||
}
|
||||
|
||||
function parseUnknownTag(atToken: Node, tagName: Identifier) {
|
||||
const result = <JSDocTag>createNode(SyntaxKind.JSDocTag, atToken.pos);
|
||||
result.atToken = atToken;
|
||||
result.tagName = tagName;
|
||||
return finishNode(result);
|
||||
}
|
||||
|
||||
function addTag(tag: JSDocTag): void {
|
||||
if (tag) {
|
||||
if (!tags) {
|
||||
tags = createNodeArray([tag], tag.pos);
|
||||
}
|
||||
else {
|
||||
tags.push(tag);
|
||||
}
|
||||
tags.end = tag.end;
|
||||
function addTag(tag: JSDocTag, comments: string[]): void {
|
||||
tag.comment = comments.join("");
|
||||
|
||||
if (!tags) {
|
||||
tags = createNodeArray([tag], tag.pos);
|
||||
}
|
||||
else {
|
||||
tags.push(tag);
|
||||
}
|
||||
tags.end = tag.end;
|
||||
}
|
||||
|
||||
function tryParseTypeExpression(): JSDocTypeExpression {
|
||||
if (token() !== SyntaxKind.OpenBraceToken) {
|
||||
return undefined;
|
||||
}
|
||||
return tryParse(() => {
|
||||
skipWhitespace();
|
||||
if (token() !== SyntaxKind.OpenBraceToken) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const typeExpression = parseJSDocTypeExpression();
|
||||
return typeExpression;
|
||||
return parseJSDocTypeExpression();
|
||||
});
|
||||
}
|
||||
|
||||
function handleParamTag(atToken: Node, tagName: Identifier) {
|
||||
function parseParamTag(atToken: Node, tagName: Identifier) {
|
||||
let typeExpression = tryParseTypeExpression();
|
||||
|
||||
skipWhitespace();
|
||||
|
||||
let name: Identifier;
|
||||
let isBracketed: boolean;
|
||||
// Looking for something like '[foo]' or 'foo'
|
||||
if (parseOptionalToken(SyntaxKind.OpenBracketToken)) {
|
||||
name = parseJSDocIdentifierName();
|
||||
skipWhitespace();
|
||||
isBracketed = true;
|
||||
|
||||
// May have an optional default, e.g. '[foo = 42]'
|
||||
@@ -6362,11 +6486,12 @@ namespace ts {
|
||||
result.preParameterName = preName;
|
||||
result.typeExpression = typeExpression;
|
||||
result.postParameterName = postName;
|
||||
result.parameterName = postName || preName;
|
||||
result.isBracketed = isBracketed;
|
||||
return finishNode(result);
|
||||
}
|
||||
|
||||
function handleReturnTag(atToken: Node, tagName: Identifier): JSDocReturnTag {
|
||||
function parseReturnTag(atToken: Node, tagName: Identifier): JSDocReturnTag {
|
||||
if (forEach(tags, t => t.kind === SyntaxKind.JSDocReturnTag)) {
|
||||
parseErrorAtPosition(tagName.pos, scanner.getTokenPos() - tagName.pos, Diagnostics._0_tag_already_specified, tagName.text);
|
||||
}
|
||||
@@ -6378,7 +6503,7 @@ namespace ts {
|
||||
return finishNode(result);
|
||||
}
|
||||
|
||||
function handleTypeTag(atToken: Node, tagName: Identifier): JSDocTypeTag {
|
||||
function parseTypeTag(atToken: Node, tagName: Identifier): JSDocTypeTag {
|
||||
if (forEach(tags, t => t.kind === SyntaxKind.JSDocTypeTag)) {
|
||||
parseErrorAtPosition(tagName.pos, scanner.getTokenPos() - tagName.pos, Diagnostics._0_tag_already_specified, tagName.text);
|
||||
}
|
||||
@@ -6390,10 +6515,11 @@ namespace ts {
|
||||
return finishNode(result);
|
||||
}
|
||||
|
||||
function handlePropertyTag(atToken: Node, tagName: Identifier): JSDocPropertyTag {
|
||||
function parsePropertyTag(atToken: Node, tagName: Identifier): JSDocPropertyTag {
|
||||
const typeExpression = tryParseTypeExpression();
|
||||
skipWhitespace();
|
||||
const name = parseJSDocIdentifierName();
|
||||
skipWhitespace();
|
||||
if (!name) {
|
||||
parseErrorAtPosition(scanner.getStartPos(), /*length*/ 0, Diagnostics.Identifier_expected);
|
||||
return undefined;
|
||||
@@ -6407,7 +6533,7 @@ namespace ts {
|
||||
return finishNode(result);
|
||||
}
|
||||
|
||||
function handleTypedefTag(atToken: Node, tagName: Identifier): JSDocTypedefTag {
|
||||
function parseTypedefTag(atToken: Node, tagName: Identifier): JSDocTypedefTag {
|
||||
const typeExpression = tryParseTypeExpression();
|
||||
skipWhitespace();
|
||||
|
||||
@@ -6416,6 +6542,7 @@ namespace ts {
|
||||
typedefTag.tagName = tagName;
|
||||
typedefTag.name = parseJSDocIdentifierName();
|
||||
typedefTag.typeExpression = typeExpression;
|
||||
skipWhitespace();
|
||||
|
||||
if (typeExpression) {
|
||||
if (typeExpression.type.kind === SyntaxKind.JSDocTypeReference) {
|
||||
@@ -6485,6 +6612,7 @@ namespace ts {
|
||||
nextJSDocToken();
|
||||
|
||||
const tagName = parseJSDocIdentifierName();
|
||||
skipWhitespace();
|
||||
if (!tagName) {
|
||||
return false;
|
||||
}
|
||||
@@ -6495,21 +6623,21 @@ namespace ts {
|
||||
// already has a @type tag, terminate the parent tag now.
|
||||
return false;
|
||||
}
|
||||
parentTag.jsDocTypeTag = handleTypeTag(atToken, tagName);
|
||||
parentTag.jsDocTypeTag = parseTypeTag(atToken, tagName);
|
||||
return true;
|
||||
case "prop":
|
||||
case "property":
|
||||
if (!parentTag.jsDocPropertyTags) {
|
||||
parentTag.jsDocPropertyTags = <NodeArray<JSDocPropertyTag>>[];
|
||||
}
|
||||
const propertyTag = handlePropertyTag(atToken, tagName);
|
||||
const propertyTag = parsePropertyTag(atToken, tagName);
|
||||
parentTag.jsDocPropertyTags.push(propertyTag);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function handleTemplateTag(atToken: Node, tagName: Identifier): JSDocTemplateTag {
|
||||
function parseTemplateTag(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);
|
||||
}
|
||||
@@ -6519,6 +6647,7 @@ namespace ts {
|
||||
|
||||
while (true) {
|
||||
const name = parseJSDocIdentifierName();
|
||||
skipWhitespace();
|
||||
if (!name) {
|
||||
parseErrorAtPosition(scanner.getStartPos(), 0, Diagnostics.Identifier_expected);
|
||||
return undefined;
|
||||
@@ -6532,6 +6661,7 @@ namespace ts {
|
||||
|
||||
if (token() === SyntaxKind.CommaToken) {
|
||||
nextJSDocToken();
|
||||
skipWhitespace();
|
||||
}
|
||||
else {
|
||||
break;
|
||||
|
||||
+27
-21
@@ -1759,40 +1759,46 @@ namespace ts {
|
||||
}
|
||||
|
||||
startPos = pos;
|
||||
|
||||
// Eat leading whitespace
|
||||
let ch = text.charCodeAt(pos);
|
||||
while (pos < end) {
|
||||
ch = text.charCodeAt(pos);
|
||||
if (isWhiteSpaceSingleLine(ch)) {
|
||||
pos++;
|
||||
}
|
||||
else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
tokenPos = pos;
|
||||
|
||||
const ch = text.charCodeAt(pos);
|
||||
switch (ch) {
|
||||
case CharacterCodes.tab:
|
||||
case CharacterCodes.verticalTab:
|
||||
case CharacterCodes.formFeed:
|
||||
case CharacterCodes.space:
|
||||
while (pos < end && isWhiteSpaceSingleLine(text.charCodeAt(pos))) {
|
||||
pos++;
|
||||
}
|
||||
return token = SyntaxKind.WhitespaceTrivia;
|
||||
case CharacterCodes.at:
|
||||
return pos += 1, token = SyntaxKind.AtToken;
|
||||
pos++;
|
||||
return token = SyntaxKind.AtToken;
|
||||
case CharacterCodes.lineFeed:
|
||||
case CharacterCodes.carriageReturn:
|
||||
return pos += 1, token = SyntaxKind.NewLineTrivia;
|
||||
pos++;
|
||||
return token = SyntaxKind.NewLineTrivia;
|
||||
case CharacterCodes.asterisk:
|
||||
return pos += 1, token = SyntaxKind.AsteriskToken;
|
||||
pos++;
|
||||
return token = SyntaxKind.AsteriskToken;
|
||||
case CharacterCodes.openBrace:
|
||||
return pos += 1, token = SyntaxKind.OpenBraceToken;
|
||||
pos++;
|
||||
return token = SyntaxKind.OpenBraceToken;
|
||||
case CharacterCodes.closeBrace:
|
||||
return pos += 1, token = SyntaxKind.CloseBraceToken;
|
||||
pos++;
|
||||
return token = SyntaxKind.CloseBraceToken;
|
||||
case CharacterCodes.openBracket:
|
||||
return pos += 1, token = SyntaxKind.OpenBracketToken;
|
||||
pos++;
|
||||
return token = SyntaxKind.OpenBracketToken;
|
||||
case CharacterCodes.closeBracket:
|
||||
return pos += 1, token = SyntaxKind.CloseBracketToken;
|
||||
pos++;
|
||||
return token = SyntaxKind.CloseBracketToken;
|
||||
case CharacterCodes.equals:
|
||||
return pos += 1, token = SyntaxKind.EqualsToken;
|
||||
pos++;
|
||||
return token = SyntaxKind.EqualsToken;
|
||||
case CharacterCodes.comma:
|
||||
return pos += 1, token = SyntaxKind.CommaToken;
|
||||
pos++;
|
||||
return token = SyntaxKind.CommaToken;
|
||||
}
|
||||
|
||||
if (isIdentifierStart(ch, ScriptTarget.Latest)) {
|
||||
|
||||
@@ -804,17 +804,17 @@ namespace ts {
|
||||
* Adds a trailing VariableStatement for an enum or module declaration.
|
||||
*/
|
||||
function addVarForExportedEnumOrNamespaceDeclaration(statements: Statement[], node: EnumDeclaration | ModuleDeclaration) {
|
||||
statements.push(
|
||||
createVariableStatement(
|
||||
/*modifiers*/ undefined,
|
||||
[createVariableDeclaration(
|
||||
getDeclarationName(node),
|
||||
const transformedStatement = createVariableStatement(
|
||||
/*modifiers*/ undefined,
|
||||
[createVariableDeclaration(
|
||||
getDeclarationName(node),
|
||||
/*type*/ undefined,
|
||||
createPropertyAccess(createIdentifier("exports"), getDeclarationName(node))
|
||||
)],
|
||||
createPropertyAccess(createIdentifier("exports"), getDeclarationName(node))
|
||||
)],
|
||||
/*location*/ node
|
||||
)
|
||||
);
|
||||
setNodeEmitFlags(transformedStatement, NodeEmitFlags.NoComments);
|
||||
statements.push(transformedStatement);
|
||||
}
|
||||
|
||||
function getDeclarationName(node: DeclarationStatement) {
|
||||
|
||||
@@ -694,19 +694,21 @@ namespace ts {
|
||||
|
||||
// let ${name} = ${classExpression} where name is either declaredName if the class doesn't contain self-reference
|
||||
// or decoratedClassAlias if the class contain self-reference.
|
||||
const transformedClassExpression = createVariableStatement(
|
||||
/*modifiers*/ undefined,
|
||||
createLetDeclarationList([
|
||||
createVariableDeclaration(
|
||||
classAlias || declaredName,
|
||||
/*type*/ undefined,
|
||||
classExpression
|
||||
)
|
||||
]),
|
||||
/*location*/ location
|
||||
);
|
||||
setCommentRange(transformedClassExpression, node);
|
||||
statements.push(
|
||||
setOriginalNode(
|
||||
createVariableStatement(
|
||||
/*modifiers*/ undefined,
|
||||
createLetDeclarationList([
|
||||
createVariableDeclaration(
|
||||
classAlias || declaredName,
|
||||
/*type*/ undefined,
|
||||
classExpression
|
||||
)
|
||||
]),
|
||||
/*location*/ location
|
||||
),
|
||||
/*node*/ transformedClassExpression,
|
||||
/*original*/ node
|
||||
)
|
||||
);
|
||||
@@ -2859,7 +2861,6 @@ namespace ts {
|
||||
const moduleBlock = <ModuleBlock>getInnerMostModuleDeclarationFromDottedModule(node).body;
|
||||
statementsLocation = moveRangePos(moduleBlock.statements, -1);
|
||||
}
|
||||
|
||||
addRange(statements, endLexicalEnvironment());
|
||||
|
||||
currentNamespaceContainerName = savedCurrentNamespaceContainerName;
|
||||
@@ -2872,6 +2873,30 @@ namespace ts {
|
||||
/*location*/ blockLocation,
|
||||
/*multiLine*/ true
|
||||
);
|
||||
|
||||
// namespace hello.hi.world {
|
||||
// function foo() {}
|
||||
//
|
||||
// // TODO, blah
|
||||
// }
|
||||
//
|
||||
// should be emitted as
|
||||
//
|
||||
// var hello;
|
||||
// (function (hello) {
|
||||
// var hi;
|
||||
// (function (hi) {
|
||||
// var world;
|
||||
// (function (world) {
|
||||
// function foo() { }
|
||||
// // TODO, blah
|
||||
// })(world = hi.world || (hi.world = {}));
|
||||
// })(hi = hello.hi || (hello.hi = {}));
|
||||
// })(hello || (hello = {}));
|
||||
// We only want to emit comment on the namespace which contains block body itself, not the containing namespaces.
|
||||
if (body.kind !== SyntaxKind.ModuleBlock) {
|
||||
setNodeEmitFlags(block, block.emitFlags | NodeEmitFlags.NoComments);
|
||||
}
|
||||
return block;
|
||||
}
|
||||
|
||||
|
||||
+11
-5
@@ -487,7 +487,7 @@ namespace ts {
|
||||
parent?: Node; // Parent node (initialized by binding)
|
||||
/* @internal */ original?: Node; // The original node if this is an updated node.
|
||||
/* @internal */ startsOnNewLine?: boolean; // Whether a synthesized node should start on a new line (used by transforms).
|
||||
/* @internal */ jsDocComments?: JSDocComment[]; // JSDoc for the node, if it has any. Only for .js files.
|
||||
/* @internal */ jsDocComments?: JSDoc[]; // JSDoc for the node, if it has any.
|
||||
/* @internal */ symbol?: Symbol; // Symbol declared by node (initialized by binding)
|
||||
/* @internal */ locals?: SymbolTable; // Locals associated with node (initialized by binding)
|
||||
/* @internal */ nextContainer?: Node; // Next container in declaration order (initialized by binding)
|
||||
@@ -1555,7 +1555,7 @@ namespace ts {
|
||||
|
||||
// @kind(SyntaxKind.JSDocRecordType)
|
||||
export interface JSDocRecordType extends JSDocType, TypeLiteralNode {
|
||||
members: NodeArray<JSDocRecordMember>;
|
||||
literal: TypeLiteralNode;
|
||||
}
|
||||
|
||||
// @kind(SyntaxKind.JSDocTypeReference)
|
||||
@@ -1603,14 +1603,16 @@ namespace ts {
|
||||
}
|
||||
|
||||
// @kind(SyntaxKind.JSDocComment)
|
||||
export interface JSDocComment extends Node {
|
||||
tags: NodeArray<JSDocTag>;
|
||||
export interface JSDoc extends Node {
|
||||
tags: NodeArray<JSDocTag> | undefined;
|
||||
comment: string | undefined;
|
||||
}
|
||||
|
||||
// @kind(SyntaxKind.JSDocTag)
|
||||
export interface JSDocTag extends Node {
|
||||
atToken: Node;
|
||||
tagName: Identifier;
|
||||
comment: string | undefined;
|
||||
}
|
||||
|
||||
// @kind(SyntaxKind.JSDocTemplateTag)
|
||||
@@ -1649,9 +1651,13 @@ namespace ts {
|
||||
|
||||
// @kind(SyntaxKind.JSDocParameterTag)
|
||||
export interface JSDocParameterTag extends JSDocTag {
|
||||
/** the parameter name, if provided *before* the type (TypeScript-style) */
|
||||
preParameterName?: Identifier;
|
||||
typeExpression?: JSDocTypeExpression;
|
||||
/** the parameter name, if provided *after* the type (JSDoc-standard) */
|
||||
postParameterName?: Identifier;
|
||||
/** the parameter name, regardless of the location it was provided */
|
||||
parameterName: Identifier;
|
||||
isBracketed: boolean;
|
||||
}
|
||||
|
||||
@@ -2138,7 +2144,7 @@ namespace ts {
|
||||
writeReturnTypeOfSignatureDeclaration(signatureDeclaration: SignatureDeclaration, enclosingDeclaration: Node, flags: TypeFormatFlags, writer: SymbolWriter): void;
|
||||
writeTypeOfExpression(expr: Expression, enclosingDeclaration: Node, flags: TypeFormatFlags, writer: SymbolWriter): void;
|
||||
writeBaseConstructorTypeOfClass(node: ClassLikeDeclaration, enclosingDeclaration: Node, flags: TypeFormatFlags, writer: SymbolWriter): void;
|
||||
isSymbolAccessible(symbol: Symbol, enclosingDeclaration: Node, meaning: SymbolFlags): SymbolAccessibilityResult;
|
||||
isSymbolAccessible(symbol: Symbol, enclosingDeclaration: Node, meaning: SymbolFlags, shouldComputeAliasToMarkVisible: boolean): SymbolAccessibilityResult;
|
||||
isEntityNameVisible(entityName: EntityNameOrEntityNameExpression, enclosingDeclaration: Node): SymbolVisibilityResult;
|
||||
// Returns the constant value this property access resolves to, or 'undefined' for a non-constant
|
||||
getConstantValue(node: EnumMember | PropertyAccessExpression | ElementAccessExpression): number;
|
||||
|
||||
+117
-37
@@ -1426,39 +1426,75 @@ namespace ts {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const jsDocComments = getJSDocComments(node, checkParentVariableStatement);
|
||||
if (!jsDocComments) {
|
||||
const jsDocTags = getJSDocTags(node, checkParentVariableStatement);
|
||||
if (!jsDocTags) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
for (const jsDocComment of jsDocComments) {
|
||||
for (const tag of jsDocComment.tags) {
|
||||
if (tag.kind === kind) {
|
||||
return tag;
|
||||
}
|
||||
for (const tag of jsDocTags) {
|
||||
if (tag.kind === kind) {
|
||||
return tag;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function getJSDocComments(node: Node, checkParentVariableStatement: boolean): JSDocComment[] {
|
||||
if (node.jsDocComments) {
|
||||
return node.jsDocComments;
|
||||
function append<T>(previous: T[] | undefined, additional: T[] | undefined): T[] | undefined {
|
||||
if (additional) {
|
||||
if (!previous) {
|
||||
previous = [];
|
||||
}
|
||||
for (const x of additional) {
|
||||
previous.push(x);
|
||||
}
|
||||
}
|
||||
// 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;
|
||||
return previous;
|
||||
}
|
||||
|
||||
const variableStatementNode = isInitializerOfVariableDeclarationInStatement ? node.parent.parent.parent : undefined;
|
||||
export function getJSDocComments(node: Node, checkParentVariableStatement: boolean): string[] {
|
||||
return getJSDocs(node, checkParentVariableStatement, docs => map(docs, doc => doc.comment), tags => map(tags, tag => tag.comment));
|
||||
}
|
||||
|
||||
function getJSDocTags(node: Node, checkParentVariableStatement: boolean): JSDocTag[] {
|
||||
return getJSDocs(node, checkParentVariableStatement, docs => {
|
||||
const result: JSDocTag[] = [];
|
||||
for (const doc of docs) {
|
||||
if (doc.tags) {
|
||||
result.push(...doc.tags);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}, tags => tags);
|
||||
}
|
||||
|
||||
function getJSDocs<T>(node: Node, checkParentVariableStatement: boolean, getDocs: (docs: JSDoc[]) => T[], getTags: (tags: JSDocTag[]) => T[]): T[] {
|
||||
// TODO: Get rid of getJsDocComments and friends (note the lowercase 's' in Js)
|
||||
// TODO: A lot of this work should be cached, maybe. I guess it's only used in services right now...
|
||||
let result: T[] = undefined;
|
||||
// prepend documentation from parent sources
|
||||
if (checkParentVariableStatement) {
|
||||
// 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; }
|
||||
const isInitializerOfVariableDeclarationInStatement =
|
||||
isVariableLike(node.parent) &&
|
||||
(node.parent).initializer === node &&
|
||||
node.parent.parent.parent.kind === SyntaxKind.VariableStatement;
|
||||
const isVariableOfVariableDeclarationStatement = isVariableLike(node) &&
|
||||
node.parent.parent.kind === SyntaxKind.VariableStatement;
|
||||
|
||||
const variableStatementNode =
|
||||
isInitializerOfVariableDeclarationInStatement ? node.parent.parent.parent :
|
||||
isVariableOfVariableDeclarationStatement ? node.parent.parent :
|
||||
undefined;
|
||||
if (variableStatementNode) {
|
||||
return variableStatementNode.jsDocComments;
|
||||
result = append(result, getJSDocs(variableStatementNode, checkParentVariableStatement, getDocs, getTags));
|
||||
}
|
||||
if (node.kind === SyntaxKind.ModuleDeclaration &&
|
||||
node.parent && node.parent.kind === SyntaxKind.ModuleDeclaration) {
|
||||
result = append(result, getJSDocs(node.parent, checkParentVariableStatement, getDocs, getTags));
|
||||
}
|
||||
|
||||
// Also recognize when the node is the RHS of an assignment expression
|
||||
@@ -1469,16 +1505,62 @@ namespace ts {
|
||||
(parent as BinaryExpression).operatorToken.kind === SyntaxKind.EqualsToken &&
|
||||
parent.parent.kind === SyntaxKind.ExpressionStatement;
|
||||
if (isSourceOfAssignmentExpressionStatement) {
|
||||
return parent.parent.jsDocComments;
|
||||
result = append(result, getJSDocs(parent.parent, checkParentVariableStatement, getDocs, getTags));
|
||||
}
|
||||
|
||||
const isPropertyAssignmentExpression = parent && parent.kind === SyntaxKind.PropertyAssignment;
|
||||
if (isPropertyAssignmentExpression) {
|
||||
return parent.jsDocComments;
|
||||
result = append(result, getJSDocs(parent, checkParentVariableStatement, getDocs, getTags));
|
||||
}
|
||||
|
||||
// Pull parameter comments from declaring function as well
|
||||
if (node.kind === SyntaxKind.Parameter) {
|
||||
const paramTags = getJSDocParameterTag(node as ParameterDeclaration, checkParentVariableStatement);
|
||||
if (paramTags) {
|
||||
result = append(result, getTags(paramTags));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return undefined;
|
||||
if (isVariableLike(node) && node.initializer) {
|
||||
result = append(result, getJSDocs(node.initializer, /*checkParentVariableStatement*/ false, getDocs, getTags));
|
||||
}
|
||||
|
||||
if (node.jsDocComments) {
|
||||
if (result) {
|
||||
result = append(result, getDocs(node.jsDocComments));
|
||||
}
|
||||
else {
|
||||
return getDocs(node.jsDocComments);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
function getJSDocParameterTag(param: ParameterDeclaration, checkParentVariableStatement: boolean): JSDocTag[] {
|
||||
const func = param.parent as FunctionLikeDeclaration;
|
||||
const tags = getJSDocTags(func, checkParentVariableStatement);
|
||||
if (!param.name) {
|
||||
// this is an anonymous jsdoc param from a `function(type1, type2): type3` specification
|
||||
const i = func.parameters.indexOf(param);
|
||||
const paramTags = filter(tags, tag => tag.kind === SyntaxKind.JSDocParameterTag);
|
||||
if (paramTags && 0 <= i && i < paramTags.length) {
|
||||
return [paramTags[i]];
|
||||
}
|
||||
}
|
||||
else if (param.name.kind === SyntaxKind.Identifier) {
|
||||
const name = (param.name as Identifier).text;
|
||||
const paramTags = filter(tags, tag => tag.kind === SyntaxKind.JSDocParameterTag && (tag as JSDocParameterTag).parameterName.text === name);
|
||||
if (paramTags) {
|
||||
return paramTags;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// TODO: it's a destructured parameter, so it should look up an "object type" series of multiple lines
|
||||
// But multi-line object types aren't supported yet either
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
export function getJSDocTypeTag(node: Node): JSDocTypeTag {
|
||||
@@ -1499,17 +1581,15 @@ namespace ts {
|
||||
// annotation.
|
||||
const parameterName = (<Identifier>parameter.name).text;
|
||||
|
||||
const jsDocComments = getJSDocComments(parameter.parent, /*checkParentVariableStatement*/ true);
|
||||
if (jsDocComments) {
|
||||
for (const jsDocComment of jsDocComments) {
|
||||
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 parameterTag;
|
||||
}
|
||||
}
|
||||
const jsDocTags = getJSDocTags(parameter.parent, /*checkParentVariableStatement*/ true);
|
||||
if (!jsDocTags) {
|
||||
return undefined;
|
||||
}
|
||||
for (const tag of jsDocTags) {
|
||||
if (tag.kind === SyntaxKind.JSDocParameterTag) {
|
||||
const parameterTag = <JSDocParameterTag>tag;
|
||||
if (parameterTag.parameterName.text === parameterName) {
|
||||
return parameterTag;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -88,6 +88,10 @@ namespace FourSlash {
|
||||
marker?: Marker;
|
||||
}
|
||||
|
||||
interface ImplementationLocationInformation extends ts.ImplementationLocation {
|
||||
matched?: boolean;
|
||||
}
|
||||
|
||||
export interface TextSpan {
|
||||
start: number;
|
||||
end: number;
|
||||
@@ -1699,6 +1703,17 @@ namespace FourSlash {
|
||||
assertFn(actualCount, expectedCount, this.messageAtLastKnownMarker("Type definitions Count"));
|
||||
}
|
||||
|
||||
public verifyImplementationListIsEmpty(negative: boolean) {
|
||||
const implementations = this.languageService.getImplementationAtPosition(this.activeFile.fileName, this.currentCaretPosition);
|
||||
|
||||
if (negative) {
|
||||
assert.isTrue(implementations && implementations.length > 0, "Expected at least one implementation but got 0");
|
||||
}
|
||||
else {
|
||||
assert.isUndefined(implementations, "Expected implementation list to be empty but implementations returned");
|
||||
}
|
||||
}
|
||||
|
||||
public verifyGoToDefinitionName(expectedName: string, expectedContainerName: string) {
|
||||
const definitions = this.languageService.getDefinitionAtPosition(this.activeFile.fileName, this.currentCaretPosition);
|
||||
const actualDefinitionName = definitions && definitions.length ? definitions[0].name : "";
|
||||
@@ -1707,6 +1722,82 @@ namespace FourSlash {
|
||||
assert.equal(actualDefinitionContainerName, expectedContainerName, this.messageAtLastKnownMarker("Definition Info Container Name"));
|
||||
}
|
||||
|
||||
public goToImplementation() {
|
||||
const implementations = this.languageService.getImplementationAtPosition(this.activeFile.fileName, this.currentCaretPosition);
|
||||
if (!implementations || !implementations.length) {
|
||||
this.raiseError("goToImplementation failed - expected to find at least one implementation location but got 0");
|
||||
}
|
||||
if (implementations.length > 1) {
|
||||
this.raiseError(`goToImplementation failed - more than 1 implementation returned (${implementations.length})`);
|
||||
}
|
||||
|
||||
const implementation = implementations[0];
|
||||
this.openFile(implementation.fileName);
|
||||
this.currentCaretPosition = implementation.textSpan.start;
|
||||
}
|
||||
|
||||
public verifyRangesInImplementationList(markerName: string) {
|
||||
this.goToMarker(markerName);
|
||||
const implementations: ImplementationLocationInformation[] = this.languageService.getImplementationAtPosition(this.activeFile.fileName, this.currentCaretPosition);
|
||||
if (!implementations || !implementations.length) {
|
||||
this.raiseError("verifyRangesInImplementationList failed - expected to find at least one implementation location but got 0");
|
||||
}
|
||||
|
||||
for (let i = 0; i < implementations.length; i++) {
|
||||
for (let j = 0; j < implementations.length; j++) {
|
||||
if (i !== j && implementationsAreEqual(implementations[i], implementations[j])) {
|
||||
const { textSpan, fileName } = implementations[i];
|
||||
const end = textSpan.start + textSpan.length;
|
||||
this.raiseError(`Duplicate implementations returned for range (${textSpan.start}, ${end}) in ${fileName}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const ranges = this.getRanges();
|
||||
|
||||
if (!ranges || !ranges.length) {
|
||||
this.raiseError("verifyRangesInImplementationList failed - expected to find at least one range in test source");
|
||||
}
|
||||
|
||||
const unsatisfiedRanges: Range[] = [];
|
||||
|
||||
for (const range of ranges) {
|
||||
const length = range.end - range.start;
|
||||
const matchingImpl = ts.find(implementations, impl =>
|
||||
range.fileName === impl.fileName && range.start === impl.textSpan.start && length === impl.textSpan.length);
|
||||
if (matchingImpl) {
|
||||
matchingImpl.matched = true;
|
||||
}
|
||||
else {
|
||||
unsatisfiedRanges.push(range);
|
||||
}
|
||||
}
|
||||
|
||||
const unmatchedImplementations = implementations.filter(impl => !impl.matched);
|
||||
if (unmatchedImplementations.length || unsatisfiedRanges.length) {
|
||||
let error = "Not all ranges or implementations are satisfied";
|
||||
if (unsatisfiedRanges.length) {
|
||||
error += "\nUnsatisfied ranges:";
|
||||
for (const range of unsatisfiedRanges) {
|
||||
error += `\n (${range.start}, ${range.end}) in ${range.fileName}: ${this.rangeText(range)}`;
|
||||
}
|
||||
}
|
||||
|
||||
if (unmatchedImplementations.length) {
|
||||
error += "\nUnmatched implementations:";
|
||||
for (const impl of unmatchedImplementations) {
|
||||
const end = impl.textSpan.start + impl.textSpan.length;
|
||||
error += `\n (${impl.textSpan.start}, ${end}) in ${impl.fileName}: ${this.getFileContent(impl.fileName).slice(impl.textSpan.start, end)}`;
|
||||
}
|
||||
}
|
||||
this.raiseError(error);
|
||||
}
|
||||
|
||||
function implementationsAreEqual(a: ImplementationLocationInformation, b: ImplementationLocationInformation) {
|
||||
return a.fileName === b.fileName && TestState.textSpansEqual(a.textSpan, b.textSpan);
|
||||
}
|
||||
}
|
||||
|
||||
public getMarkers(): Marker[] {
|
||||
// Return a copy of the list
|
||||
return this.testData.markers.slice(0);
|
||||
@@ -2885,6 +2976,10 @@ namespace FourSlashInterface {
|
||||
this.state.goToTypeDefinition(definitionIndex);
|
||||
}
|
||||
|
||||
public implementation() {
|
||||
this.state.goToImplementation();
|
||||
}
|
||||
|
||||
public position(position: number, fileIndex?: number): void;
|
||||
public position(position: number, fileName?: string): void;
|
||||
public position(position: number, fileNameOrIndex?: any): void {
|
||||
@@ -2985,6 +3080,10 @@ namespace FourSlashInterface {
|
||||
this.state.verifyTypeDefinitionsCount(this.negative, expectedCount);
|
||||
}
|
||||
|
||||
public implementationListIsEmpty() {
|
||||
this.state.verifyImplementationListIsEmpty(this.negative);
|
||||
}
|
||||
|
||||
public isValidBraceCompletionAtPosition(openingBrace: string) {
|
||||
this.state.verifyBraceCompletionAtPosition(this.negative, openingBrace);
|
||||
}
|
||||
@@ -3253,6 +3352,10 @@ namespace FourSlashInterface {
|
||||
public ProjectInfo(expected: string[]) {
|
||||
this.state.verifyProjectInfo(expected);
|
||||
}
|
||||
|
||||
public allRangesAppearInImplementationList(markerName: string) {
|
||||
this.state.verifyRangesInImplementationList(markerName);
|
||||
}
|
||||
}
|
||||
|
||||
export class Edit {
|
||||
|
||||
@@ -435,6 +435,9 @@ namespace Harness.LanguageService {
|
||||
getTypeDefinitionAtPosition(fileName: string, position: number): ts.DefinitionInfo[] {
|
||||
return unwrapJSONCallResult(this.shim.getTypeDefinitionAtPosition(fileName, position));
|
||||
}
|
||||
getImplementationAtPosition(fileName: string, position: number): ts.ImplementationLocation[] {
|
||||
return unwrapJSONCallResult(this.shim.getImplementationAtPosition(fileName, position));
|
||||
}
|
||||
getReferencesAtPosition(fileName: string, position: number): ts.ReferenceEntry[] {
|
||||
return unwrapJSONCallResult(this.shim.getReferencesAtPosition(fileName, position));
|
||||
}
|
||||
@@ -489,6 +492,9 @@ namespace Harness.LanguageService {
|
||||
getNonBoundSourceFile(fileName: string): ts.SourceFile {
|
||||
throw new Error("SourceFile can not be marshaled across the shim layer.");
|
||||
}
|
||||
getSourceFile(fileName: string): ts.SourceFile {
|
||||
throw new Error("SourceFile can not be marshaled across the shim layer.");
|
||||
}
|
||||
dispose(): void { this.shim.dispose({}); }
|
||||
}
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ namespace ts {
|
||||
function parsesCorrectly(name: string, content: string) {
|
||||
it(name, () => {
|
||||
const typeAndDiagnostics = ts.parseJSDocTypeExpressionForTests(content);
|
||||
assert.isTrue(typeAndDiagnostics && typeAndDiagnostics.diagnostics.length === 0);
|
||||
assert.isTrue(typeAndDiagnostics && typeAndDiagnostics.diagnostics.length === 0, "no errors issued");
|
||||
|
||||
Harness.Baseline.runBaseline("JSDocParsing/TypeExpressions.parsesCorrectly." + name + ".json",
|
||||
() => Utils.sourceFileToJSON(typeAndDiagnostics.jsDocTypeExpression.type));
|
||||
@@ -36,6 +36,9 @@ namespace ts {
|
||||
parsesCorrectly("recordType6", "{{foo, bar: number}}");
|
||||
parsesCorrectly("recordType7", "{{foo: number, bar: number}}");
|
||||
parsesCorrectly("recordType8", "{{function}}");
|
||||
parsesCorrectly("trailingCommaInRecordType", "{{a,}}");
|
||||
parsesCorrectly("callSignatureInRecordType", "{{(): number}}");
|
||||
parsesCorrectly("methodInRecordType", "{{foo(): number}}");
|
||||
parsesCorrectly("unionType", "{(number|string)}");
|
||||
parsesCorrectly("topLevelNoParenUnionType", "{number|string}");
|
||||
parsesCorrectly("functionType1", "{function()}");
|
||||
@@ -63,7 +66,6 @@ namespace ts {
|
||||
|
||||
describe("parsesIncorrectly", () => {
|
||||
parsesIncorrectly("emptyType", "{}");
|
||||
parsesIncorrectly("trailingCommaInRecordType", "{{a,}}");
|
||||
parsesIncorrectly("unionTypeWithTrailingBar", "{(a|)}");
|
||||
parsesIncorrectly("unionTypeWithoutTypes", "{()}");
|
||||
parsesIncorrectly("nullableTypeWithoutType", "{!}");
|
||||
@@ -80,8 +82,6 @@ namespace ts {
|
||||
parsesIncorrectly("tsConstructoType", "{new () => string}");
|
||||
parsesIncorrectly("typeOfType", "{typeof M}");
|
||||
parsesIncorrectly("namedParameter", "{function(a: number)}");
|
||||
parsesIncorrectly("callSignatureInRecordType", "{{(): number}}");
|
||||
parsesIncorrectly("methodInRecordType", "{{foo(): number}}");
|
||||
parsesIncorrectly("tupleTypeWithComma", "{[,]}");
|
||||
parsesIncorrectly("tupleTypeWithTrailingComma", "{[number,]}");
|
||||
parsesIncorrectly("tupleTypeWithLeadingComma", "{[,number]}");
|
||||
@@ -100,7 +100,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
Harness.Baseline.runBaseline("JSDocParsing/DocComments.parsesCorrectly." + name + ".json",
|
||||
() => JSON.stringify(comment.jsDocComment,
|
||||
() => JSON.stringify(comment.jsDoc,
|
||||
(k, v) => v && v.pos !== undefined ? JSON.parse(Utils.sourceFileToJSON(v)) : v, 4));
|
||||
});
|
||||
}
|
||||
@@ -115,7 +115,6 @@ namespace ts {
|
||||
describe("parsesIncorrectly", () => {
|
||||
parsesIncorrectly("emptyComment", "/***/");
|
||||
parsesIncorrectly("threeAsterisks", "/*** */");
|
||||
parsesIncorrectly("asteriskAfterPreamble", "/** * @type {number} */");
|
||||
parsesIncorrectly("multipleTypes",
|
||||
`/**
|
||||
* @type {number}
|
||||
@@ -167,6 +166,7 @@ namespace ts {
|
||||
* @type {number}
|
||||
*/`);
|
||||
|
||||
parsesCorrectly("asteriskAfterPreamble", "/** * @type {number} */");
|
||||
|
||||
parsesCorrectly("typeTag",
|
||||
`/**
|
||||
|
||||
Vendored
+15
-2
@@ -1,7 +1,7 @@
|
||||
interface Map<K, V> {
|
||||
clear(): void;
|
||||
delete(key: K): boolean;
|
||||
forEach(callbackfn: (value: V, index: K, map: Map<K, V>) => void, thisArg?: any): void;
|
||||
forEach(callbackfn: (value: V, key: K, map: Map<K, V>) => void, thisArg?: any): void;
|
||||
get(key: K): V | undefined;
|
||||
has(key: K): boolean;
|
||||
set(key: K, value?: V): this;
|
||||
@@ -15,6 +15,13 @@ interface MapConstructor {
|
||||
}
|
||||
declare var Map: MapConstructor;
|
||||
|
||||
interface ReadonlyMap<K, V> {
|
||||
forEach(callbackfn: (value: V, key: K, map: ReadonlyMap<K, V>) => void, thisArg?: any): void;
|
||||
get(key: K): V|undefined;
|
||||
has(key: K): boolean;
|
||||
readonly size: number;
|
||||
}
|
||||
|
||||
interface WeakMap<K, V> {
|
||||
delete(key: K): boolean;
|
||||
get(key: K): V | undefined;
|
||||
@@ -33,7 +40,7 @@ interface Set<T> {
|
||||
add(value: T): this;
|
||||
clear(): void;
|
||||
delete(value: T): boolean;
|
||||
forEach(callbackfn: (value: T, index: T, set: Set<T>) => void, thisArg?: any): void;
|
||||
forEach(callbackfn: (value: T, value2: T, set: Set<T>) => void, thisArg?: any): void;
|
||||
has(value: T): boolean;
|
||||
readonly size: number;
|
||||
}
|
||||
@@ -45,6 +52,12 @@ interface SetConstructor {
|
||||
}
|
||||
declare var Set: SetConstructor;
|
||||
|
||||
interface ReadonlySet<T> {
|
||||
forEach(callbackfn: (value: T, value2: T, set: ReadonlySet<T>) => void, thisArg?: any): void;
|
||||
has(value: T): boolean;
|
||||
readonly size: number;
|
||||
}
|
||||
|
||||
interface WeakSet<T> {
|
||||
add(value: T): this;
|
||||
delete(value: T): boolean;
|
||||
|
||||
Vendored
+2
-2
@@ -21,7 +21,7 @@ interface Array<T> {
|
||||
* @param thisArg If provided, it will be used as the this value for each invocation of
|
||||
* predicate. If it is not provided, undefined is used instead.
|
||||
*/
|
||||
findIndex(predicate: (value: T) => boolean, thisArg?: any): number;
|
||||
findIndex(predicate: (value: T, index: number, obj: Array<T>) => boolean, thisArg?: any): number;
|
||||
|
||||
/**
|
||||
* Returns the this object after filling the section identified by start and end with value
|
||||
@@ -368,7 +368,7 @@ interface ReadonlyArray<T> {
|
||||
* @param thisArg If provided, it will be used as the this value for each invocation of
|
||||
* predicate. If it is not provided, undefined is used instead.
|
||||
*/
|
||||
findIndex(predicate: (value: T) => boolean, thisArg?: any): number;
|
||||
findIndex(predicate: (value: T, index: number, obj: Array<T>) => boolean, thisArg?: any): number;
|
||||
}
|
||||
|
||||
interface RegExp {
|
||||
|
||||
Vendored
+1
-2
@@ -6,8 +6,7 @@ declare namespace Reflect {
|
||||
function get(target: any, propertyKey: PropertyKey, receiver?: any): any;
|
||||
function getOwnPropertyDescriptor(target: any, propertyKey: PropertyKey): PropertyDescriptor;
|
||||
function getPrototypeOf(target: any): any;
|
||||
function has(target: any, propertyKey: string): boolean;
|
||||
function has(target: any, propertyKey: symbol): boolean;
|
||||
function has(target: any, propertyKey: PropertyKey): boolean;
|
||||
function isExtensible(target: any): boolean;
|
||||
function ownKeys(target: any): Array<PropertyKey>;
|
||||
function preventExtensions(target: any): boolean;
|
||||
|
||||
Vendored
+9
-9
@@ -1576,7 +1576,7 @@ interface Int8Array {
|
||||
* @param thisArg If provided, it will be used as the this value for each invocation of
|
||||
* predicate. If it is not provided, undefined is used instead.
|
||||
*/
|
||||
findIndex(predicate: (value: number) => boolean, thisArg?: any): number;
|
||||
findIndex(predicate: (value: number, index: number, obj: Array<number>) => boolean, thisArg?: any): number;
|
||||
|
||||
/**
|
||||
* Performs the specified action for each element in an array.
|
||||
@@ -1849,7 +1849,7 @@ interface Uint8Array {
|
||||
* @param thisArg If provided, it will be used as the this value for each invocation of
|
||||
* predicate. If it is not provided, undefined is used instead.
|
||||
*/
|
||||
findIndex(predicate: (value: number) => boolean, thisArg?: any): number;
|
||||
findIndex(predicate: (value: number, index: number, obj: Array<number>) => boolean, thisArg?: any): number;
|
||||
|
||||
/**
|
||||
* Performs the specified action for each element in an array.
|
||||
@@ -2123,7 +2123,7 @@ interface Uint8ClampedArray {
|
||||
* @param thisArg If provided, it will be used as the this value for each invocation of
|
||||
* predicate. If it is not provided, undefined is used instead.
|
||||
*/
|
||||
findIndex(predicate: (value: number) => boolean, thisArg?: any): number;
|
||||
findIndex(predicate: (value: number, index: number, obj: Array<number>) => boolean, thisArg?: any): number;
|
||||
|
||||
/**
|
||||
* Performs the specified action for each element in an array.
|
||||
@@ -2396,7 +2396,7 @@ interface Int16Array {
|
||||
* @param thisArg If provided, it will be used as the this value for each invocation of
|
||||
* predicate. If it is not provided, undefined is used instead.
|
||||
*/
|
||||
findIndex(predicate: (value: number) => boolean, thisArg?: any): number;
|
||||
findIndex(predicate: (value: number, index: number, obj: Array<number>) => boolean, thisArg?: any): number;
|
||||
|
||||
/**
|
||||
* Performs the specified action for each element in an array.
|
||||
@@ -2670,7 +2670,7 @@ interface Uint16Array {
|
||||
* @param thisArg If provided, it will be used as the this value for each invocation of
|
||||
* predicate. If it is not provided, undefined is used instead.
|
||||
*/
|
||||
findIndex(predicate: (value: number) => boolean, thisArg?: any): number;
|
||||
findIndex(predicate: (value: number, index: number, obj: Array<number>) => boolean, thisArg?: any): number;
|
||||
|
||||
/**
|
||||
* Performs the specified action for each element in an array.
|
||||
@@ -2943,7 +2943,7 @@ interface Int32Array {
|
||||
* @param thisArg If provided, it will be used as the this value for each invocation of
|
||||
* predicate. If it is not provided, undefined is used instead.
|
||||
*/
|
||||
findIndex(predicate: (value: number) => boolean, thisArg?: any): number;
|
||||
findIndex(predicate: (value: number, index: number, obj: Array<number>) => boolean, thisArg?: any): number;
|
||||
|
||||
/**
|
||||
* Performs the specified action for each element in an array.
|
||||
@@ -3216,7 +3216,7 @@ interface Uint32Array {
|
||||
* @param thisArg If provided, it will be used as the this value for each invocation of
|
||||
* predicate. If it is not provided, undefined is used instead.
|
||||
*/
|
||||
findIndex(predicate: (value: number) => boolean, thisArg?: any): number;
|
||||
findIndex(predicate: (value: number, index: number, obj: Array<number>) => boolean, thisArg?: any): number;
|
||||
|
||||
/**
|
||||
* Performs the specified action for each element in an array.
|
||||
@@ -3489,7 +3489,7 @@ interface Float32Array {
|
||||
* @param thisArg If provided, it will be used as the this value for each invocation of
|
||||
* predicate. If it is not provided, undefined is used instead.
|
||||
*/
|
||||
findIndex(predicate: (value: number) => boolean, thisArg?: any): number;
|
||||
findIndex(predicate: (value: number, index: number, obj: Array<number>) => boolean, thisArg?: any): number;
|
||||
|
||||
/**
|
||||
* Performs the specified action for each element in an array.
|
||||
@@ -3763,7 +3763,7 @@ interface Float64Array {
|
||||
* @param thisArg If provided, it will be used as the this value for each invocation of
|
||||
* predicate. If it is not provided, undefined is used instead.
|
||||
*/
|
||||
findIndex(predicate: (value: number) => boolean, thisArg?: any): number;
|
||||
findIndex(predicate: (value: number, index: number, obj: Array<number>) => boolean, thisArg?: any): number;
|
||||
|
||||
/**
|
||||
* Performs the specified action for each element in an array.
|
||||
|
||||
@@ -368,6 +368,28 @@ namespace ts.server {
|
||||
});
|
||||
}
|
||||
|
||||
getImplementationAtPosition(fileName: string, position: number): ImplementationLocation[] {
|
||||
const lineOffset = this.positionToOneBasedLineOffset(fileName, position);
|
||||
const args: protocol.FileLocationRequestArgs = {
|
||||
file: fileName,
|
||||
line: lineOffset.line,
|
||||
offset: lineOffset.offset,
|
||||
};
|
||||
|
||||
const request = this.processRequest<protocol.ImplementationRequest>(CommandNames.Implementation, args);
|
||||
const response = this.processResponse<protocol.ImplementationResponse>(request);
|
||||
|
||||
return response.body.map(entry => {
|
||||
const fileName = entry.file;
|
||||
const start = this.lineOffsetToPosition(fileName, entry.start);
|
||||
const end = this.lineOffsetToPosition(fileName, entry.end);
|
||||
return {
|
||||
fileName,
|
||||
textSpan: ts.createTextSpanFromBounds(start, end)
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
findReferences(fileName: string, position: number): ReferencedSymbol[] {
|
||||
// Not yet implemented.
|
||||
return [];
|
||||
@@ -656,6 +678,10 @@ namespace ts.server {
|
||||
throw new Error("SourceFile objects are not serializable through the server protocol.");
|
||||
}
|
||||
|
||||
getSourceFile(fileName: string): SourceFile {
|
||||
throw new Error("SourceFile objects are not serializable through the server protocol.");
|
||||
}
|
||||
|
||||
cleanupSemanticCache(): void {
|
||||
throw new Error("cleanupSemanticCache is not available through the server layer.");
|
||||
}
|
||||
|
||||
Vendored
+15
@@ -193,6 +193,14 @@ declare namespace ts.server.protocol {
|
||||
export interface TypeDefinitionRequest extends FileLocationRequest {
|
||||
}
|
||||
|
||||
/**
|
||||
* Go to implementation request; value of command field is
|
||||
* "implementation". Return response giving the file locations that
|
||||
* implement the symbol found in file at location line, col.
|
||||
*/
|
||||
export interface ImplementationRequest extends FileLocationRequest {
|
||||
}
|
||||
|
||||
/**
|
||||
* Location in source code expressed as (one-based) line and character offset.
|
||||
*/
|
||||
@@ -240,6 +248,13 @@ declare namespace ts.server.protocol {
|
||||
body?: FileSpan[];
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation response message. Gives text range for implementations.
|
||||
*/
|
||||
export interface ImplementationResponse extends Response {
|
||||
body?: FileSpan[];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get occurrences request; value of command field is
|
||||
* "occurrences". Return response giving spans that are relevant
|
||||
|
||||
@@ -111,6 +111,7 @@ namespace ts.server {
|
||||
export const Formatonkey = "formatonkey";
|
||||
export const Geterr = "geterr";
|
||||
export const GeterrForProject = "geterrForProject";
|
||||
export const Implementation = "implementation";
|
||||
export const SemanticDiagnosticsSync = "semanticDiagnosticsSync";
|
||||
export const SyntacticDiagnosticsSync = "syntacticDiagnosticsSync";
|
||||
export const NavBar = "navbar";
|
||||
@@ -363,6 +364,28 @@ namespace ts.server {
|
||||
}));
|
||||
}
|
||||
|
||||
private getImplementation(line: number, offset: number, fileName: string): protocol.FileSpan[] {
|
||||
const file = ts.normalizePath(fileName);
|
||||
const project = this.projectService.getProjectForFile(file);
|
||||
if (!project || project.languageServiceDiabled) {
|
||||
throw Errors.NoProject;
|
||||
}
|
||||
|
||||
const compilerService = project.compilerService;
|
||||
const implementations = compilerService.languageService.getImplementationAtPosition(file,
|
||||
compilerService.host.lineOffsetToPosition(file, line, offset));
|
||||
|
||||
if (!implementations) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return implementations.map(impl => ({
|
||||
file: impl.fileName,
|
||||
start: compilerService.host.positionToLineOffset(impl.fileName, impl.textSpan.start),
|
||||
end: compilerService.host.positionToLineOffset(impl.fileName, ts.textSpanEnd(impl.textSpan))
|
||||
}));
|
||||
}
|
||||
|
||||
private getOccurrences(line: number, offset: number, fileName: string): protocol.OccurrencesResponseItem[] {
|
||||
fileName = ts.normalizePath(fileName);
|
||||
const project = this.projectService.getProjectForFile(fileName);
|
||||
@@ -1090,6 +1113,10 @@ namespace ts.server {
|
||||
const defArgs = <protocol.FileLocationRequestArgs>request.arguments;
|
||||
return { response: this.getTypeDefinition(defArgs.line, defArgs.offset, defArgs.file), responseRequired: true };
|
||||
},
|
||||
[CommandNames.Implementation]: (request: protocol.Request) => {
|
||||
const implArgs = <protocol.FileLocationRequestArgs>request.arguments;
|
||||
return { response: this.getImplementation(implArgs.line, implArgs.offset, implArgs.file), responseRequired: true };
|
||||
},
|
||||
[CommandNames.References]: (request: protocol.Request) => {
|
||||
const defArgs = <protocol.FileLocationRequestArgs>request.arguments;
|
||||
return { response: this.getReferences(defArgs.line, defArgs.offset, defArgs.file), responseRequired: true };
|
||||
|
||||
+34
-32
@@ -698,9 +698,9 @@ namespace ts {
|
||||
// See if this is a doc comment. If so, we'll classify certain portions of it
|
||||
// specially.
|
||||
const docCommentAndDiagnostics = parseIsolatedJSDocComment(sourceFile.text, start, width);
|
||||
if (docCommentAndDiagnostics && docCommentAndDiagnostics.jsDocComment) {
|
||||
docCommentAndDiagnostics.jsDocComment.parent = token;
|
||||
classifyJSDocComment(docCommentAndDiagnostics.jsDocComment);
|
||||
if (docCommentAndDiagnostics && docCommentAndDiagnostics.jsDoc) {
|
||||
docCommentAndDiagnostics.jsDoc.parent = token;
|
||||
classifyJSDocComment(docCommentAndDiagnostics.jsDoc);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -713,37 +713,39 @@ namespace ts {
|
||||
pushClassification(start, width, ClassificationType.comment);
|
||||
}
|
||||
|
||||
function classifyJSDocComment(docComment: JSDocComment) {
|
||||
function classifyJSDocComment(docComment: JSDoc) {
|
||||
let pos = docComment.pos;
|
||||
|
||||
for (const tag of docComment.tags) {
|
||||
// As we walk through each tag, classify the portion of text from the end of
|
||||
// the last tag (or the start of the entire doc comment) as 'comment'.
|
||||
if (tag.pos !== pos) {
|
||||
pushCommentRange(pos, tag.pos - pos);
|
||||
if (docComment.tags) {
|
||||
for (const tag of docComment.tags) {
|
||||
// As we walk through each tag, classify the portion of text from the end of
|
||||
// the last tag (or the start of the entire doc comment) as 'comment'.
|
||||
if (tag.pos !== pos) {
|
||||
pushCommentRange(pos, tag.pos - pos);
|
||||
}
|
||||
|
||||
pushClassification(tag.atToken.pos, tag.atToken.end - tag.atToken.pos, ClassificationType.punctuation);
|
||||
pushClassification(tag.tagName.pos, tag.tagName.end - tag.tagName.pos, ClassificationType.docCommentTagName);
|
||||
|
||||
pos = tag.tagName.end;
|
||||
|
||||
switch (tag.kind) {
|
||||
case SyntaxKind.JSDocParameterTag:
|
||||
processJSDocParameterTag(<JSDocParameterTag>tag);
|
||||
break;
|
||||
case SyntaxKind.JSDocTemplateTag:
|
||||
processJSDocTemplateTag(<JSDocTemplateTag>tag);
|
||||
break;
|
||||
case SyntaxKind.JSDocTypeTag:
|
||||
processElement((<JSDocTypeTag>tag).typeExpression);
|
||||
break;
|
||||
case SyntaxKind.JSDocReturnTag:
|
||||
processElement((<JSDocReturnTag>tag).typeExpression);
|
||||
break;
|
||||
}
|
||||
|
||||
pos = tag.end;
|
||||
}
|
||||
|
||||
pushClassification(tag.atToken.pos, tag.atToken.end - tag.atToken.pos, ClassificationType.punctuation);
|
||||
pushClassification(tag.tagName.pos, tag.tagName.end - tag.tagName.pos, ClassificationType.docCommentTagName);
|
||||
|
||||
pos = tag.tagName.end;
|
||||
|
||||
switch (tag.kind) {
|
||||
case SyntaxKind.JSDocParameterTag:
|
||||
processJSDocParameterTag(<JSDocParameterTag>tag);
|
||||
break;
|
||||
case SyntaxKind.JSDocTemplateTag:
|
||||
processJSDocTemplateTag(<JSDocTemplateTag>tag);
|
||||
break;
|
||||
case SyntaxKind.JSDocTypeTag:
|
||||
processElement((<JSDocTypeTag>tag).typeExpression);
|
||||
break;
|
||||
case SyntaxKind.JSDocReturnTag:
|
||||
processElement((<JSDocReturnTag>tag).typeExpression);
|
||||
break;
|
||||
}
|
||||
|
||||
pos = tag.end;
|
||||
}
|
||||
|
||||
if (pos !== docComment.end) {
|
||||
@@ -982,4 +984,4 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,7 +27,7 @@ namespace ts.DocumentHighlights {
|
||||
node.kind === SyntaxKind.StringLiteral ||
|
||||
isLiteralNameOfPropertyDeclarationOrIndexAccess(node)) {
|
||||
|
||||
const referencedSymbols = FindAllReferences.getReferencedSymbolsForNode(typeChecker, cancellationToken, node, sourceFilesToSearch, /*findInStrings*/ false, /*findInComments*/ false);
|
||||
const referencedSymbols = FindAllReferences.getReferencedSymbolsForNode(typeChecker, cancellationToken, node, sourceFilesToSearch, /*findInStrings*/ false, /*findInComments*/ false, /*implementations*/false);
|
||||
return convertReferencedSymbols(referencedSymbols);
|
||||
|
||||
}
|
||||
|
||||
@@ -17,42 +17,45 @@ namespace ts.FindAllReferences {
|
||||
// case SyntaxKind.SuperKeyword: TODO:GH#9268
|
||||
case SyntaxKind.ConstructorKeyword:
|
||||
case SyntaxKind.StringLiteral:
|
||||
return getReferencedSymbolsForNode(typeChecker, cancellationToken, node, sourceFiles, findInStrings, findInComments);
|
||||
return getReferencedSymbolsForNode(typeChecker, cancellationToken, node, sourceFiles, findInStrings, findInComments, /*implementations*/false);
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
export function getReferencedSymbolsForNode(typeChecker: TypeChecker, cancellationToken: CancellationToken, node: Node, sourceFiles: SourceFile[], findInStrings: boolean, findInComments: boolean): ReferencedSymbol[] {
|
||||
// Labels
|
||||
if (isLabelName(node)) {
|
||||
if (isJumpStatementTarget(node)) {
|
||||
const labelDefinition = getTargetLabel((<BreakOrContinueStatement>node.parent), (<Identifier>node).text);
|
||||
// if we have a label definition, look within its statement for references, if not, then
|
||||
// the label is undefined and we have no results..
|
||||
return labelDefinition ? getLabelReferencesInNode(labelDefinition.parent, labelDefinition) : undefined;
|
||||
export function getReferencedSymbolsForNode(typeChecker: TypeChecker, cancellationToken: CancellationToken, node: Node, sourceFiles: SourceFile[], findInStrings: boolean, findInComments: boolean, implementations: boolean): ReferencedSymbol[] {
|
||||
if (!implementations) {
|
||||
// Labels
|
||||
if (isLabelName(node)) {
|
||||
if (isJumpStatementTarget(node)) {
|
||||
const labelDefinition = getTargetLabel((<BreakOrContinueStatement>node.parent), (<Identifier>node).text);
|
||||
// if we have a label definition, look within its statement for references, if not, then
|
||||
// the label is undefined and we have no results..
|
||||
return labelDefinition ? getLabelReferencesInNode(labelDefinition.parent, labelDefinition) : undefined;
|
||||
}
|
||||
else {
|
||||
// it is a label definition and not a target, search within the parent labeledStatement
|
||||
return getLabelReferencesInNode(node.parent, <Identifier>node);
|
||||
}
|
||||
}
|
||||
else {
|
||||
// it is a label definition and not a target, search within the parent labeledStatement
|
||||
return getLabelReferencesInNode(node.parent, <Identifier>node);
|
||||
|
||||
if (isThis(node)) {
|
||||
return getReferencesForThisKeyword(node, sourceFiles);
|
||||
}
|
||||
}
|
||||
|
||||
if (isThis(node)) {
|
||||
return getReferencesForThisKeyword(node, sourceFiles);
|
||||
}
|
||||
|
||||
if (node.kind === SyntaxKind.SuperKeyword) {
|
||||
return getReferencesForSuperKeyword(node);
|
||||
if (node.kind === SyntaxKind.SuperKeyword) {
|
||||
return getReferencesForSuperKeyword(node);
|
||||
}
|
||||
}
|
||||
|
||||
// `getSymbolAtLocation` normally returns the symbol of the class when given the constructor keyword,
|
||||
// so we have to specify that we want the constructor symbol.
|
||||
const symbol = typeChecker.getSymbolAtLocation(node);
|
||||
|
||||
if (!symbol && node.kind === SyntaxKind.StringLiteral) {
|
||||
if (!implementations && !symbol && node.kind === SyntaxKind.StringLiteral) {
|
||||
return getReferencesForStringLiteral(<StringLiteral>node, sourceFiles);
|
||||
}
|
||||
|
||||
|
||||
// Could not find a symbol e.g. unknown identifier
|
||||
if (!symbol) {
|
||||
// Can't have references to something that we have no symbol for.
|
||||
@@ -356,9 +359,9 @@ namespace ts.FindAllReferences {
|
||||
}
|
||||
|
||||
/** Search within node "container" for references for a search value, where the search value is defined as a
|
||||
* tuple of(searchSymbol, searchText, searchLocation, and searchMeaning).
|
||||
* searchLocation: a node where the search value
|
||||
*/
|
||||
* tuple of(searchSymbol, searchText, searchLocation, and searchMeaning).
|
||||
* searchLocation: a node where the search value
|
||||
*/
|
||||
function getReferencesInNode(container: Node,
|
||||
searchSymbol: Symbol,
|
||||
searchText: string,
|
||||
@@ -374,6 +377,9 @@ namespace ts.FindAllReferences {
|
||||
const start = findInComments ? container.getFullStart() : container.getStart();
|
||||
const possiblePositions = getPossibleSymbolReferencePositions(sourceFile, searchText, start, container.getEnd());
|
||||
|
||||
const parents = getParentSymbolsOfPropertyAccess();
|
||||
const inheritsFromCache: Map<boolean> = createMap<boolean>();
|
||||
|
||||
if (possiblePositions.length) {
|
||||
// Build the set of symbols to search for, initially it has only the current symbol
|
||||
const searchSymbols = populateSearchSymbolSet(searchSymbol, searchLocation);
|
||||
@@ -386,8 +392,8 @@ namespace ts.FindAllReferences {
|
||||
// This wasn't the start of a token. Check to see if it might be a
|
||||
// match in a comment or string if that's what the caller is asking
|
||||
// for.
|
||||
if ((findInStrings && isInString(sourceFile, position)) ||
|
||||
(findInComments && isInNonReferenceComment(sourceFile, position))) {
|
||||
if (!implementations && ((findInStrings && isInString(sourceFile, position)) ||
|
||||
(findInComments && isInNonReferenceComment(sourceFile, position)))) {
|
||||
|
||||
// In the case where we're looking inside comments/strings, we don't have
|
||||
// an actual definition. So just use 'undefined' here. Features like
|
||||
@@ -415,11 +421,10 @@ namespace ts.FindAllReferences {
|
||||
const referenceSymbolDeclaration = referenceSymbol.valueDeclaration;
|
||||
const shorthandValueSymbol = typeChecker.getShorthandAssignmentValueSymbol(referenceSymbolDeclaration);
|
||||
const relatedSymbol = getRelatedSymbol(searchSymbols, referenceSymbol, referenceLocation,
|
||||
/*searchLocationIsConstructor*/ searchLocation.kind === SyntaxKind.ConstructorKeyword);
|
||||
/*searchLocationIsConstructor*/ searchLocation.kind === SyntaxKind.ConstructorKeyword, parents, inheritsFromCache);
|
||||
|
||||
if (relatedSymbol) {
|
||||
const referencedSymbol = getReferencedSymbol(relatedSymbol);
|
||||
referencedSymbol.references.push(getReferenceEntryFromNode(referenceLocation));
|
||||
addReferenceToRelatedSymbol(referenceLocation, relatedSymbol);
|
||||
}
|
||||
/* Because in short-hand property assignment, an identifier which stored as name of the short-hand property assignment
|
||||
* has two meaning : property name and property value. Therefore when we do findAllReference at the position where
|
||||
@@ -428,8 +433,7 @@ namespace ts.FindAllReferences {
|
||||
* position of property accessing, the referenceEntry of such position will be handled in the first case.
|
||||
*/
|
||||
else if (!(referenceSymbol.flags & SymbolFlags.Transient) && searchSymbols.indexOf(shorthandValueSymbol) >= 0) {
|
||||
const referencedSymbol = getReferencedSymbol(shorthandValueSymbol);
|
||||
referencedSymbol.references.push(getReferenceEntryFromNode(referenceSymbolDeclaration.name));
|
||||
addReferenceToRelatedSymbol(referenceSymbolDeclaration.name, shorthandValueSymbol);
|
||||
}
|
||||
else if (searchLocation.kind === SyntaxKind.ConstructorKeyword) {
|
||||
findAdditionalConstructorReferences(referenceSymbol, referenceLocation);
|
||||
@@ -437,9 +441,34 @@ namespace ts.FindAllReferences {
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
/* If we are just looking for implementations and this is a property access expression, we need to get the
|
||||
* symbol of the local type of the symbol the property is being accessed on. This is because our search
|
||||
* symbol may have a different parent symbol if the local type's symbol does not declare the property
|
||||
* being accessed (i.e. it is declared in some parent class or interface)
|
||||
*/
|
||||
function getParentSymbolsOfPropertyAccess(): Symbol[] | undefined {
|
||||
if (implementations) {
|
||||
const propertyAccessExpression = getPropertyAccessExpressionFromRightHandSide(searchLocation);
|
||||
if (propertyAccessExpression) {
|
||||
const localParentType = typeChecker.getTypeAtLocation(propertyAccessExpression.expression);
|
||||
if (localParentType) {
|
||||
if (localParentType.symbol && localParentType.symbol.flags & (SymbolFlags.Class | SymbolFlags.Interface) && localParentType.symbol !== searchSymbol.parent) {
|
||||
return [localParentType.symbol];
|
||||
}
|
||||
else if (localParentType.flags & TypeFlags.UnionOrIntersection) {
|
||||
return getSymbolsForClassAndInterfaceComponents(<UnionOrIntersectionType>localParentType);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function getPropertyAccessExpressionFromRightHandSide(node: Node): PropertyAccessExpression {
|
||||
return isRightSideOfPropertyAccess(node) && <PropertyAccessExpression>node.parent;
|
||||
}
|
||||
|
||||
/** Adds references when a constructor is used with `new this()` in its own class and `super()` calls in subclasses. */
|
||||
function findAdditionalConstructorReferences(referenceSymbol: Symbol, referenceLocation: Node): void {
|
||||
Debug.assert(isClassLike(searchSymbol.valueDeclaration));
|
||||
@@ -534,6 +563,200 @@ namespace ts.FindAllReferences {
|
||||
|
||||
return result[index];
|
||||
}
|
||||
|
||||
function addReferenceToRelatedSymbol(node: Node, relatedSymbol: Symbol) {
|
||||
const references = getReferencedSymbol(relatedSymbol).references;
|
||||
if (implementations) {
|
||||
getImplementationReferenceEntryForNode(node, references);
|
||||
}
|
||||
else {
|
||||
references.push(getReferenceEntryFromNode(node));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function getImplementationReferenceEntryForNode(refNode: Node, result: ReferenceEntry[]): void {
|
||||
// Check if we found a function/propertyAssignment/method with an implementation or initializer
|
||||
if (isDeclarationName(refNode) && isImplementation(refNode.parent)) {
|
||||
result.push(getReferenceEntryFromNode(refNode.parent));
|
||||
}
|
||||
else if (refNode.kind === SyntaxKind.Identifier) {
|
||||
if (refNode.parent.kind === SyntaxKind.ShorthandPropertyAssignment) {
|
||||
// Go ahead and dereference the shorthand assignment by going to its definition
|
||||
getReferenceEntriesForShorthandPropertyAssignment(refNode, typeChecker, result);
|
||||
}
|
||||
|
||||
// Check if the node is within an extends or implements clause
|
||||
const containingClass = getContainingClassIfInHeritageClause(refNode);
|
||||
if (containingClass) {
|
||||
result.push(getReferenceEntryFromNode(containingClass));
|
||||
return;
|
||||
}
|
||||
|
||||
// If we got a type reference, try and see if the reference applies to any expressions that can implement an interface
|
||||
const containingTypeReference = getContainingTypeReference(refNode);
|
||||
if (containingTypeReference) {
|
||||
const parent = containingTypeReference.parent;
|
||||
if (isVariableLike(parent) && parent.type === containingTypeReference && parent.initializer && isImplementationExpression(parent.initializer)) {
|
||||
maybeAdd(getReferenceEntryFromNode(parent.initializer));
|
||||
}
|
||||
else if (isFunctionLike(parent) && parent.type === containingTypeReference && parent.body) {
|
||||
if (parent.body.kind === SyntaxKind.Block) {
|
||||
forEachReturnStatement(<Block>parent.body, returnStatement => {
|
||||
if (returnStatement.expression && isImplementationExpression(returnStatement.expression)) {
|
||||
maybeAdd(getReferenceEntryFromNode(returnStatement.expression));
|
||||
}
|
||||
});
|
||||
}
|
||||
else if (isImplementationExpression(<Expression>parent.body)) {
|
||||
maybeAdd(getReferenceEntryFromNode(parent.body));
|
||||
}
|
||||
}
|
||||
else if (isAssertionExpression(parent) && isImplementationExpression(parent.expression)) {
|
||||
maybeAdd(getReferenceEntryFromNode(parent.expression));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Type nodes can contain multiple references to the same type. For example:
|
||||
// let x: Foo & (Foo & Bar) = ...
|
||||
// Because we are returning the implementation locations and not the identifier locations,
|
||||
// duplicate entries would be returned here as each of the type references is part of
|
||||
// the same implementation. For that reason, check before we add a new entry
|
||||
function maybeAdd(a: ReferenceEntry) {
|
||||
if (!forEach(result, b => a.fileName === b.fileName && a.textSpan.start === b.textSpan.start && a.textSpan.length === b.textSpan.length)) {
|
||||
result.push(a);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function getSymbolsForClassAndInterfaceComponents(type: UnionOrIntersectionType, result: Symbol[] = []): Symbol[] {
|
||||
for (const componentType of type.types) {
|
||||
if (componentType.symbol && componentType.symbol.getFlags() & (SymbolFlags.Class | SymbolFlags.Interface)) {
|
||||
result.push(componentType.symbol);
|
||||
}
|
||||
if (componentType.getFlags() & TypeFlags.UnionOrIntersection) {
|
||||
getSymbolsForClassAndInterfaceComponents(<UnionOrIntersectionType>componentType, result);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
function getContainingTypeReference(node: Node): Node {
|
||||
let topLevelTypeReference: Node = undefined;
|
||||
|
||||
while (node) {
|
||||
if (isTypeNode(node)) {
|
||||
topLevelTypeReference = node;
|
||||
}
|
||||
node = node.parent;
|
||||
}
|
||||
|
||||
return topLevelTypeReference;
|
||||
}
|
||||
|
||||
function getContainingClassIfInHeritageClause(node: Node): ClassLikeDeclaration {
|
||||
if (node && node.parent) {
|
||||
if (node.kind === SyntaxKind.ExpressionWithTypeArguments
|
||||
&& node.parent.kind === SyntaxKind.HeritageClause
|
||||
&& isClassLike(node.parent.parent)) {
|
||||
return node.parent.parent;
|
||||
}
|
||||
|
||||
else if (node.kind === SyntaxKind.Identifier || node.kind === SyntaxKind.PropertyAccessExpression) {
|
||||
return getContainingClassIfInHeritageClause(node.parent);
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if this is an expression that can be considered an implementation
|
||||
*/
|
||||
function isImplementationExpression(node: Expression): boolean {
|
||||
// Unwrap parentheses
|
||||
if (node.kind === SyntaxKind.ParenthesizedExpression) {
|
||||
return isImplementationExpression((<ParenthesizedExpression>node).expression);
|
||||
}
|
||||
|
||||
return node.kind === SyntaxKind.ArrowFunction ||
|
||||
node.kind === SyntaxKind.FunctionExpression ||
|
||||
node.kind === SyntaxKind.ObjectLiteralExpression ||
|
||||
node.kind === SyntaxKind.ClassExpression ||
|
||||
node.kind === SyntaxKind.ArrayLiteralExpression;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if the parent symbol occurs somewhere in the child's ancestry. If the parent symbol
|
||||
* is an interface, determines if some ancestor of the child symbol extends or inherits from it.
|
||||
* Also takes in a cache of previous results which makes this slightly more efficient and is
|
||||
* necessary to avoid potential loops like so:
|
||||
* class A extends B { }
|
||||
* class B extends A { }
|
||||
*
|
||||
* We traverse the AST rather than using the type checker because users are typically only interested
|
||||
* in explicit implementations of an interface/class when calling "Go to Implementation". Sibling
|
||||
* implementations of types that share a common ancestor with the type whose implementation we are
|
||||
* searching for need to be filtered out of the results. The type checker doesn't let us make the
|
||||
* distinction between structurally compatible implementations and explicit implementations, so we
|
||||
* must use the AST.
|
||||
*
|
||||
* @param child A class or interface Symbol
|
||||
* @param parent Another class or interface Symbol
|
||||
* @param cachedResults A map of symbol id pairs (i.e. "child,parent") to booleans indicating previous results
|
||||
*/
|
||||
function explicitlyInheritsFrom(child: Symbol, parent: Symbol, cachedResults: Map<boolean>): boolean {
|
||||
const parentIsInterface = parent.getFlags() & SymbolFlags.Interface;
|
||||
return searchHierarchy(child);
|
||||
|
||||
function searchHierarchy(symbol: Symbol): boolean {
|
||||
if (symbol === parent) {
|
||||
return true;
|
||||
}
|
||||
|
||||
const key = getSymbolId(symbol) + "," + getSymbolId(parent);
|
||||
if (key in cachedResults) {
|
||||
return cachedResults[key];
|
||||
}
|
||||
|
||||
// Set the key so that we don't infinitely recurse
|
||||
cachedResults[key] = false;
|
||||
|
||||
const inherits = forEach(symbol.getDeclarations(), declaration => {
|
||||
if (isClassLike(declaration)) {
|
||||
if (parentIsInterface) {
|
||||
const interfaceReferences = getClassImplementsHeritageClauseElements(declaration);
|
||||
if (interfaceReferences) {
|
||||
for (const typeReference of interfaceReferences) {
|
||||
if (searchTypeReference(typeReference)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return searchTypeReference(getClassExtendsHeritageClauseElement(declaration));
|
||||
}
|
||||
else if (declaration.kind === SyntaxKind.InterfaceDeclaration) {
|
||||
if (parentIsInterface) {
|
||||
return forEach(getInterfaceBaseTypeNodes(<InterfaceDeclaration>declaration), searchTypeReference);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
});
|
||||
|
||||
cachedResults[key] = inherits;
|
||||
return inherits;
|
||||
}
|
||||
|
||||
function searchTypeReference(typeReference: ExpressionWithTypeArguments): boolean {
|
||||
if (typeReference) {
|
||||
const type = typeChecker.getTypeAtLocation(typeReference);
|
||||
if (type && type.symbol) {
|
||||
return searchHierarchy(type.symbol);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
function getReferencesForSuperKeyword(superKeyword: Node): ReferencedSymbol[] {
|
||||
@@ -696,6 +919,7 @@ namespace ts.FindAllReferences {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function getReferencesForStringLiteral(node: StringLiteral, sourceFiles: SourceFile[]): ReferencedSymbol[] {
|
||||
const type = getStringLiteralTypeForNode(node, typeChecker);
|
||||
|
||||
@@ -821,7 +1045,7 @@ namespace ts.FindAllReferences {
|
||||
}
|
||||
|
||||
// Add symbol of properties/methods of the same name in base classes and implemented interfaces definitions
|
||||
if (rootSymbol.parent && rootSymbol.parent.flags & (SymbolFlags.Class | SymbolFlags.Interface)) {
|
||||
if (!implementations && rootSymbol.parent && rootSymbol.parent.flags & (SymbolFlags.Class | SymbolFlags.Interface)) {
|
||||
getPropertySymbolsFromBaseTypes(rootSymbol.parent, rootSymbol.getName(), result, /*previousIterationSymbolsCache*/ createMap<Symbol>());
|
||||
}
|
||||
});
|
||||
@@ -888,7 +1112,7 @@ namespace ts.FindAllReferences {
|
||||
}
|
||||
}
|
||||
|
||||
function getRelatedSymbol(searchSymbols: Symbol[], referenceSymbol: Symbol, referenceLocation: Node, searchLocationIsConstructor: boolean): Symbol | undefined {
|
||||
function getRelatedSymbol(searchSymbols: Symbol[], referenceSymbol: Symbol, referenceLocation: Node, searchLocationIsConstructor: boolean, parents: Symbol[] | undefined, cache: Map<boolean>): Symbol {
|
||||
if (contains(searchSymbols, referenceSymbol)) {
|
||||
// If we are searching for constructor uses, they must be 'new' expressions.
|
||||
return (!searchLocationIsConstructor || isNewExpressionTarget(referenceLocation)) && referenceSymbol;
|
||||
@@ -898,7 +1122,7 @@ namespace ts.FindAllReferences {
|
||||
// symbols but by looking up for related symbol of this alias so it can handle multiple level of indirectness.
|
||||
const aliasSymbol = getAliasSymbolForPropertyNameSymbol(referenceSymbol, referenceLocation);
|
||||
if (aliasSymbol) {
|
||||
return getRelatedSymbol(searchSymbols, aliasSymbol, referenceLocation, searchLocationIsConstructor);
|
||||
return getRelatedSymbol(searchSymbols, aliasSymbol, referenceLocation, searchLocationIsConstructor, parents, cache);
|
||||
}
|
||||
|
||||
// If the reference location is in an object literal, try to get the contextual type for the
|
||||
@@ -941,8 +1165,16 @@ namespace ts.FindAllReferences {
|
||||
}
|
||||
|
||||
// Finally, try all properties with the same name in any type the containing type extended or implemented, and
|
||||
// see if any is in the list
|
||||
// see if any is in the list. If we were passed a parent symbol, only include types that are subtypes of the
|
||||
// parent symbol
|
||||
if (rootSymbol.parent && rootSymbol.parent.flags & (SymbolFlags.Class | SymbolFlags.Interface)) {
|
||||
// Parents will only be defined if implementations is true
|
||||
if (parents) {
|
||||
if (!forEach(parents, parent => explicitlyInheritsFrom(rootSymbol.parent, parent, cache))) {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
const result: Symbol[] = [];
|
||||
getPropertySymbolsFromBaseTypes(rootSymbol.parent, rootSymbol.getName(), result, /*previousIterationSymbolsCache*/ createMap<Symbol>());
|
||||
return forEach(result, s => searchSymbols.indexOf(s) >= 0 ? s : undefined);
|
||||
@@ -1035,7 +1267,55 @@ namespace ts.FindAllReferences {
|
||||
return referenceEntries;
|
||||
}
|
||||
|
||||
function getReferenceEntryFromNode(node: Node): ReferenceEntry {
|
||||
function isImplementation(node: Node): boolean {
|
||||
if (!node) {
|
||||
return false;
|
||||
}
|
||||
else if (isVariableLike(node)) {
|
||||
if (node.initializer) {
|
||||
return true;
|
||||
}
|
||||
else if (node.kind === SyntaxKind.VariableDeclaration) {
|
||||
const parentStatement = getParentStatementOfVariableDeclaration(<VariableDeclaration>node);
|
||||
return parentStatement && hasModifier(parentStatement, ModifierFlags.Ambient);
|
||||
}
|
||||
}
|
||||
else if (isFunctionLike(node)) {
|
||||
return !!node.body || hasModifier(node, ModifierFlags.Ambient);
|
||||
}
|
||||
else {
|
||||
switch (node.kind) {
|
||||
case SyntaxKind.ClassDeclaration:
|
||||
case SyntaxKind.ClassExpression:
|
||||
case SyntaxKind.EnumDeclaration:
|
||||
case SyntaxKind.ModuleDeclaration:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function getParentStatementOfVariableDeclaration(node: VariableDeclaration): VariableStatement {
|
||||
if (node.parent && node.parent.parent && node.parent.parent.kind === SyntaxKind.VariableStatement) {
|
||||
Debug.assert(node.parent.kind === SyntaxKind.VariableDeclarationList);
|
||||
return <VariableStatement>node.parent.parent;
|
||||
}
|
||||
}
|
||||
|
||||
export function getReferenceEntriesForShorthandPropertyAssignment(node: Node, typeChecker: TypeChecker, result: ReferenceEntry[]): void {
|
||||
const refSymbol = typeChecker.getSymbolAtLocation(node);
|
||||
const shorthandSymbol = typeChecker.getShorthandAssignmentValueSymbol(refSymbol.valueDeclaration);
|
||||
|
||||
if (shorthandSymbol) {
|
||||
for (const declaration of shorthandSymbol.getDeclarations()) {
|
||||
if (getMeaningFromDeclaration(declaration) & SemanticMeaning.Value) {
|
||||
result.push(getReferenceEntryFromNode(declaration));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function getReferenceEntryFromNode(node: Node): ReferenceEntry {
|
||||
let start = node.getStart();
|
||||
let end = node.getEnd();
|
||||
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
/* @internal */
|
||||
namespace ts.GoToImplementation {
|
||||
export function getImplementationAtPosition(typeChecker: TypeChecker, cancellationToken: CancellationToken, sourceFiles: SourceFile[], node: Node): ImplementationLocation[] {
|
||||
// If invoked directly on a shorthand property assignment, then return
|
||||
// the declaration of the symbol being assigned (not the symbol being assigned to).
|
||||
if (node.parent.kind === SyntaxKind.ShorthandPropertyAssignment) {
|
||||
const result: ReferenceEntry[] = [];
|
||||
FindAllReferences.getReferenceEntriesForShorthandPropertyAssignment(node, typeChecker, result);
|
||||
return result.length > 0 ? result : undefined;
|
||||
}
|
||||
else if (node.kind === SyntaxKind.SuperKeyword || isSuperProperty(node.parent)) {
|
||||
// References to and accesses on the super keyword only have one possible implementation, so no
|
||||
// need to "Find all References"
|
||||
const symbol = typeChecker.getSymbolAtLocation(node);
|
||||
return symbol.valueDeclaration && [FindAllReferences.getReferenceEntryFromNode(symbol.valueDeclaration)];
|
||||
}
|
||||
else {
|
||||
// Perform "Find all References" and retrieve only those that are implementations
|
||||
const referencedSymbols = FindAllReferences.getReferencedSymbolsForNode(typeChecker, cancellationToken,
|
||||
node, sourceFiles, /*findInStrings*/false, /*findInComments*/false, /*implementations*/true);
|
||||
const result = flatMap(referencedSymbols, symbol =>
|
||||
map(symbol.references, ({ textSpan, fileName }) => ({ textSpan, fileName })));
|
||||
|
||||
return result && result.length > 0 ? result : undefined;
|
||||
}
|
||||
}
|
||||
}
|
||||
+32
-334
@@ -44,349 +44,47 @@ namespace ts.JsDoc {
|
||||
let jsDocCompletionEntries: CompletionEntry[];
|
||||
|
||||
export function getJsDocCommentsFromDeclarations(declarations: Declaration[], name: string, canUseParsedParamTagComments: boolean) {
|
||||
// Only collect doc comments from duplicate declarations once:
|
||||
// In case of a union property there might be same declaration multiple times
|
||||
// which only varies in type parameter
|
||||
// Eg. const a: Array<string> | Array<number>; a.length
|
||||
// The property length will have two declarations of property length coming
|
||||
// from Array<T> - Array<string> and Array<number>
|
||||
const documentationComment = <SymbolDisplayPart[]>[];
|
||||
const docComments = getJsDocCommentsSeparatedByNewLines();
|
||||
ts.forEach(docComments, docComment => {
|
||||
if (documentationComment.length) {
|
||||
documentationComment.push(lineBreakPart());
|
||||
forEachUnique(declarations, declaration => {
|
||||
const comments = getJSDocComments(declaration, /*checkParentVariableStatement*/ true);
|
||||
if (!comments) {
|
||||
return;
|
||||
}
|
||||
for (const comment of comments) {
|
||||
if (comment) {
|
||||
if (documentationComment.length) {
|
||||
documentationComment.push(lineBreakPart());
|
||||
}
|
||||
documentationComment.push(textPart(comment));
|
||||
}
|
||||
}
|
||||
documentationComment.push(docComment);
|
||||
});
|
||||
|
||||
return documentationComment;
|
||||
}
|
||||
|
||||
function getJsDocCommentsSeparatedByNewLines() {
|
||||
const paramTag = "@param";
|
||||
const jsDocCommentParts: SymbolDisplayPart[] = [];
|
||||
|
||||
ts.forEach(declarations, (declaration, indexOfDeclaration) => {
|
||||
// Make sure we are collecting doc comment from declaration once,
|
||||
// In case of union property there might be same declaration multiple times
|
||||
// which only varies in type parameter
|
||||
// Eg. const a: Array<string> | Array<number>; a.length
|
||||
// The property length will have two declarations of property length coming
|
||||
// from Array<T> - Array<string> and Array<number>
|
||||
if (indexOf(declarations, declaration) === indexOfDeclaration) {
|
||||
const sourceFileOfDeclaration = getSourceFileOfNode(declaration);
|
||||
// If it is parameter - try and get the jsDoc comment with @param tag from function declaration's jsDoc comments
|
||||
if (canUseParsedParamTagComments && declaration.kind === SyntaxKind.Parameter) {
|
||||
if ((declaration.parent.kind === SyntaxKind.FunctionExpression || declaration.parent.kind === SyntaxKind.ArrowFunction) &&
|
||||
declaration.parent.parent.kind === SyntaxKind.VariableDeclaration) {
|
||||
addCommentParts(declaration.parent.parent.parent, sourceFileOfDeclaration, getCleanedParamJsDocComment);
|
||||
}
|
||||
addCommentParts(declaration.parent, sourceFileOfDeclaration, getCleanedParamJsDocComment);
|
||||
}
|
||||
|
||||
// If this is left side of dotted module declaration, there is no doc comments associated with this node
|
||||
if (declaration.kind === SyntaxKind.ModuleDeclaration && (<ModuleDeclaration>declaration).body && (<ModuleDeclaration>declaration).body.kind === SyntaxKind.ModuleDeclaration) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ((declaration.kind === SyntaxKind.FunctionExpression || declaration.kind === SyntaxKind.ArrowFunction) &&
|
||||
declaration.parent.kind === SyntaxKind.VariableDeclaration) {
|
||||
addCommentParts(declaration.parent.parent, sourceFileOfDeclaration, getCleanedJsDocComment);
|
||||
}
|
||||
|
||||
// If this is dotted module name, get the doc comments from the parent
|
||||
while (declaration.kind === SyntaxKind.ModuleDeclaration && declaration.parent.kind === SyntaxKind.ModuleDeclaration) {
|
||||
declaration = <ModuleDeclaration>declaration.parent;
|
||||
}
|
||||
addCommentParts(declaration.kind === SyntaxKind.VariableDeclaration ? declaration.parent.parent : declaration,
|
||||
sourceFileOfDeclaration,
|
||||
getCleanedJsDocComment);
|
||||
|
||||
if (declaration.kind === SyntaxKind.VariableDeclaration) {
|
||||
const init = (declaration as VariableDeclaration).initializer;
|
||||
if (init && (init.kind === SyntaxKind.FunctionExpression || init.kind === SyntaxKind.ArrowFunction)) {
|
||||
// Get the cleaned js doc comment text from the initializer
|
||||
addCommentParts(init, sourceFileOfDeclaration, getCleanedJsDocComment);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return jsDocCommentParts;
|
||||
|
||||
function addCommentParts(commented: Node,
|
||||
sourceFileOfDeclaration: SourceFile,
|
||||
getCommentPart: (pos: number, end: number, file: SourceFile) => SymbolDisplayPart[]): void {
|
||||
const ranges = getJsDocCommentTextRange(commented, sourceFileOfDeclaration);
|
||||
// Get the cleaned js doc comment text from the declaration
|
||||
ts.forEach(ranges, jsDocCommentTextRange => {
|
||||
const cleanedComment = getCommentPart(jsDocCommentTextRange.pos, jsDocCommentTextRange.end, sourceFileOfDeclaration);
|
||||
if (cleanedComment) {
|
||||
addRange(jsDocCommentParts, cleanedComment);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function getJsDocCommentTextRange(node: Node, sourceFile: SourceFile): TextRange[] {
|
||||
return ts.map(getJsDocComments(node, sourceFile),
|
||||
jsDocComment => {
|
||||
return {
|
||||
pos: jsDocComment.pos + "/*".length, // Consume /* from the comment
|
||||
end: jsDocComment.end - "*/".length // Trim off comment end indicator
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
function consumeWhiteSpacesOnTheLine(pos: number, end: number, sourceFile: SourceFile, maxSpacesToRemove?: number) {
|
||||
if (maxSpacesToRemove !== undefined) {
|
||||
end = Math.min(end, pos + maxSpacesToRemove);
|
||||
}
|
||||
|
||||
for (; pos < end; pos++) {
|
||||
const ch = sourceFile.text.charCodeAt(pos);
|
||||
if (!isWhiteSpaceSingleLine(ch)) {
|
||||
return pos;
|
||||
}
|
||||
}
|
||||
|
||||
return end;
|
||||
}
|
||||
|
||||
function consumeLineBreaks(pos: number, end: number, sourceFile: SourceFile) {
|
||||
while (pos < end && isLineBreak(sourceFile.text.charCodeAt(pos))) {
|
||||
pos++;
|
||||
}
|
||||
|
||||
return pos;
|
||||
}
|
||||
|
||||
function isName(pos: number, end: number, sourceFile: SourceFile, name: string) {
|
||||
return pos + name.length < end &&
|
||||
sourceFile.text.substr(pos, name.length) === name &&
|
||||
isWhiteSpace(sourceFile.text.charCodeAt(pos + name.length));
|
||||
}
|
||||
|
||||
function isParamTag(pos: number, end: number, sourceFile: SourceFile) {
|
||||
// If it is @param tag
|
||||
return isName(pos, end, sourceFile, paramTag);
|
||||
}
|
||||
|
||||
function pushDocCommentLineText(docComments: SymbolDisplayPart[], text: string, blankLineCount: number) {
|
||||
// Add the empty lines in between texts
|
||||
while (blankLineCount) {
|
||||
blankLineCount--;
|
||||
docComments.push(textPart(""));
|
||||
}
|
||||
|
||||
docComments.push(textPart(text));
|
||||
}
|
||||
|
||||
function getCleanedJsDocComment(pos: number, end: number, sourceFile: SourceFile) {
|
||||
let spacesToRemoveAfterAsterisk: number;
|
||||
const docComments: SymbolDisplayPart[] = [];
|
||||
let blankLineCount = 0;
|
||||
let isInParamTag = false;
|
||||
|
||||
while (pos < end) {
|
||||
let docCommentTextOfLine = "";
|
||||
// First consume leading white space
|
||||
pos = consumeWhiteSpacesOnTheLine(pos, end, sourceFile);
|
||||
|
||||
// If the comment starts with '*' consume the spaces on this line
|
||||
if (pos < end && sourceFile.text.charCodeAt(pos) === CharacterCodes.asterisk) {
|
||||
const lineStartPos = pos + 1;
|
||||
pos = consumeWhiteSpacesOnTheLine(pos + 1, end, sourceFile, spacesToRemoveAfterAsterisk);
|
||||
|
||||
// Set the spaces to remove after asterisk as margin if not already set
|
||||
if (spacesToRemoveAfterAsterisk === undefined && pos < end && !isLineBreak(sourceFile.text.charCodeAt(pos))) {
|
||||
spacesToRemoveAfterAsterisk = pos - lineStartPos;
|
||||
}
|
||||
}
|
||||
else if (spacesToRemoveAfterAsterisk === undefined) {
|
||||
spacesToRemoveAfterAsterisk = 0;
|
||||
}
|
||||
|
||||
// Analyze text on this line
|
||||
while (pos < end && !isLineBreak(sourceFile.text.charCodeAt(pos))) {
|
||||
const ch = sourceFile.text.charAt(pos);
|
||||
if (ch === "@") {
|
||||
// If it is @param tag
|
||||
if (isParamTag(pos, end, sourceFile)) {
|
||||
isInParamTag = true;
|
||||
pos += paramTag.length;
|
||||
continue;
|
||||
}
|
||||
else {
|
||||
isInParamTag = false;
|
||||
}
|
||||
}
|
||||
|
||||
// Add the ch to doc text if we arent in param tag
|
||||
if (!isInParamTag) {
|
||||
docCommentTextOfLine += ch;
|
||||
}
|
||||
|
||||
// Scan next character
|
||||
pos++;
|
||||
}
|
||||
|
||||
// Continue with next line
|
||||
pos = consumeLineBreaks(pos, end, sourceFile);
|
||||
if (docCommentTextOfLine) {
|
||||
pushDocCommentLineText(docComments, docCommentTextOfLine, blankLineCount);
|
||||
blankLineCount = 0;
|
||||
}
|
||||
else if (!isInParamTag && docComments.length) {
|
||||
// This is blank line when there is text already parsed
|
||||
blankLineCount++;
|
||||
}
|
||||
}
|
||||
|
||||
return docComments;
|
||||
}
|
||||
|
||||
function getCleanedParamJsDocComment(pos: number, end: number, sourceFile: SourceFile) {
|
||||
let paramHelpStringMargin: number;
|
||||
const paramDocComments: SymbolDisplayPart[] = [];
|
||||
while (pos < end) {
|
||||
if (isParamTag(pos, end, sourceFile)) {
|
||||
let blankLineCount = 0;
|
||||
let recordedParamTag = false;
|
||||
// Consume leading spaces
|
||||
pos = consumeWhiteSpaces(pos + paramTag.length);
|
||||
if (pos >= end) {
|
||||
break;
|
||||
}
|
||||
|
||||
// Ignore type expression
|
||||
if (sourceFile.text.charCodeAt(pos) === CharacterCodes.openBrace) {
|
||||
pos++;
|
||||
for (let curlies = 1; pos < end; pos++) {
|
||||
const charCode = sourceFile.text.charCodeAt(pos);
|
||||
|
||||
// { character means we need to find another } to match the found one
|
||||
if (charCode === CharacterCodes.openBrace) {
|
||||
curlies++;
|
||||
continue;
|
||||
}
|
||||
|
||||
// } char
|
||||
if (charCode === CharacterCodes.closeBrace) {
|
||||
curlies--;
|
||||
if (curlies === 0) {
|
||||
// We do not have any more } to match the type expression is ignored completely
|
||||
pos++;
|
||||
break;
|
||||
}
|
||||
else {
|
||||
// there are more { to be matched with }
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// Found start of another tag
|
||||
if (charCode === CharacterCodes.at) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Consume white spaces
|
||||
pos = consumeWhiteSpaces(pos);
|
||||
if (pos >= end) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Parameter name
|
||||
if (isName(pos, end, sourceFile, name)) {
|
||||
// Found the parameter we are looking for consume white spaces
|
||||
pos = consumeWhiteSpaces(pos + name.length);
|
||||
if (pos >= end) {
|
||||
break;
|
||||
}
|
||||
|
||||
let paramHelpString = "";
|
||||
const firstLineParamHelpStringPos = pos;
|
||||
while (pos < end) {
|
||||
const ch = sourceFile.text.charCodeAt(pos);
|
||||
|
||||
// at line break, set this comment line text and go to next line
|
||||
if (isLineBreak(ch)) {
|
||||
if (paramHelpString) {
|
||||
pushDocCommentLineText(paramDocComments, paramHelpString, blankLineCount);
|
||||
paramHelpString = "";
|
||||
blankLineCount = 0;
|
||||
recordedParamTag = true;
|
||||
}
|
||||
else if (recordedParamTag) {
|
||||
blankLineCount++;
|
||||
}
|
||||
|
||||
// Get the pos after cleaning start of the line
|
||||
setPosForParamHelpStringOnNextLine(firstLineParamHelpStringPos);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Done scanning param help string - next tag found
|
||||
if (ch === CharacterCodes.at) {
|
||||
break;
|
||||
}
|
||||
|
||||
paramHelpString += sourceFile.text.charAt(pos);
|
||||
|
||||
// Go to next character
|
||||
pos++;
|
||||
}
|
||||
|
||||
// If there is param help text, add it top the doc comments
|
||||
if (paramHelpString) {
|
||||
pushDocCommentLineText(paramDocComments, paramHelpString, blankLineCount);
|
||||
}
|
||||
paramHelpStringMargin = undefined;
|
||||
}
|
||||
|
||||
// If this is the start of another tag, continue with the loop in search of param tag with symbol name
|
||||
if (sourceFile.text.charCodeAt(pos) === CharacterCodes.at) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// Next character
|
||||
pos++;
|
||||
}
|
||||
|
||||
return paramDocComments;
|
||||
|
||||
function consumeWhiteSpaces(pos: number) {
|
||||
while (pos < end && isWhiteSpaceSingleLine(sourceFile.text.charCodeAt(pos))) {
|
||||
pos++;
|
||||
}
|
||||
|
||||
return pos;
|
||||
}
|
||||
|
||||
function setPosForParamHelpStringOnNextLine(firstLineParamHelpStringPos: number) {
|
||||
// Get the pos after consuming line breaks
|
||||
pos = consumeLineBreaks(pos, end, sourceFile);
|
||||
if (pos >= end) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (paramHelpStringMargin === undefined) {
|
||||
paramHelpStringMargin = sourceFile.getLineAndCharacterOfPosition(firstLineParamHelpStringPos).character;
|
||||
}
|
||||
|
||||
// Now consume white spaces max
|
||||
const startOfLinePos = pos;
|
||||
pos = consumeWhiteSpacesOnTheLine(pos, end, sourceFile, paramHelpStringMargin);
|
||||
if (pos >= end) {
|
||||
return;
|
||||
}
|
||||
|
||||
const consumedSpaces = pos - startOfLinePos;
|
||||
if (consumedSpaces < paramHelpStringMargin) {
|
||||
const ch = sourceFile.text.charCodeAt(pos);
|
||||
if (ch === CharacterCodes.asterisk) {
|
||||
// Consume more spaces after asterisk
|
||||
pos = consumeWhiteSpacesOnTheLine(pos + 1, end, sourceFile, paramHelpStringMargin - consumedSpaces - 1);
|
||||
}
|
||||
/**
|
||||
* Iterates through 'array' by index and performs the callback on each element of array until the callback
|
||||
* returns a truthy value, then returns that value.
|
||||
* If no such value is found, the callback is applied to each element of array and undefined is returned.
|
||||
*/
|
||||
function forEachUnique<T, U>(array: T[], callback: (element: T, index: number) => U): U {
|
||||
if (array) {
|
||||
for (let i = 0, len = array.length; i < len; i++) {
|
||||
if (indexOf(array, array[i]) === i) {
|
||||
const result = callback(array[i], i);
|
||||
if (result) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
export function getAllJsDocCompletionEntries(): CompletionEntry[] {
|
||||
|
||||
@@ -218,15 +218,13 @@ namespace ts.NavigationBar {
|
||||
break;
|
||||
|
||||
default:
|
||||
if (node.jsDocComments) {
|
||||
for (const jsDocComment of node.jsDocComments) {
|
||||
for (const tag of jsDocComment.tags) {
|
||||
if (tag.kind === SyntaxKind.JSDocTypedefTag) {
|
||||
addLeafNode(tag);
|
||||
}
|
||||
forEach(node.jsDocComments, jsDocComment => {
|
||||
forEach(jsDocComment.tags, tag => {
|
||||
if (tag.kind === SyntaxKind.JSDocTypedefTag) {
|
||||
addLeafNode(tag);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
forEachChild(node, addChildrenRecursively);
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
/// <reference path='documentRegistry.ts' />
|
||||
/// <reference path='findAllReferences.ts' />
|
||||
/// <reference path='goToDefinition.ts' />
|
||||
/// <reference path='goToImplementation.ts' />
|
||||
/// <reference path='jsDoc.ts' />
|
||||
/// <reference path='jsTyping.ts' />
|
||||
/// <reference path='navigateTo.ts' />
|
||||
@@ -42,7 +43,7 @@ namespace ts {
|
||||
public end: number;
|
||||
public flags: NodeFlags;
|
||||
public parent: Node;
|
||||
public jsDocComments: JSDocComment[];
|
||||
public jsDocComments: JSDoc[];
|
||||
public original: Node;
|
||||
public transformFlags: TransformFlags;
|
||||
public excludeTransformFlags: TransformFlags;
|
||||
@@ -215,7 +216,7 @@ namespace ts {
|
||||
public end: number;
|
||||
public flags: NodeFlags;
|
||||
public parent: Node;
|
||||
public jsDocComments: JSDocComment[];
|
||||
public jsDocComments: JSDoc[];
|
||||
public __tokenTag: any;
|
||||
|
||||
constructor(pos: number, end: number) {
|
||||
@@ -1271,6 +1272,13 @@ namespace ts {
|
||||
return GoToDefinition.getDefinitionAtPosition(program, getValidSourceFile(fileName), position);
|
||||
}
|
||||
|
||||
/// Goto implementation
|
||||
function getImplementationAtPosition(fileName: string, position: number): ImplementationLocation[] {
|
||||
synchronizeHostData();
|
||||
return GoToImplementation.getImplementationAtPosition(program.getTypeChecker(), cancellationToken,
|
||||
program.getSourceFiles(), getTouchingPropertyName(getValidSourceFile(fileName), position));
|
||||
}
|
||||
|
||||
function getTypeDefinitionAtPosition(fileName: string, position: number): DefinitionInfo[] {
|
||||
synchronizeHostData();
|
||||
return GoToDefinition.getTypeDefinitionAtPosition(program.getTypeChecker(), getValidSourceFile(fileName), position);
|
||||
@@ -1393,6 +1401,10 @@ namespace ts {
|
||||
return syntaxTreeCache.getCurrentSourceFile(fileName);
|
||||
}
|
||||
|
||||
function getSourceFile(fileName: string): SourceFile {
|
||||
return getNonBoundSourceFile(fileName);
|
||||
}
|
||||
|
||||
function getNameOrDottedNameSpan(fileName: string, startPos: number, endPos: number): TextSpan {
|
||||
const sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName);
|
||||
|
||||
@@ -1781,6 +1793,7 @@ namespace ts {
|
||||
getSignatureHelpItems,
|
||||
getQuickInfoAtPosition,
|
||||
getDefinitionAtPosition,
|
||||
getImplementationAtPosition,
|
||||
getTypeDefinitionAtPosition,
|
||||
getReferencesAtPosition,
|
||||
findReferences,
|
||||
@@ -1803,6 +1816,7 @@ namespace ts {
|
||||
isValidBraceCompletionAtPosition,
|
||||
getEmitOutput,
|
||||
getNonBoundSourceFile,
|
||||
getSourceFile,
|
||||
getProgram
|
||||
};
|
||||
}
|
||||
|
||||
@@ -177,6 +177,12 @@ namespace ts {
|
||||
*/
|
||||
getTypeDefinitionAtPosition(fileName: string, position: number): string;
|
||||
|
||||
/**
|
||||
* Returns a JSON-encoded value of the type:
|
||||
* { fileName: string; textSpan: { start: number; length: number}; }[]
|
||||
*/
|
||||
getImplementationAtPosition(fileName: string, position: number): string;
|
||||
|
||||
/**
|
||||
* Returns a JSON-encoded value of the type:
|
||||
* { fileName: string; textSpan: { start: number; length: number}; isWriteAccess: boolean, isDefinition?: boolean }[]
|
||||
@@ -798,6 +804,19 @@ namespace ts {
|
||||
);
|
||||
}
|
||||
|
||||
/// GOTO Implementation
|
||||
|
||||
/**
|
||||
* Computes the implementation location of the symbol
|
||||
* at the requested position.
|
||||
*/
|
||||
public getImplementationAtPosition(fileName: string, position: number): string {
|
||||
return this.forwardJSONCall(
|
||||
`getImplementationAtPosition('${fileName}', ${position})`,
|
||||
() => this.languageService.getImplementationAtPosition(fileName, position)
|
||||
);
|
||||
}
|
||||
|
||||
public getRenameInfo(fileName: string, position: number): string {
|
||||
return this.forwardJSONCall(
|
||||
`getRenameInfo('${fileName}', ${position})`,
|
||||
|
||||
@@ -49,6 +49,7 @@
|
||||
"documentRegistry.ts",
|
||||
"findAllReferences.ts",
|
||||
"goToDefinition.ts",
|
||||
"goToImplementation.ts",
|
||||
"jsDoc.ts",
|
||||
"jsTyping.ts",
|
||||
"navigateTo.ts",
|
||||
|
||||
@@ -209,6 +209,7 @@ namespace ts {
|
||||
|
||||
getDefinitionAtPosition(fileName: string, position: number): DefinitionInfo[];
|
||||
getTypeDefinitionAtPosition(fileName: string, position: number): DefinitionInfo[];
|
||||
getImplementationAtPosition(fileName: string, position: number): ImplementationLocation[];
|
||||
|
||||
getReferencesAtPosition(fileName: string, position: number): ReferenceEntry[];
|
||||
findReferences(fileName: string, position: number): ReferencedSymbol[];
|
||||
@@ -239,6 +240,12 @@ namespace ts {
|
||||
|
||||
/* @internal */ getNonBoundSourceFile(fileName: string): SourceFile;
|
||||
|
||||
/**
|
||||
* @internal
|
||||
* @deprecated Use ts.createSourceFile instead.
|
||||
*/
|
||||
getSourceFile(fileName: string): SourceFile;
|
||||
|
||||
dispose(): void;
|
||||
}
|
||||
|
||||
@@ -297,6 +304,11 @@ namespace ts {
|
||||
isDefinition: boolean;
|
||||
}
|
||||
|
||||
export interface ImplementationLocation {
|
||||
textSpan: TextSpan;
|
||||
fileName: string;
|
||||
}
|
||||
|
||||
export interface DocumentHighlights {
|
||||
fileName: string;
|
||||
highlightSpans: HighlightSpan[];
|
||||
|
||||
@@ -953,9 +953,11 @@ namespace ts {
|
||||
if (node) {
|
||||
if (node.jsDocComments) {
|
||||
for (const jsDocComment of node.jsDocComments) {
|
||||
for (const tag of jsDocComment.tags) {
|
||||
if (tag.pos <= position && position <= tag.end) {
|
||||
return tag;
|
||||
if (jsDocComment.tags) {
|
||||
for (const tag of jsDocComment.tags) {
|
||||
if (tag.pos <= position && position <= tag.end) {
|
||||
return tag;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1353,4 +1355,4 @@ namespace ts {
|
||||
}
|
||||
return { configJsonObject, diagnostics };
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"kind": "JSDocComment",
|
||||
"pos": 0,
|
||||
"end": 23,
|
||||
"comment": "* @type {number} "
|
||||
}
|
||||
+2
-1
@@ -27,7 +27,8 @@
|
||||
"pos": 15,
|
||||
"end": 21
|
||||
}
|
||||
}
|
||||
},
|
||||
"comment": ""
|
||||
},
|
||||
"length": 1,
|
||||
"pos": 8,
|
||||
|
||||
+2
-1
@@ -27,7 +27,8 @@
|
||||
"pos": 15,
|
||||
"end": 21
|
||||
}
|
||||
}
|
||||
},
|
||||
"comment": ""
|
||||
},
|
||||
"length": 1,
|
||||
"pos": 8,
|
||||
|
||||
+4
-3
@@ -6,7 +6,7 @@
|
||||
"0": {
|
||||
"kind": "JSDocReturnTag",
|
||||
"pos": 8,
|
||||
"end": 15,
|
||||
"end": 16,
|
||||
"atToken": {
|
||||
"kind": "AtToken",
|
||||
"pos": 8,
|
||||
@@ -17,10 +17,11 @@
|
||||
"pos": 9,
|
||||
"end": 15,
|
||||
"text": "return"
|
||||
}
|
||||
},
|
||||
"comment": ""
|
||||
},
|
||||
"length": 1,
|
||||
"pos": 8,
|
||||
"end": 15
|
||||
"end": 16
|
||||
}
|
||||
}
|
||||
@@ -6,7 +6,7 @@
|
||||
"0": {
|
||||
"kind": "JSDocTypeTag",
|
||||
"pos": 8,
|
||||
"end": 13,
|
||||
"end": 14,
|
||||
"atToken": {
|
||||
"kind": "AtToken",
|
||||
"pos": 8,
|
||||
@@ -17,10 +17,11 @@
|
||||
"pos": 9,
|
||||
"end": 13,
|
||||
"text": "type"
|
||||
}
|
||||
},
|
||||
"comment": ""
|
||||
},
|
||||
"length": 1,
|
||||
"pos": 8,
|
||||
"end": 13
|
||||
"end": 14
|
||||
}
|
||||
}
|
||||
@@ -33,7 +33,14 @@
|
||||
"pos": 24,
|
||||
"end": 29,
|
||||
"text": "name1"
|
||||
}
|
||||
},
|
||||
"parameterName": {
|
||||
"kind": "Identifier",
|
||||
"pos": 24,
|
||||
"end": 29,
|
||||
"text": "name1"
|
||||
},
|
||||
"comment": ""
|
||||
},
|
||||
"length": 1,
|
||||
"pos": 8,
|
||||
|
||||
@@ -33,7 +33,14 @@
|
||||
"pos": 24,
|
||||
"end": 29,
|
||||
"text": "name1"
|
||||
}
|
||||
},
|
||||
"parameterName": {
|
||||
"kind": "Identifier",
|
||||
"pos": 24,
|
||||
"end": 29,
|
||||
"text": "name1"
|
||||
},
|
||||
"comment": "Description text follows"
|
||||
},
|
||||
"length": 1,
|
||||
"pos": 8,
|
||||
|
||||
+8
-1
@@ -34,7 +34,14 @@
|
||||
"end": 30,
|
||||
"text": "name1"
|
||||
},
|
||||
"isBracketed": true
|
||||
"parameterName": {
|
||||
"kind": "Identifier",
|
||||
"pos": 25,
|
||||
"end": 30,
|
||||
"text": "name1"
|
||||
},
|
||||
"isBracketed": true,
|
||||
"comment": "Description text follows"
|
||||
},
|
||||
"length": 1,
|
||||
"pos": 8,
|
||||
|
||||
+8
-1
@@ -34,7 +34,14 @@
|
||||
"end": 31,
|
||||
"text": "name1"
|
||||
},
|
||||
"isBracketed": true
|
||||
"parameterName": {
|
||||
"kind": "Identifier",
|
||||
"pos": 26,
|
||||
"end": 31,
|
||||
"text": "name1"
|
||||
},
|
||||
"isBracketed": true,
|
||||
"comment": "Description text follows"
|
||||
},
|
||||
"length": 1,
|
||||
"pos": 8,
|
||||
|
||||
+8
-1
@@ -33,7 +33,14 @@
|
||||
"pos": 22,
|
||||
"end": 28
|
||||
}
|
||||
}
|
||||
},
|
||||
"parameterName": {
|
||||
"kind": "Identifier",
|
||||
"pos": 15,
|
||||
"end": 20,
|
||||
"text": "name1"
|
||||
},
|
||||
"comment": ""
|
||||
},
|
||||
"length": 1,
|
||||
"pos": 8,
|
||||
|
||||
+8
-1
@@ -33,7 +33,14 @@
|
||||
"pos": 22,
|
||||
"end": 28
|
||||
}
|
||||
}
|
||||
},
|
||||
"parameterName": {
|
||||
"kind": "Identifier",
|
||||
"pos": 15,
|
||||
"end": 20,
|
||||
"text": "name1"
|
||||
},
|
||||
"comment": "Description"
|
||||
},
|
||||
"length": 1,
|
||||
"pos": 8,
|
||||
|
||||
+8
-1
@@ -23,7 +23,14 @@
|
||||
"pos": 15,
|
||||
"end": 18,
|
||||
"text": "foo"
|
||||
}
|
||||
},
|
||||
"parameterName": {
|
||||
"kind": "Identifier",
|
||||
"pos": 15,
|
||||
"end": 18,
|
||||
"text": "foo"
|
||||
},
|
||||
"comment": ""
|
||||
},
|
||||
"length": 1,
|
||||
"pos": 8,
|
||||
|
||||
@@ -27,7 +27,8 @@
|
||||
"pos": 17,
|
||||
"end": 23
|
||||
}
|
||||
}
|
||||
},
|
||||
"comment": ""
|
||||
},
|
||||
"length": 1,
|
||||
"pos": 8,
|
||||
|
||||
@@ -27,7 +27,8 @@
|
||||
"pos": 17,
|
||||
"end": 23
|
||||
}
|
||||
}
|
||||
},
|
||||
"comment": "Description text follows"
|
||||
},
|
||||
"length": 1,
|
||||
"pos": 8,
|
||||
|
||||
@@ -27,7 +27,8 @@
|
||||
"pos": 18,
|
||||
"end": 24
|
||||
}
|
||||
}
|
||||
},
|
||||
"comment": ""
|
||||
},
|
||||
"length": 1,
|
||||
"pos": 8,
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
"0": {
|
||||
"kind": "JSDocTemplateTag",
|
||||
"pos": 8,
|
||||
"end": 19,
|
||||
"end": 20,
|
||||
"atToken": {
|
||||
"kind": "AtToken",
|
||||
"pos": 8,
|
||||
@@ -22,7 +22,7 @@
|
||||
"0": {
|
||||
"kind": "TypeParameter",
|
||||
"pos": 18,
|
||||
"end": 19,
|
||||
"end": 20,
|
||||
"name": {
|
||||
"kind": "Identifier",
|
||||
"pos": 18,
|
||||
@@ -31,12 +31,13 @@
|
||||
}
|
||||
},
|
||||
"length": 1,
|
||||
"pos": 17,
|
||||
"end": 19
|
||||
}
|
||||
"pos": 18,
|
||||
"end": 20
|
||||
},
|
||||
"comment": ""
|
||||
},
|
||||
"length": 1,
|
||||
"pos": 8,
|
||||
"end": 19
|
||||
"end": 20
|
||||
}
|
||||
}
|
||||
+7
-6
@@ -6,7 +6,7 @@
|
||||
"0": {
|
||||
"kind": "JSDocTemplateTag",
|
||||
"pos": 8,
|
||||
"end": 21,
|
||||
"end": 22,
|
||||
"atToken": {
|
||||
"kind": "AtToken",
|
||||
"pos": 8,
|
||||
@@ -33,7 +33,7 @@
|
||||
"1": {
|
||||
"kind": "TypeParameter",
|
||||
"pos": 20,
|
||||
"end": 21,
|
||||
"end": 22,
|
||||
"name": {
|
||||
"kind": "Identifier",
|
||||
"pos": 20,
|
||||
@@ -42,12 +42,13 @@
|
||||
}
|
||||
},
|
||||
"length": 2,
|
||||
"pos": 17,
|
||||
"end": 21
|
||||
}
|
||||
"pos": 18,
|
||||
"end": 22
|
||||
},
|
||||
"comment": ""
|
||||
},
|
||||
"length": 1,
|
||||
"pos": 8,
|
||||
"end": 21
|
||||
"end": 22
|
||||
}
|
||||
}
|
||||
+8
-7
@@ -6,7 +6,7 @@
|
||||
"0": {
|
||||
"kind": "JSDocTemplateTag",
|
||||
"pos": 8,
|
||||
"end": 22,
|
||||
"end": 23,
|
||||
"atToken": {
|
||||
"kind": "AtToken",
|
||||
"pos": 8,
|
||||
@@ -22,7 +22,7 @@
|
||||
"0": {
|
||||
"kind": "TypeParameter",
|
||||
"pos": 18,
|
||||
"end": 19,
|
||||
"end": 20,
|
||||
"name": {
|
||||
"kind": "Identifier",
|
||||
"pos": 18,
|
||||
@@ -33,7 +33,7 @@
|
||||
"1": {
|
||||
"kind": "TypeParameter",
|
||||
"pos": 21,
|
||||
"end": 22,
|
||||
"end": 23,
|
||||
"name": {
|
||||
"kind": "Identifier",
|
||||
"pos": 21,
|
||||
@@ -42,12 +42,13 @@
|
||||
}
|
||||
},
|
||||
"length": 2,
|
||||
"pos": 17,
|
||||
"end": 22
|
||||
}
|
||||
"pos": 18,
|
||||
"end": 23
|
||||
},
|
||||
"comment": ""
|
||||
},
|
||||
"length": 1,
|
||||
"pos": 8,
|
||||
"end": 22
|
||||
"end": 23
|
||||
}
|
||||
}
|
||||
+7
-6
@@ -6,7 +6,7 @@
|
||||
"0": {
|
||||
"kind": "JSDocTemplateTag",
|
||||
"pos": 8,
|
||||
"end": 22,
|
||||
"end": 23,
|
||||
"atToken": {
|
||||
"kind": "AtToken",
|
||||
"pos": 8,
|
||||
@@ -33,7 +33,7 @@
|
||||
"1": {
|
||||
"kind": "TypeParameter",
|
||||
"pos": 21,
|
||||
"end": 22,
|
||||
"end": 23,
|
||||
"name": {
|
||||
"kind": "Identifier",
|
||||
"pos": 21,
|
||||
@@ -42,12 +42,13 @@
|
||||
}
|
||||
},
|
||||
"length": 2,
|
||||
"pos": 17,
|
||||
"end": 22
|
||||
}
|
||||
"pos": 18,
|
||||
"end": 23
|
||||
},
|
||||
"comment": ""
|
||||
},
|
||||
"length": 1,
|
||||
"pos": 8,
|
||||
"end": 22
|
||||
"end": 23
|
||||
}
|
||||
}
|
||||
+8
-7
@@ -6,7 +6,7 @@
|
||||
"0": {
|
||||
"kind": "JSDocTemplateTag",
|
||||
"pos": 8,
|
||||
"end": 23,
|
||||
"end": 24,
|
||||
"atToken": {
|
||||
"kind": "AtToken",
|
||||
"pos": 8,
|
||||
@@ -22,7 +22,7 @@
|
||||
"0": {
|
||||
"kind": "TypeParameter",
|
||||
"pos": 18,
|
||||
"end": 19,
|
||||
"end": 20,
|
||||
"name": {
|
||||
"kind": "Identifier",
|
||||
"pos": 18,
|
||||
@@ -33,7 +33,7 @@
|
||||
"1": {
|
||||
"kind": "TypeParameter",
|
||||
"pos": 22,
|
||||
"end": 23,
|
||||
"end": 24,
|
||||
"name": {
|
||||
"kind": "Identifier",
|
||||
"pos": 22,
|
||||
@@ -42,12 +42,13 @@
|
||||
}
|
||||
},
|
||||
"length": 2,
|
||||
"pos": 17,
|
||||
"end": 23
|
||||
}
|
||||
"pos": 18,
|
||||
"end": 24
|
||||
},
|
||||
"comment": ""
|
||||
},
|
||||
"length": 1,
|
||||
"pos": 8,
|
||||
"end": 23
|
||||
"end": 24
|
||||
}
|
||||
}
|
||||
+8
-7
@@ -6,7 +6,7 @@
|
||||
"0": {
|
||||
"kind": "JSDocTemplateTag",
|
||||
"pos": 8,
|
||||
"end": 23,
|
||||
"end": 24,
|
||||
"atToken": {
|
||||
"kind": "AtToken",
|
||||
"pos": 8,
|
||||
@@ -22,7 +22,7 @@
|
||||
"0": {
|
||||
"kind": "TypeParameter",
|
||||
"pos": 18,
|
||||
"end": 19,
|
||||
"end": 20,
|
||||
"name": {
|
||||
"kind": "Identifier",
|
||||
"pos": 18,
|
||||
@@ -33,7 +33,7 @@
|
||||
"1": {
|
||||
"kind": "TypeParameter",
|
||||
"pos": 22,
|
||||
"end": 23,
|
||||
"end": 24,
|
||||
"name": {
|
||||
"kind": "Identifier",
|
||||
"pos": 22,
|
||||
@@ -42,12 +42,13 @@
|
||||
}
|
||||
},
|
||||
"length": 2,
|
||||
"pos": 17,
|
||||
"end": 23
|
||||
}
|
||||
"pos": 18,
|
||||
"end": 24
|
||||
},
|
||||
"comment": "Description of type parameters."
|
||||
},
|
||||
"length": 1,
|
||||
"pos": 8,
|
||||
"end": 23
|
||||
"end": 24
|
||||
}
|
||||
}
|
||||
+16
-2
@@ -33,7 +33,14 @@
|
||||
"pos": 24,
|
||||
"end": 29,
|
||||
"text": "name1"
|
||||
}
|
||||
},
|
||||
"parameterName": {
|
||||
"kind": "Identifier",
|
||||
"pos": 24,
|
||||
"end": 29,
|
||||
"text": "name1"
|
||||
},
|
||||
"comment": ""
|
||||
},
|
||||
"1": {
|
||||
"kind": "JSDocParameterTag",
|
||||
@@ -65,7 +72,14 @@
|
||||
"pos": 50,
|
||||
"end": 55,
|
||||
"text": "name2"
|
||||
}
|
||||
},
|
||||
"parameterName": {
|
||||
"kind": "Identifier",
|
||||
"pos": 50,
|
||||
"end": 55,
|
||||
"text": "name2"
|
||||
},
|
||||
"comment": ""
|
||||
},
|
||||
"length": 2,
|
||||
"pos": 8,
|
||||
|
||||
+49
-3
@@ -33,10 +33,56 @@
|
||||
"pos": 24,
|
||||
"end": 29,
|
||||
"text": "name1"
|
||||
}
|
||||
},
|
||||
"parameterName": {
|
||||
"kind": "Identifier",
|
||||
"pos": 24,
|
||||
"end": 29,
|
||||
"text": "name1"
|
||||
},
|
||||
"comment": ""
|
||||
},
|
||||
"length": 1,
|
||||
"1": {
|
||||
"kind": "JSDocParameterTag",
|
||||
"pos": 30,
|
||||
"end": 51,
|
||||
"atToken": {
|
||||
"kind": "AtToken",
|
||||
"pos": 30,
|
||||
"end": 31
|
||||
},
|
||||
"tagName": {
|
||||
"kind": "Identifier",
|
||||
"pos": 31,
|
||||
"end": 36,
|
||||
"text": "param"
|
||||
},
|
||||
"typeExpression": {
|
||||
"kind": "JSDocTypeExpression",
|
||||
"pos": 37,
|
||||
"end": 45,
|
||||
"type": {
|
||||
"kind": "NumberKeyword",
|
||||
"pos": 38,
|
||||
"end": 44
|
||||
}
|
||||
},
|
||||
"postParameterName": {
|
||||
"kind": "Identifier",
|
||||
"pos": 46,
|
||||
"end": 51,
|
||||
"text": "name2"
|
||||
},
|
||||
"parameterName": {
|
||||
"kind": "Identifier",
|
||||
"pos": 46,
|
||||
"end": 51,
|
||||
"text": "name2"
|
||||
},
|
||||
"comment": ""
|
||||
},
|
||||
"length": 2,
|
||||
"pos": 8,
|
||||
"end": 29
|
||||
"end": 51
|
||||
}
|
||||
}
|
||||
@@ -27,7 +27,8 @@
|
||||
"pos": 15,
|
||||
"end": 21
|
||||
}
|
||||
}
|
||||
},
|
||||
"comment": ""
|
||||
},
|
||||
"length": 1,
|
||||
"pos": 8,
|
||||
|
||||
+14
-13
@@ -6,7 +6,7 @@
|
||||
"0": {
|
||||
"kind": "JSDocTypedefTag",
|
||||
"pos": 8,
|
||||
"end": 97,
|
||||
"end": 98,
|
||||
"atToken": {
|
||||
"kind": "AtToken",
|
||||
"pos": 8,
|
||||
@@ -26,15 +26,15 @@
|
||||
},
|
||||
"jsDocTypeLiteral": {
|
||||
"kind": "JSDocTypeLiteral",
|
||||
"pos": 23,
|
||||
"end": 97,
|
||||
"pos": 26,
|
||||
"end": 98,
|
||||
"jsDocTypeTag": {
|
||||
"kind": "JSDocTypeTag",
|
||||
"pos": 27,
|
||||
"pos": 28,
|
||||
"end": 42,
|
||||
"atToken": {
|
||||
"kind": "AtToken",
|
||||
"pos": 27,
|
||||
"pos": 28,
|
||||
"end": 29
|
||||
},
|
||||
"tagName": {
|
||||
@@ -63,11 +63,11 @@
|
||||
"jsDocPropertyTags": [
|
||||
{
|
||||
"kind": "JSDocPropertyTag",
|
||||
"pos": 46,
|
||||
"end": 69,
|
||||
"pos": 47,
|
||||
"end": 72,
|
||||
"atToken": {
|
||||
"kind": "AtToken",
|
||||
"pos": 46,
|
||||
"pos": 47,
|
||||
"end": 48
|
||||
},
|
||||
"tagName": {
|
||||
@@ -95,11 +95,11 @@
|
||||
},
|
||||
{
|
||||
"kind": "JSDocPropertyTag",
|
||||
"pos": 73,
|
||||
"end": 97,
|
||||
"pos": 74,
|
||||
"end": 98,
|
||||
"atToken": {
|
||||
"kind": "AtToken",
|
||||
"pos": 73,
|
||||
"pos": 74,
|
||||
"end": 75
|
||||
},
|
||||
"tagName": {
|
||||
@@ -126,10 +126,11 @@
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"comment": ""
|
||||
},
|
||||
"length": 1,
|
||||
"pos": 8,
|
||||
"end": 97
|
||||
"end": 98
|
||||
}
|
||||
}
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
{
|
||||
"kind": "JSDocRecordType",
|
||||
"pos": 1,
|
||||
"end": 13,
|
||||
"literal": {
|
||||
"kind": "TypeLiteral",
|
||||
"pos": 1,
|
||||
"end": 13,
|
||||
"members": {
|
||||
"0": {
|
||||
"kind": "CallSignature",
|
||||
"pos": 2,
|
||||
"end": 12,
|
||||
"parameters": {
|
||||
"length": 0,
|
||||
"pos": 3,
|
||||
"end": 3
|
||||
},
|
||||
"type": {
|
||||
"kind": "NumberKeyword",
|
||||
"pos": 5,
|
||||
"end": 12
|
||||
}
|
||||
},
|
||||
"length": 1,
|
||||
"pos": 2,
|
||||
"end": 12
|
||||
}
|
||||
}
|
||||
}
|
||||
+36
@@ -0,0 +1,36 @@
|
||||
{
|
||||
"kind": "JSDocRecordType",
|
||||
"pos": 1,
|
||||
"end": 16,
|
||||
"literal": {
|
||||
"kind": "TypeLiteral",
|
||||
"pos": 1,
|
||||
"end": 16,
|
||||
"members": {
|
||||
"0": {
|
||||
"kind": "MethodSignature",
|
||||
"pos": 2,
|
||||
"end": 15,
|
||||
"name": {
|
||||
"kind": "Identifier",
|
||||
"pos": 2,
|
||||
"end": 5,
|
||||
"text": "foo"
|
||||
},
|
||||
"parameters": {
|
||||
"length": 0,
|
||||
"pos": 6,
|
||||
"end": 6
|
||||
},
|
||||
"type": {
|
||||
"kind": "NumberKeyword",
|
||||
"pos": 8,
|
||||
"end": 15
|
||||
}
|
||||
},
|
||||
"length": 1,
|
||||
"pos": 2,
|
||||
"end": 15
|
||||
}
|
||||
}
|
||||
}
|
||||
+9
-4
@@ -2,9 +2,14 @@
|
||||
"kind": "JSDocRecordType",
|
||||
"pos": 1,
|
||||
"end": 3,
|
||||
"members": {
|
||||
"length": 0,
|
||||
"pos": 2,
|
||||
"end": 2
|
||||
"literal": {
|
||||
"kind": "TypeLiteral",
|
||||
"pos": 1,
|
||||
"end": 3,
|
||||
"members": {
|
||||
"length": 0,
|
||||
"pos": 2,
|
||||
"end": 2
|
||||
}
|
||||
}
|
||||
}
|
||||
+18
-13
@@ -2,20 +2,25 @@
|
||||
"kind": "JSDocRecordType",
|
||||
"pos": 1,
|
||||
"end": 6,
|
||||
"members": {
|
||||
"0": {
|
||||
"kind": "JSDocRecordMember",
|
||||
"pos": 2,
|
||||
"end": 5,
|
||||
"name": {
|
||||
"kind": "Identifier",
|
||||
"literal": {
|
||||
"kind": "TypeLiteral",
|
||||
"pos": 1,
|
||||
"end": 6,
|
||||
"members": {
|
||||
"0": {
|
||||
"kind": "PropertySignature",
|
||||
"pos": 2,
|
||||
"end": 5,
|
||||
"text": "foo"
|
||||
}
|
||||
},
|
||||
"length": 1,
|
||||
"pos": 2,
|
||||
"end": 5
|
||||
"name": {
|
||||
"kind": "Identifier",
|
||||
"pos": 2,
|
||||
"end": 5,
|
||||
"text": "foo"
|
||||
}
|
||||
},
|
||||
"length": 1,
|
||||
"pos": 2,
|
||||
"end": 5
|
||||
}
|
||||
}
|
||||
}
|
||||
+23
-18
@@ -2,25 +2,30 @@
|
||||
"kind": "JSDocRecordType",
|
||||
"pos": 1,
|
||||
"end": 14,
|
||||
"members": {
|
||||
"0": {
|
||||
"kind": "JSDocRecordMember",
|
||||
"pos": 2,
|
||||
"end": 13,
|
||||
"name": {
|
||||
"kind": "Identifier",
|
||||
"literal": {
|
||||
"kind": "TypeLiteral",
|
||||
"pos": 1,
|
||||
"end": 14,
|
||||
"members": {
|
||||
"0": {
|
||||
"kind": "PropertySignature",
|
||||
"pos": 2,
|
||||
"end": 5,
|
||||
"text": "foo"
|
||||
"end": 13,
|
||||
"name": {
|
||||
"kind": "Identifier",
|
||||
"pos": 2,
|
||||
"end": 5,
|
||||
"text": "foo"
|
||||
},
|
||||
"type": {
|
||||
"kind": "NumberKeyword",
|
||||
"pos": 6,
|
||||
"end": 13
|
||||
}
|
||||
},
|
||||
"type": {
|
||||
"kind": "NumberKeyword",
|
||||
"pos": 6,
|
||||
"end": 13
|
||||
}
|
||||
},
|
||||
"length": 1,
|
||||
"pos": 2,
|
||||
"end": 13
|
||||
"length": 1,
|
||||
"pos": 2,
|
||||
"end": 13
|
||||
}
|
||||
}
|
||||
}
|
||||
+28
-23
@@ -2,31 +2,36 @@
|
||||
"kind": "JSDocRecordType",
|
||||
"pos": 1,
|
||||
"end": 11,
|
||||
"members": {
|
||||
"0": {
|
||||
"kind": "JSDocRecordMember",
|
||||
"pos": 2,
|
||||
"end": 5,
|
||||
"name": {
|
||||
"kind": "Identifier",
|
||||
"literal": {
|
||||
"kind": "TypeLiteral",
|
||||
"pos": 1,
|
||||
"end": 11,
|
||||
"members": {
|
||||
"0": {
|
||||
"kind": "PropertySignature",
|
||||
"pos": 2,
|
||||
"end": 5,
|
||||
"text": "foo"
|
||||
}
|
||||
},
|
||||
"1": {
|
||||
"kind": "JSDocRecordMember",
|
||||
"pos": 6,
|
||||
"end": 10,
|
||||
"name": {
|
||||
"kind": "Identifier",
|
||||
"end": 6,
|
||||
"name": {
|
||||
"kind": "Identifier",
|
||||
"pos": 2,
|
||||
"end": 5,
|
||||
"text": "foo"
|
||||
}
|
||||
},
|
||||
"1": {
|
||||
"kind": "PropertySignature",
|
||||
"pos": 6,
|
||||
"end": 10,
|
||||
"text": "bar"
|
||||
}
|
||||
},
|
||||
"length": 2,
|
||||
"pos": 2,
|
||||
"end": 10
|
||||
"name": {
|
||||
"kind": "Identifier",
|
||||
"pos": 6,
|
||||
"end": 10,
|
||||
"text": "bar"
|
||||
}
|
||||
},
|
||||
"length": 2,
|
||||
"pos": 2,
|
||||
"end": 10
|
||||
}
|
||||
}
|
||||
}
|
||||
+32
-27
@@ -2,36 +2,41 @@
|
||||
"kind": "JSDocRecordType",
|
||||
"pos": 1,
|
||||
"end": 19,
|
||||
"members": {
|
||||
"0": {
|
||||
"kind": "JSDocRecordMember",
|
||||
"pos": 2,
|
||||
"end": 13,
|
||||
"name": {
|
||||
"kind": "Identifier",
|
||||
"literal": {
|
||||
"kind": "TypeLiteral",
|
||||
"pos": 1,
|
||||
"end": 19,
|
||||
"members": {
|
||||
"0": {
|
||||
"kind": "PropertySignature",
|
||||
"pos": 2,
|
||||
"end": 5,
|
||||
"text": "foo"
|
||||
"end": 14,
|
||||
"name": {
|
||||
"kind": "Identifier",
|
||||
"pos": 2,
|
||||
"end": 5,
|
||||
"text": "foo"
|
||||
},
|
||||
"type": {
|
||||
"kind": "NumberKeyword",
|
||||
"pos": 6,
|
||||
"end": 13
|
||||
}
|
||||
},
|
||||
"type": {
|
||||
"kind": "NumberKeyword",
|
||||
"pos": 6,
|
||||
"end": 13
|
||||
}
|
||||
},
|
||||
"1": {
|
||||
"kind": "JSDocRecordMember",
|
||||
"pos": 14,
|
||||
"end": 18,
|
||||
"name": {
|
||||
"kind": "Identifier",
|
||||
"1": {
|
||||
"kind": "PropertySignature",
|
||||
"pos": 14,
|
||||
"end": 18,
|
||||
"text": "bar"
|
||||
}
|
||||
},
|
||||
"length": 2,
|
||||
"pos": 2,
|
||||
"end": 18
|
||||
"name": {
|
||||
"kind": "Identifier",
|
||||
"pos": 14,
|
||||
"end": 18,
|
||||
"text": "bar"
|
||||
}
|
||||
},
|
||||
"length": 2,
|
||||
"pos": 2,
|
||||
"end": 18
|
||||
}
|
||||
}
|
||||
}
|
||||
+34
-29
@@ -2,36 +2,41 @@
|
||||
"kind": "JSDocRecordType",
|
||||
"pos": 1,
|
||||
"end": 19,
|
||||
"members": {
|
||||
"0": {
|
||||
"kind": "JSDocRecordMember",
|
||||
"pos": 2,
|
||||
"end": 5,
|
||||
"name": {
|
||||
"kind": "Identifier",
|
||||
"literal": {
|
||||
"kind": "TypeLiteral",
|
||||
"pos": 1,
|
||||
"end": 19,
|
||||
"members": {
|
||||
"0": {
|
||||
"kind": "PropertySignature",
|
||||
"pos": 2,
|
||||
"end": 5,
|
||||
"text": "foo"
|
||||
}
|
||||
},
|
||||
"1": {
|
||||
"kind": "JSDocRecordMember",
|
||||
"pos": 6,
|
||||
"end": 18,
|
||||
"name": {
|
||||
"kind": "Identifier",
|
||||
"pos": 6,
|
||||
"end": 10,
|
||||
"text": "bar"
|
||||
"end": 6,
|
||||
"name": {
|
||||
"kind": "Identifier",
|
||||
"pos": 2,
|
||||
"end": 5,
|
||||
"text": "foo"
|
||||
}
|
||||
},
|
||||
"type": {
|
||||
"kind": "NumberKeyword",
|
||||
"pos": 11,
|
||||
"end": 18
|
||||
}
|
||||
},
|
||||
"length": 2,
|
||||
"pos": 2,
|
||||
"end": 18
|
||||
"1": {
|
||||
"kind": "PropertySignature",
|
||||
"pos": 6,
|
||||
"end": 18,
|
||||
"name": {
|
||||
"kind": "Identifier",
|
||||
"pos": 6,
|
||||
"end": 10,
|
||||
"text": "bar"
|
||||
},
|
||||
"type": {
|
||||
"kind": "NumberKeyword",
|
||||
"pos": 11,
|
||||
"end": 18
|
||||
}
|
||||
},
|
||||
"length": 2,
|
||||
"pos": 2,
|
||||
"end": 18
|
||||
}
|
||||
}
|
||||
}
|
||||
+37
-32
@@ -2,41 +2,46 @@
|
||||
"kind": "JSDocRecordType",
|
||||
"pos": 1,
|
||||
"end": 27,
|
||||
"members": {
|
||||
"0": {
|
||||
"kind": "JSDocRecordMember",
|
||||
"pos": 2,
|
||||
"end": 13,
|
||||
"name": {
|
||||
"kind": "Identifier",
|
||||
"literal": {
|
||||
"kind": "TypeLiteral",
|
||||
"pos": 1,
|
||||
"end": 27,
|
||||
"members": {
|
||||
"0": {
|
||||
"kind": "PropertySignature",
|
||||
"pos": 2,
|
||||
"end": 5,
|
||||
"text": "foo"
|
||||
"end": 14,
|
||||
"name": {
|
||||
"kind": "Identifier",
|
||||
"pos": 2,
|
||||
"end": 5,
|
||||
"text": "foo"
|
||||
},
|
||||
"type": {
|
||||
"kind": "NumberKeyword",
|
||||
"pos": 6,
|
||||
"end": 13
|
||||
}
|
||||
},
|
||||
"type": {
|
||||
"kind": "NumberKeyword",
|
||||
"pos": 6,
|
||||
"end": 13
|
||||
}
|
||||
},
|
||||
"1": {
|
||||
"kind": "JSDocRecordMember",
|
||||
"pos": 14,
|
||||
"end": 26,
|
||||
"name": {
|
||||
"kind": "Identifier",
|
||||
"1": {
|
||||
"kind": "PropertySignature",
|
||||
"pos": 14,
|
||||
"end": 18,
|
||||
"text": "bar"
|
||||
"end": 26,
|
||||
"name": {
|
||||
"kind": "Identifier",
|
||||
"pos": 14,
|
||||
"end": 18,
|
||||
"text": "bar"
|
||||
},
|
||||
"type": {
|
||||
"kind": "NumberKeyword",
|
||||
"pos": 19,
|
||||
"end": 26
|
||||
}
|
||||
},
|
||||
"type": {
|
||||
"kind": "NumberKeyword",
|
||||
"pos": 19,
|
||||
"end": 26
|
||||
}
|
||||
},
|
||||
"length": 2,
|
||||
"pos": 2,
|
||||
"end": 26
|
||||
"length": 2,
|
||||
"pos": 2,
|
||||
"end": 26
|
||||
}
|
||||
}
|
||||
}
|
||||
+19
-14
@@ -2,21 +2,26 @@
|
||||
"kind": "JSDocRecordType",
|
||||
"pos": 1,
|
||||
"end": 11,
|
||||
"members": {
|
||||
"0": {
|
||||
"kind": "JSDocRecordMember",
|
||||
"pos": 2,
|
||||
"end": 10,
|
||||
"name": {
|
||||
"kind": "Identifier",
|
||||
"literal": {
|
||||
"kind": "TypeLiteral",
|
||||
"pos": 1,
|
||||
"end": 11,
|
||||
"members": {
|
||||
"0": {
|
||||
"kind": "PropertySignature",
|
||||
"pos": 2,
|
||||
"end": 10,
|
||||
"originalKeywordKind": "FunctionKeyword",
|
||||
"text": "function"
|
||||
}
|
||||
},
|
||||
"length": 1,
|
||||
"pos": 2,
|
||||
"end": 10
|
||||
"name": {
|
||||
"kind": "Identifier",
|
||||
"pos": 2,
|
||||
"end": 10,
|
||||
"originalKeywordKind": "FunctionKeyword",
|
||||
"text": "function"
|
||||
}
|
||||
},
|
||||
"length": 1,
|
||||
"pos": 2,
|
||||
"end": 10
|
||||
}
|
||||
}
|
||||
}
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
{
|
||||
"kind": "JSDocRecordType",
|
||||
"pos": 1,
|
||||
"end": 5,
|
||||
"literal": {
|
||||
"kind": "TypeLiteral",
|
||||
"pos": 1,
|
||||
"end": 5,
|
||||
"members": {
|
||||
"0": {
|
||||
"kind": "PropertySignature",
|
||||
"pos": 2,
|
||||
"end": 4,
|
||||
"name": {
|
||||
"kind": "Identifier",
|
||||
"pos": 2,
|
||||
"end": 3,
|
||||
"text": "a"
|
||||
}
|
||||
},
|
||||
"length": 1,
|
||||
"pos": 2,
|
||||
"end": 4
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
//// [commentInNamespaceDeclarationWithIdentifierPathName.ts]
|
||||
namespace hello.hi.world
|
||||
{
|
||||
function foo() {}
|
||||
|
||||
// TODO, blah
|
||||
}
|
||||
|
||||
//// [commentInNamespaceDeclarationWithIdentifierPathName.js]
|
||||
var hello;
|
||||
(function (hello) {
|
||||
var hi;
|
||||
(function (hi) {
|
||||
var world;
|
||||
(function (world) {
|
||||
function foo() { }
|
||||
// TODO, blah
|
||||
})(world = hi.world || (hi.world = {}));
|
||||
})(hi = hello.hi || (hello.hi = {}));
|
||||
})(hello || (hello = {}));
|
||||
@@ -0,0 +1,11 @@
|
||||
=== tests/cases/compiler/commentInNamespaceDeclarationWithIdentifierPathName.ts ===
|
||||
namespace hello.hi.world
|
||||
>hello : Symbol(hello, Decl(commentInNamespaceDeclarationWithIdentifierPathName.ts, 0, 0))
|
||||
>hi : Symbol(hi, Decl(commentInNamespaceDeclarationWithIdentifierPathName.ts, 0, 16))
|
||||
>world : Symbol(world, Decl(commentInNamespaceDeclarationWithIdentifierPathName.ts, 0, 19))
|
||||
{
|
||||
function foo() {}
|
||||
>foo : Symbol(foo, Decl(commentInNamespaceDeclarationWithIdentifierPathName.ts, 1, 1))
|
||||
|
||||
// TODO, blah
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
=== tests/cases/compiler/commentInNamespaceDeclarationWithIdentifierPathName.ts ===
|
||||
namespace hello.hi.world
|
||||
>hello : typeof hello
|
||||
>hi : typeof hi
|
||||
>world : typeof world
|
||||
{
|
||||
function foo() {}
|
||||
>foo : () => void
|
||||
|
||||
// TODO, blah
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
//// [commentOnDecoratedClassDeclaration.ts]
|
||||
declare function decorator(x: string): any;
|
||||
|
||||
/**
|
||||
* Leading trivia
|
||||
*/
|
||||
@decorator("hello")
|
||||
class Remote { }
|
||||
|
||||
/**
|
||||
* Floating Comment
|
||||
*/
|
||||
|
||||
@decorator("hi")
|
||||
class AnotherRomote {
|
||||
constructor() {}
|
||||
}
|
||||
|
||||
//// [commentOnDecoratedClassDeclaration.js]
|
||||
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
||||
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
||||
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
||||
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
||||
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
||||
};
|
||||
/**
|
||||
* Leading trivia
|
||||
*/
|
||||
var Remote = (function () {
|
||||
function Remote() {
|
||||
}
|
||||
return Remote;
|
||||
}());
|
||||
Remote = __decorate([
|
||||
decorator("hello")
|
||||
], Remote);
|
||||
/**
|
||||
* Floating Comment
|
||||
*/
|
||||
var AnotherRomote = (function () {
|
||||
function AnotherRomote() {
|
||||
}
|
||||
return AnotherRomote;
|
||||
}());
|
||||
AnotherRomote = __decorate([
|
||||
decorator("hi")
|
||||
], AnotherRomote);
|
||||
@@ -0,0 +1,26 @@
|
||||
=== tests/cases/compiler/commentOnDecoratedClassDeclaration.ts ===
|
||||
declare function decorator(x: string): any;
|
||||
>decorator : Symbol(decorator, Decl(commentOnDecoratedClassDeclaration.ts, 0, 0))
|
||||
>x : Symbol(x, Decl(commentOnDecoratedClassDeclaration.ts, 0, 27))
|
||||
|
||||
/**
|
||||
* Leading trivia
|
||||
*/
|
||||
@decorator("hello")
|
||||
>decorator : Symbol(decorator, Decl(commentOnDecoratedClassDeclaration.ts, 0, 0))
|
||||
|
||||
class Remote { }
|
||||
>Remote : Symbol(Remote, Decl(commentOnDecoratedClassDeclaration.ts, 0, 43))
|
||||
|
||||
/**
|
||||
* Floating Comment
|
||||
*/
|
||||
|
||||
@decorator("hi")
|
||||
>decorator : Symbol(decorator, Decl(commentOnDecoratedClassDeclaration.ts, 0, 0))
|
||||
|
||||
class AnotherRomote {
|
||||
>AnotherRomote : Symbol(AnotherRomote, Decl(commentOnDecoratedClassDeclaration.ts, 6, 16))
|
||||
|
||||
constructor() {}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
=== tests/cases/compiler/commentOnDecoratedClassDeclaration.ts ===
|
||||
declare function decorator(x: string): any;
|
||||
>decorator : (x: string) => any
|
||||
>x : string
|
||||
|
||||
/**
|
||||
* Leading trivia
|
||||
*/
|
||||
@decorator("hello")
|
||||
>decorator("hello") : any
|
||||
>decorator : (x: string) => any
|
||||
>"hello" : "hello"
|
||||
|
||||
class Remote { }
|
||||
>Remote : Remote
|
||||
|
||||
/**
|
||||
* Floating Comment
|
||||
*/
|
||||
|
||||
@decorator("hi")
|
||||
>decorator("hi") : any
|
||||
>decorator : (x: string) => any
|
||||
>"hi" : "hi"
|
||||
|
||||
class AnotherRomote {
|
||||
>AnotherRomote : AnotherRomote
|
||||
|
||||
constructor() {}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
//// [commentOnExportEnumDeclaration.ts]
|
||||
/**
|
||||
* comment
|
||||
*/
|
||||
export enum Color {
|
||||
r, g, b
|
||||
}
|
||||
|
||||
//// [commentOnExportEnumDeclaration.js]
|
||||
"use strict";
|
||||
/**
|
||||
* comment
|
||||
*/
|
||||
(function (Color) {
|
||||
Color[Color["r"] = 0] = "r";
|
||||
Color[Color["g"] = 1] = "g";
|
||||
Color[Color["b"] = 2] = "b";
|
||||
})(exports.Color || (exports.Color = {}));
|
||||
var Color = exports.Color;
|
||||
@@ -0,0 +1,12 @@
|
||||
=== tests/cases/compiler/commentOnExportEnumDeclaration.ts ===
|
||||
/**
|
||||
* comment
|
||||
*/
|
||||
export enum Color {
|
||||
>Color : Symbol(Color, Decl(commentOnExportEnumDeclaration.ts, 0, 0))
|
||||
|
||||
r, g, b
|
||||
>r : Symbol(Color.r, Decl(commentOnExportEnumDeclaration.ts, 3, 19))
|
||||
>g : Symbol(Color.g, Decl(commentOnExportEnumDeclaration.ts, 4, 6))
|
||||
>b : Symbol(Color.b, Decl(commentOnExportEnumDeclaration.ts, 4, 9))
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
=== tests/cases/compiler/commentOnExportEnumDeclaration.ts ===
|
||||
/**
|
||||
* comment
|
||||
*/
|
||||
export enum Color {
|
||||
>Color : Color
|
||||
|
||||
r, g, b
|
||||
>r : Color.r
|
||||
>g : Color.g
|
||||
>b : Color.b
|
||||
}
|
||||
@@ -62,21 +62,21 @@ declare function isHTMLCollection(sourceObj: any): sourceObj is HTMLCollection;
|
||||
>HTMLCollection : HTMLCollection
|
||||
|
||||
type EventTargetLike = {a: string} | HTMLCollection | NodeList;
|
||||
>EventTargetLike : EventTargetLike
|
||||
>EventTargetLike : NodeList | HTMLCollection | { a: string; }
|
||||
>a : string
|
||||
>HTMLCollection : HTMLCollection
|
||||
>NodeList : NodeList
|
||||
|
||||
var sourceObj: EventTargetLike = <any>undefined;
|
||||
>sourceObj : EventTargetLike
|
||||
>EventTargetLike : EventTargetLike
|
||||
>sourceObj : NodeList | HTMLCollection | { a: string; }
|
||||
>EventTargetLike : NodeList | HTMLCollection | { a: string; }
|
||||
><any>undefined : any
|
||||
>undefined : undefined
|
||||
|
||||
if (isNodeList(sourceObj)) {
|
||||
>isNodeList(sourceObj) : boolean
|
||||
>isNodeList : (sourceObj: any) => sourceObj is NodeList
|
||||
>sourceObj : EventTargetLike
|
||||
>sourceObj : NodeList | HTMLCollection | { a: string; }
|
||||
|
||||
sourceObj.length;
|
||||
>sourceObj.length : number
|
||||
@@ -87,7 +87,7 @@ if (isNodeList(sourceObj)) {
|
||||
if (isHTMLCollection(sourceObj)) {
|
||||
>isHTMLCollection(sourceObj) : boolean
|
||||
>isHTMLCollection : (sourceObj: any) => sourceObj is HTMLCollection
|
||||
>sourceObj : EventTargetLike
|
||||
>sourceObj : NodeList | HTMLCollection | { a: string; }
|
||||
|
||||
sourceObj.length;
|
||||
>sourceObj.length : number
|
||||
@@ -99,7 +99,7 @@ if (isNodeList(sourceObj) || isHTMLCollection(sourceObj)) {
|
||||
>isNodeList(sourceObj) || isHTMLCollection(sourceObj) : boolean
|
||||
>isNodeList(sourceObj) : boolean
|
||||
>isNodeList : (sourceObj: any) => sourceObj is NodeList
|
||||
>sourceObj : EventTargetLike
|
||||
>sourceObj : NodeList | HTMLCollection | { a: string; }
|
||||
>isHTMLCollection(sourceObj) : boolean
|
||||
>isHTMLCollection : (sourceObj: any) => sourceObj is HTMLCollection
|
||||
>sourceObj : HTMLCollection | { a: string; }
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
//// [declarationEmitArrayTypesFromGenericArrayUsage.ts]
|
||||
interface A extends Array<string> { }
|
||||
|
||||
|
||||
//// [declarationEmitArrayTypesFromGenericArrayUsage.js]
|
||||
|
||||
|
||||
//// [declarationEmitArrayTypesFromGenericArrayUsage.d.ts]
|
||||
interface A extends Array<string> {
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
=== tests/cases/compiler/declarationEmitArrayTypesFromGenericArrayUsage.ts ===
|
||||
interface A extends Array<string> { }
|
||||
>A : Symbol(A, Decl(declarationEmitArrayTypesFromGenericArrayUsage.ts, 0, 0))
|
||||
>Array : Symbol(Array, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
=== tests/cases/compiler/declarationEmitArrayTypesFromGenericArrayUsage.ts ===
|
||||
interface A extends Array<string> { }
|
||||
>A : A
|
||||
>Array : T[]
|
||||
|
||||
+3
-3
@@ -1,4 +1,4 @@
|
||||
//// [declarationEmit_bindingPatterns.ts]
|
||||
//// [declarationEmitBindingPatterns.ts]
|
||||
|
||||
const k = ({x: z = 'y'}) => { }
|
||||
|
||||
@@ -6,7 +6,7 @@ var a;
|
||||
function f({} = a, [] = a, { p: {} = a} = a) {
|
||||
}
|
||||
|
||||
//// [declarationEmit_bindingPatterns.js]
|
||||
//// [declarationEmitBindingPatterns.js]
|
||||
var k = function (_a) {
|
||||
var _b = _a.x, z = _b === void 0 ? 'y' : _b;
|
||||
};
|
||||
@@ -18,7 +18,7 @@ function f(_a, _b, _c) {
|
||||
}
|
||||
|
||||
|
||||
//// [declarationEmit_bindingPatterns.d.ts]
|
||||
//// [declarationEmitBindingPatterns.d.ts]
|
||||
declare const k: ({x: z}: {
|
||||
x?: string;
|
||||
}) => void;
|
||||
@@ -0,0 +1,17 @@
|
||||
=== tests/cases/compiler/declarationEmitBindingPatterns.ts ===
|
||||
|
||||
const k = ({x: z = 'y'}) => { }
|
||||
>k : Symbol(k, Decl(declarationEmitBindingPatterns.ts, 1, 5))
|
||||
>x : Symbol(x)
|
||||
>z : Symbol(z, Decl(declarationEmitBindingPatterns.ts, 1, 12))
|
||||
|
||||
var a;
|
||||
>a : Symbol(a, Decl(declarationEmitBindingPatterns.ts, 3, 3))
|
||||
|
||||
function f({} = a, [] = a, { p: {} = a} = a) {
|
||||
>f : Symbol(f, Decl(declarationEmitBindingPatterns.ts, 3, 6))
|
||||
>a : Symbol(a, Decl(declarationEmitBindingPatterns.ts, 3, 3))
|
||||
>a : Symbol(a, Decl(declarationEmitBindingPatterns.ts, 3, 3))
|
||||
>a : Symbol(a, Decl(declarationEmitBindingPatterns.ts, 3, 3))
|
||||
>a : Symbol(a, Decl(declarationEmitBindingPatterns.ts, 3, 3))
|
||||
}
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
=== tests/cases/compiler/declarationEmit_bindingPatterns.ts ===
|
||||
=== tests/cases/compiler/declarationEmitBindingPatterns.ts ===
|
||||
|
||||
const k = ({x: z = 'y'}) => { }
|
||||
>k : ({x: z}: { x?: string; }) => void
|
||||
+3
-3
@@ -1,4 +1,4 @@
|
||||
//// [declarationEmit_classMemberNameConflict.ts]
|
||||
//// [declarationEmitClassMemberNameConflict.ts]
|
||||
|
||||
export class C1 {
|
||||
C1() { } // has to be the same as the class name
|
||||
@@ -36,7 +36,7 @@ export class C4 {
|
||||
}
|
||||
}
|
||||
|
||||
//// [declarationEmit_classMemberNameConflict.js]
|
||||
//// [declarationEmitClassMemberNameConflict.js]
|
||||
"use strict";
|
||||
var C1 = (function () {
|
||||
function C1() {
|
||||
@@ -93,7 +93,7 @@ var C4 = (function () {
|
||||
exports.C4 = C4;
|
||||
|
||||
|
||||
//// [declarationEmit_classMemberNameConflict.d.ts]
|
||||
//// [declarationEmitClassMemberNameConflict.d.ts]
|
||||
export declare class C1 {
|
||||
C1(): void;
|
||||
bar(): (t: typeof C1) => void;
|
||||
@@ -0,0 +1,70 @@
|
||||
=== tests/cases/compiler/declarationEmitClassMemberNameConflict.ts ===
|
||||
|
||||
export class C1 {
|
||||
>C1 : Symbol(C1, Decl(declarationEmitClassMemberNameConflict.ts, 0, 0))
|
||||
|
||||
C1() { } // has to be the same as the class name
|
||||
>C1 : Symbol(C1.C1, Decl(declarationEmitClassMemberNameConflict.ts, 1, 17))
|
||||
|
||||
bar() {
|
||||
>bar : Symbol(C1.bar, Decl(declarationEmitClassMemberNameConflict.ts, 2, 12))
|
||||
|
||||
return function (t: typeof C1) {
|
||||
>t : Symbol(t, Decl(declarationEmitClassMemberNameConflict.ts, 5, 25))
|
||||
>C1 : Symbol(C1, Decl(declarationEmitClassMemberNameConflict.ts, 0, 0))
|
||||
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export class C2 {
|
||||
>C2 : Symbol(C2, Decl(declarationEmitClassMemberNameConflict.ts, 8, 1))
|
||||
|
||||
C2: any // has to be the same as the class name
|
||||
>C2 : Symbol(C2.C2, Decl(declarationEmitClassMemberNameConflict.ts, 10, 17))
|
||||
|
||||
bar() {
|
||||
>bar : Symbol(C2.bar, Decl(declarationEmitClassMemberNameConflict.ts, 11, 11))
|
||||
|
||||
return function (t: typeof C2) {
|
||||
>t : Symbol(t, Decl(declarationEmitClassMemberNameConflict.ts, 14, 25))
|
||||
>C2 : Symbol(C2, Decl(declarationEmitClassMemberNameConflict.ts, 8, 1))
|
||||
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export class C3 {
|
||||
>C3 : Symbol(C3, Decl(declarationEmitClassMemberNameConflict.ts, 17, 1))
|
||||
|
||||
get C3() { return 0; } // has to be the same as the class name
|
||||
>C3 : Symbol(C3.C3, Decl(declarationEmitClassMemberNameConflict.ts, 19, 17))
|
||||
|
||||
bar() {
|
||||
>bar : Symbol(C3.bar, Decl(declarationEmitClassMemberNameConflict.ts, 20, 26))
|
||||
|
||||
return function (t: typeof C3) {
|
||||
>t : Symbol(t, Decl(declarationEmitClassMemberNameConflict.ts, 23, 25))
|
||||
>C3 : Symbol(C3, Decl(declarationEmitClassMemberNameConflict.ts, 17, 1))
|
||||
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export class C4 {
|
||||
>C4 : Symbol(C4, Decl(declarationEmitClassMemberNameConflict.ts, 26, 1))
|
||||
|
||||
set C4(v) { } // has to be the same as the class name
|
||||
>C4 : Symbol(C4.C4, Decl(declarationEmitClassMemberNameConflict.ts, 28, 17))
|
||||
>v : Symbol(v, Decl(declarationEmitClassMemberNameConflict.ts, 29, 11))
|
||||
|
||||
bar() {
|
||||
>bar : Symbol(C4.bar, Decl(declarationEmitClassMemberNameConflict.ts, 29, 17))
|
||||
|
||||
return function (t: typeof C4) {
|
||||
>t : Symbol(t, Decl(declarationEmitClassMemberNameConflict.ts, 32, 25))
|
||||
>C4 : Symbol(C4, Decl(declarationEmitClassMemberNameConflict.ts, 26, 1))
|
||||
|
||||
};
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
=== tests/cases/compiler/declarationEmit_classMemberNameConflict.ts ===
|
||||
=== tests/cases/compiler/declarationEmitClassMemberNameConflict.ts ===
|
||||
|
||||
export class C1 {
|
||||
>C1 : C1
|
||||
+3
-3
@@ -1,4 +1,4 @@
|
||||
//// [declarationEmit_classMemberNameConflict2.ts]
|
||||
//// [declarationEmitClassMemberNameConflict2.ts]
|
||||
|
||||
const Bar = 'bar';
|
||||
|
||||
@@ -21,7 +21,7 @@ class Foo {
|
||||
Hello2 = Hello1;
|
||||
}
|
||||
|
||||
//// [declarationEmit_classMemberNameConflict2.js]
|
||||
//// [declarationEmitClassMemberNameConflict2.js]
|
||||
var Bar = 'bar';
|
||||
var Hello;
|
||||
(function (Hello) {
|
||||
@@ -44,7 +44,7 @@ var Foo = (function () {
|
||||
}());
|
||||
|
||||
|
||||
//// [declarationEmit_classMemberNameConflict2.d.ts]
|
||||
//// [declarationEmitClassMemberNameConflict2.d.ts]
|
||||
declare const Bar: "bar";
|
||||
declare enum Hello {
|
||||
World = 0,
|
||||
@@ -0,0 +1,37 @@
|
||||
=== tests/cases/compiler/declarationEmitClassMemberNameConflict2.ts ===
|
||||
|
||||
const Bar = 'bar';
|
||||
>Bar : Symbol(Bar, Decl(declarationEmitClassMemberNameConflict2.ts, 1, 5))
|
||||
|
||||
enum Hello {
|
||||
>Hello : Symbol(Hello, Decl(declarationEmitClassMemberNameConflict2.ts, 1, 18))
|
||||
|
||||
World
|
||||
>World : Symbol(Hello.World, Decl(declarationEmitClassMemberNameConflict2.ts, 3, 12))
|
||||
}
|
||||
|
||||
enum Hello1 {
|
||||
>Hello1 : Symbol(Hello1, Decl(declarationEmitClassMemberNameConflict2.ts, 5, 1))
|
||||
|
||||
World1
|
||||
>World1 : Symbol(Hello1.World1, Decl(declarationEmitClassMemberNameConflict2.ts, 7, 13))
|
||||
}
|
||||
|
||||
class Foo {
|
||||
>Foo : Symbol(Foo, Decl(declarationEmitClassMemberNameConflict2.ts, 9, 1))
|
||||
|
||||
// Same names + string => OK
|
||||
Bar = Bar;
|
||||
>Bar : Symbol(Foo.Bar, Decl(declarationEmitClassMemberNameConflict2.ts, 11, 11))
|
||||
>Bar : Symbol(Bar, Decl(declarationEmitClassMemberNameConflict2.ts, 1, 5))
|
||||
|
||||
// Same names + enum => OK
|
||||
Hello = Hello;
|
||||
>Hello : Symbol(Foo.Hello, Decl(declarationEmitClassMemberNameConflict2.ts, 13, 14))
|
||||
>Hello : Symbol(Hello, Decl(declarationEmitClassMemberNameConflict2.ts, 1, 18))
|
||||
|
||||
// Different names + enum => OK
|
||||
Hello2 = Hello1;
|
||||
>Hello2 : Symbol(Foo.Hello2, Decl(declarationEmitClassMemberNameConflict2.ts, 16, 18))
|
||||
>Hello1 : Symbol(Hello1, Decl(declarationEmitClassMemberNameConflict2.ts, 5, 1))
|
||||
}
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
=== tests/cases/compiler/declarationEmit_classMemberNameConflict2.ts ===
|
||||
=== tests/cases/compiler/declarationEmitClassMemberNameConflict2.ts ===
|
||||
|
||||
const Bar = 'bar';
|
||||
>Bar : "bar"
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
//// [tests/cases/compiler/declarationEmit_exportAssignment.ts] ////
|
||||
//// [tests/cases/compiler/declarationEmitExportAssignment.ts] ////
|
||||
|
||||
//// [utils.ts]
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
//// [tests/cases/compiler/declarationEmit_exportDeclaration.ts] ////
|
||||
//// [tests/cases/compiler/declarationEmitExportDeclaration.ts] ////
|
||||
|
||||
//// [utils.ts]
|
||||
|
||||
+3
-3
@@ -1,4 +1,4 @@
|
||||
//// [declarationEmit_expressionInExtends.ts]
|
||||
//// [declarationEmitExpressionInExtends.ts]
|
||||
|
||||
var x: {
|
||||
new<T>(s: any): Q;
|
||||
@@ -14,7 +14,7 @@ class B extends x<string> {
|
||||
var q: B;
|
||||
q.s;
|
||||
|
||||
//// [declarationEmit_expressionInExtends.js]
|
||||
//// [declarationEmitExpressionInExtends.js]
|
||||
var __extends = (this && this.__extends) || function (d, b) {
|
||||
for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
|
||||
function __() { this.constructor = d; }
|
||||
@@ -38,7 +38,7 @@ var q;
|
||||
q.s;
|
||||
|
||||
|
||||
//// [declarationEmit_expressionInExtends.d.ts]
|
||||
//// [declarationEmitExpressionInExtends.d.ts]
|
||||
declare var x: {
|
||||
new <T>(s: any): Q;
|
||||
};
|
||||
@@ -0,0 +1,32 @@
|
||||
=== tests/cases/compiler/declarationEmitExpressionInExtends.ts ===
|
||||
|
||||
var x: {
|
||||
>x : Symbol(x, Decl(declarationEmitExpressionInExtends.ts, 1, 3))
|
||||
|
||||
new<T>(s: any): Q;
|
||||
>T : Symbol(T, Decl(declarationEmitExpressionInExtends.ts, 2, 8))
|
||||
>s : Symbol(s, Decl(declarationEmitExpressionInExtends.ts, 2, 11))
|
||||
>Q : Symbol(Q, Decl(declarationEmitExpressionInExtends.ts, 3, 1))
|
||||
}
|
||||
|
||||
class Q {
|
||||
>Q : Symbol(Q, Decl(declarationEmitExpressionInExtends.ts, 3, 1))
|
||||
|
||||
s: string;
|
||||
>s : Symbol(Q.s, Decl(declarationEmitExpressionInExtends.ts, 5, 9))
|
||||
}
|
||||
|
||||
class B extends x<string> {
|
||||
>B : Symbol(B, Decl(declarationEmitExpressionInExtends.ts, 7, 1))
|
||||
>x : Symbol(x, Decl(declarationEmitExpressionInExtends.ts, 1, 3))
|
||||
}
|
||||
|
||||
var q: B;
|
||||
>q : Symbol(q, Decl(declarationEmitExpressionInExtends.ts, 12, 3))
|
||||
>B : Symbol(B, Decl(declarationEmitExpressionInExtends.ts, 7, 1))
|
||||
|
||||
q.s;
|
||||
>q.s : Symbol(Q.s, Decl(declarationEmitExpressionInExtends.ts, 5, 9))
|
||||
>q : Symbol(q, Decl(declarationEmitExpressionInExtends.ts, 12, 3))
|
||||
>s : Symbol(Q.s, Decl(declarationEmitExpressionInExtends.ts, 5, 9))
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
=== tests/cases/compiler/declarationEmit_expressionInExtends.ts ===
|
||||
=== tests/cases/compiler/declarationEmitExpressionInExtends.ts ===
|
||||
|
||||
var x: {
|
||||
>x : new <T>(s: any) => Q
|
||||
+3
-3
@@ -1,4 +1,4 @@
|
||||
//// [declarationEmit_expressionInExtends2.ts]
|
||||
//// [declarationEmitExpressionInExtends2.ts]
|
||||
|
||||
class C<T, U> {
|
||||
x: T;
|
||||
@@ -12,7 +12,7 @@ function getClass<T>(c: T) {
|
||||
class MyClass extends getClass(2) <string, number> {
|
||||
}
|
||||
|
||||
//// [declarationEmit_expressionInExtends2.js]
|
||||
//// [declarationEmitExpressionInExtends2.js]
|
||||
var __extends = (this && this.__extends) || function (d, b) {
|
||||
for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
|
||||
function __() { this.constructor = d; }
|
||||
@@ -36,7 +36,7 @@ var MyClass = (function (_super) {
|
||||
}(getClass(2)));
|
||||
|
||||
|
||||
//// [declarationEmit_expressionInExtends2.d.ts]
|
||||
//// [declarationEmitExpressionInExtends2.d.ts]
|
||||
declare class C<T, U> {
|
||||
x: T;
|
||||
y: U;
|
||||
@@ -0,0 +1,30 @@
|
||||
=== tests/cases/compiler/declarationEmitExpressionInExtends2.ts ===
|
||||
|
||||
class C<T, U> {
|
||||
>C : Symbol(C, Decl(declarationEmitExpressionInExtends2.ts, 0, 0))
|
||||
>T : Symbol(T, Decl(declarationEmitExpressionInExtends2.ts, 1, 8))
|
||||
>U : Symbol(U, Decl(declarationEmitExpressionInExtends2.ts, 1, 10))
|
||||
|
||||
x: T;
|
||||
>x : Symbol(C.x, Decl(declarationEmitExpressionInExtends2.ts, 1, 15))
|
||||
>T : Symbol(T, Decl(declarationEmitExpressionInExtends2.ts, 1, 8))
|
||||
|
||||
y: U;
|
||||
>y : Symbol(C.y, Decl(declarationEmitExpressionInExtends2.ts, 2, 9))
|
||||
>U : Symbol(U, Decl(declarationEmitExpressionInExtends2.ts, 1, 10))
|
||||
}
|
||||
|
||||
function getClass<T>(c: T) {
|
||||
>getClass : Symbol(getClass, Decl(declarationEmitExpressionInExtends2.ts, 4, 1))
|
||||
>T : Symbol(T, Decl(declarationEmitExpressionInExtends2.ts, 6, 18))
|
||||
>c : Symbol(c, Decl(declarationEmitExpressionInExtends2.ts, 6, 21))
|
||||
>T : Symbol(T, Decl(declarationEmitExpressionInExtends2.ts, 6, 18))
|
||||
|
||||
return C;
|
||||
>C : Symbol(C, Decl(declarationEmitExpressionInExtends2.ts, 0, 0))
|
||||
}
|
||||
|
||||
class MyClass extends getClass(2) <string, number> {
|
||||
>MyClass : Symbol(MyClass, Decl(declarationEmitExpressionInExtends2.ts, 8, 1))
|
||||
>getClass : Symbol(getClass, Decl(declarationEmitExpressionInExtends2.ts, 4, 1))
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user