From ee5d1d33c1548d38165a3cf62dc938e928627fea Mon Sep 17 00:00:00 2001 From: Sheetal Nandi Date: Thu, 1 Jun 2017 16:20:30 -0700 Subject: [PATCH] Completion list in the type expression should show types --- src/harness/fourslash.ts | 7 +- src/services/completions.ts | 58 +++++--- src/services/utilities.ts | 4 +- ...JsdocTypedefTagTypeExpressionCompletion.ts | 70 +++++++++ ...sdocTypedefTagTypeExpressionCompletion2.ts | 65 ++++++++ ...sdocTypedefTagTypeExpressionCompletion3.ts | 127 ++++++++++++++++ ...jsdocTypedefTagTypeExpressionCompletion.ts | 140 ++++++++++++++++++ 7 files changed, 446 insertions(+), 25 deletions(-) create mode 100644 tests/cases/fourslash/jsFileJsdocTypedefTagTypeExpressionCompletion.ts create mode 100644 tests/cases/fourslash/jsFileJsdocTypedefTagTypeExpressionCompletion2.ts create mode 100644 tests/cases/fourslash/jsFileJsdocTypedefTagTypeExpressionCompletion3.ts create mode 100644 tests/cases/fourslash/jsdocTypedefTagTypeExpressionCompletion.ts diff --git a/src/harness/fourslash.ts b/src/harness/fourslash.ts index 8f19b83c7ad..0f840421b65 100644 --- a/src/harness/fourslash.ts +++ b/src/harness/fourslash.ts @@ -822,8 +822,8 @@ namespace FourSlash { function filterByTextOrDocumentation(entry: ts.CompletionEntry) { const details = that.getCompletionEntryDetails(entry.name); - const documentation = ts.displayPartsToString(details.documentation); - const text = ts.displayPartsToString(details.displayParts); + const documentation = details && ts.displayPartsToString(details.documentation); + const text = details && ts.displayPartsToString(details.displayParts); // If any of the expected values are undefined, assume that users don't // care about them. @@ -860,6 +860,9 @@ namespace FourSlash { if (expectedKind) { error += "Expected kind: " + expectedKind + " to equal: " + filterCompletions[0].kind + "."; } + else { + error += "kind: " + filterCompletions[0].kind + "."; + } if (replacementSpan) { const spanText = filterCompletions[0].replacementSpan ? stringify(filterCompletions[0].replacementSpan) : undefined; error += "Expected replacement span: " + stringify(replacementSpan) + " to equal: " + spanText + "."; diff --git a/src/services/completions.ts b/src/services/completions.ts index 94935d3f3db..7c0662c7531 100644 --- a/src/services/completions.ts +++ b/src/services/completions.ts @@ -354,7 +354,7 @@ namespace ts.Completions { let requestJsDocTag = false; let start = timestamp(); - const currentToken = getTokenAtPosition(sourceFile, position, /*includeJsDocComment*/ false); // TODO: GH#15853 + let currentToken = getTokenAtPosition(sourceFile, position, /*includeJsDocComment*/ false); // TODO: GH#15853 log("getCompletionData: Get current token: " + (timestamp() - start)); start = timestamp(); @@ -362,6 +362,7 @@ namespace ts.Completions { const insideComment = isInComment(sourceFile, position, currentToken); log("getCompletionData: Is inside comment: " + (timestamp() - start)); + let insideJsDocTagTypeExpression = false; if (insideComment) { if (hasDocComment(sourceFile, position)) { // The current position is next to the '@' sign, when no tag name being provided yet. @@ -394,22 +395,20 @@ namespace ts.Completions { // Completion should work inside certain JsDoc tags. For example: // /** @type {number | string} */ // Completion should work in the brackets - let insideJsDocTagExpression = false; const tag = getJsDocTagAtPosition(sourceFile, position); if (tag) { if (tag.tagName.pos <= position && position <= tag.tagName.end) { requestJsDocTagName = true; } - - switch (tag.kind) { - case SyntaxKind.JSDocTypeTag: - case SyntaxKind.JSDocParameterTag: - case SyntaxKind.JSDocReturnTag: - const tagWithExpression = tag; - if (tagWithExpression.typeExpression) { - insideJsDocTagExpression = tagWithExpression.typeExpression.pos < position && position < tagWithExpression.typeExpression.end; - } - break; + if (isTagWithTypeExpression(tag) && tag.typeExpression) { + currentToken = getTokenAtPosition(sourceFile, position, /*includeJsDocComment*/ true); + if (!currentToken || + (!isDeclarationName(currentToken) && + (currentToken.parent.kind !== SyntaxKind.JSDocPropertyTag || + (currentToken.parent).name !== currentToken))) { + // Use as type location if inside tag's type expression + insideJsDocTagTypeExpression = isCurrentlyEditingNode(tag.typeExpression); + } } } @@ -417,7 +416,7 @@ namespace ts.Completions { return { symbols: undefined, isGlobalCompletion: false, isMemberCompletion: false, isNewIdentifierLocation: false, location: undefined, isRightOfDot: false, requestJsDocTagName, requestJsDocTag, hasFilteredClassMemberKeywords: false }; } - if (!insideJsDocTagExpression) { + if (!insideJsDocTagTypeExpression) { // Proceed if the current position is in jsDoc tag expression; otherwise it is a normal // comment or the plain text part of a jsDoc comment, so no completion should be available log("Returning an empty list because completion was inside a regular comment or plain text part of a JsDoc comment."); @@ -426,7 +425,7 @@ namespace ts.Completions { } start = timestamp(); - const previousToken = findPrecedingToken(position, sourceFile); + const previousToken = findPrecedingToken(position, sourceFile, /*startNode*/ undefined, insideJsDocTagTypeExpression); log("getCompletionData: Get previous token 1: " + (timestamp() - start)); // The decision to provide completion depends on the contextToken, which is determined through the previousToken. @@ -437,7 +436,7 @@ namespace ts.Completions { // Skip this partial identifier and adjust the contextToken to the token that precedes it. if (contextToken && position <= contextToken.end && isWord(contextToken.kind)) { const start = timestamp(); - contextToken = findPrecedingToken(contextToken.getFullStart(), sourceFile); + contextToken = findPrecedingToken(contextToken.getFullStart(), sourceFile, /*startNode*/ undefined, insideJsDocTagTypeExpression); log("getCompletionData: Get previous token 2: " + (timestamp() - start)); } @@ -449,7 +448,7 @@ namespace ts.Completions { let isRightOfOpenTag = false; let isStartingCloseTag = false; - let location = getTouchingPropertyName(sourceFile, position, /*includeJsDocComment*/ false); // TODO: GH#15853 + let location = getTouchingPropertyName(sourceFile, position, insideJsDocTagTypeExpression); // TODO: GH#15853 if (contextToken) { // Bail out if this is a known invalid completion location if (isCompletionListBlocker(contextToken)) { @@ -553,6 +552,20 @@ namespace ts.Completions { return { symbols, isGlobalCompletion, isMemberCompletion, isNewIdentifierLocation, location, isRightOfDot: (isRightOfDot || isRightOfOpenTag), requestJsDocTagName, requestJsDocTag, hasFilteredClassMemberKeywords }; + type JSDocTagWithTypeExpression = JSDocAugmentsTag | JSDocParameterTag | JSDocPropertyTag | JSDocReturnTag | JSDocTypeTag | JSDocTypedefTag; + + function isTagWithTypeExpression(tag: JSDocTag): tag is JSDocTagWithTypeExpression { + switch (tag.kind) { + case SyntaxKind.JSDocAugmentsTag: + case SyntaxKind.JSDocParameterTag: + case SyntaxKind.JSDocPropertyTag: + case SyntaxKind.JSDocReturnTag: + case SyntaxKind.JSDocTypeTag: + case SyntaxKind.JSDocTypedefTag: + return true; + } + } + function getTypeScriptMemberSymbols(): void { // Right of dot member completion list isGlobalCompletion = false; @@ -560,7 +573,7 @@ namespace ts.Completions { isNewIdentifierLocation = false; // Since this is qualified name check its a type node location - const isTypeLocation = isPartOfTypeNode(node.parent); + const isTypeLocation = isPartOfTypeNode(node.parent) || insideJsDocTagTypeExpression; const isRhsOfImportDeclaration = isInRightSideOfInternalImportEqualsDeclaration(node); if (node.kind === SyntaxKind.Identifier || node.kind === SyntaxKind.QualifiedName || node.kind === SyntaxKind.PropertyAccessExpression) { let symbol = typeChecker.getSymbolAtLocation(node); @@ -722,8 +735,9 @@ namespace ts.Completions { return !!(symbol.flags & SymbolFlags.Namespace); } - if (!isContextTokenValueLocation(contextToken) && - (isPartOfTypeNode(location) || isContextTokenTypeLocation(contextToken))) { + if (insideJsDocTagTypeExpression || + (!isContextTokenValueLocation(contextToken) && + (isPartOfTypeNode(location) || isContextTokenTypeLocation(contextToken)))) { // Its a type, but you can reach it by namespace.type as well return symbolCanbeReferencedAtTypeLocation(symbol); } @@ -770,14 +784,16 @@ namespace ts.Completions { symbol = typeChecker.getAliasedSymbol(symbol); } + if (symbol.flags & SymbolFlags.Type) { + return true; + } + if (symbol.flags & (SymbolFlags.ValueModule | SymbolFlags.NamespaceModule)) { const exportedSymbols = typeChecker.getExportsOfModule(symbol); // If the exported symbols contains type, // symbol can be referenced at locations where type is allowed return forEach(exportedSymbols, symbolCanbeReferencedAtTypeLocation); } - - return !!(symbol.flags & (SymbolFlags.NamespaceModule | SymbolFlags.Type)); } /** diff --git a/src/services/utilities.ts b/src/services/utilities.ts index 7fd3d837406..d40824ced33 100644 --- a/src/services/utilities.ts +++ b/src/services/utilities.ts @@ -707,7 +707,7 @@ namespace ts { } } - export function findPrecedingToken(position: number, sourceFile: SourceFile, startNode?: Node): Node { + export function findPrecedingToken(position: number, sourceFile: SourceFile, startNode?: Node, includeJsDocComment?: boolean): Node { return find(startNode || sourceFile); function findRightmostToken(n: Node): Node { @@ -738,7 +738,7 @@ namespace ts { // NOTE: JsxText is a weird kind of node that can contain only whitespaces (since they are not counted as trivia). // if this is the case - then we should assume that token in question is located in previous child. if (position < child.end && (nodeHasTokens(child) || child.kind === SyntaxKind.JsxText)) { - const start = child.getStart(sourceFile); + const start = child.getStart(sourceFile, includeJsDocComment); const lookInPreviousChild = (start >= position) || // cursor in the leading trivia (child.kind === SyntaxKind.JsxText && start === child.end); // whitespace only JsxText diff --git a/tests/cases/fourslash/jsFileJsdocTypedefTagTypeExpressionCompletion.ts b/tests/cases/fourslash/jsFileJsdocTypedefTagTypeExpressionCompletion.ts new file mode 100644 index 00000000000..62046458e4c --- /dev/null +++ b/tests/cases/fourslash/jsFileJsdocTypedefTagTypeExpressionCompletion.ts @@ -0,0 +1,70 @@ +/// + +// @allowNonTsExtensions: true +// @Filename: jsFileJsdocTypedefTagTypeExpressionCompletion_typedef.js + +//// /** +//// * @typedef {/*1*/string | /*2*/number} T.NumberLike +//// * @typedef {{/*propertyName*/age: /*3*/number}} T.People +//// * @typedef {string | number} T.O.Q.NumberLike +//// * @type {/*4*/T./*1TypeMember*/NumberLike} +//// */ +//// var x; +//// /** @type {/*5*/T./*2TypeMember*/O.Q.NumberLike} */ +//// var x1; +//// /** @type {/*6*/T./*3TypeMember*/People} */ +//// var x1; +//// /*globalValue*/ + +interface VeriferCompletionsInJsDoc { + verifyType(symbol: string, kind: string): void; + verifyValue(symbol: string, kind: string): void; + verifyTypeMember(symbol: string, kind: string): void; +} + +function verifyCompletionsInJsDocType(marker: string, { verifyType, verifyValue, verifyTypeMember }: VeriferCompletionsInJsDoc) { + goTo.marker(marker); + + verifyType("T", "module"); + + // TODO: May be filter keywords based on context + //verifyType("string", "keyword"); + //verifyType("number", "keyword"); + + verifyValue("x", "var"); + verifyValue("x1", "var"); + + verifyTypeMember("NumberLike", "type"); + verifyTypeMember("People", "type"); + verifyTypeMember("O", "module"); +} + +function verifySymbolPresentWithKind(symbol: string, kind: string) { + return verify.completionListContains(symbol, /*text*/ undefined, /*documentation*/ undefined, kind); +} + +function verifySymbolPresentWithWarning(symbol: string) { + return verifySymbolPresentWithKind(symbol, "warning"); +} + +for (let i = 1; i <= 6; i++) { + verifyCompletionsInJsDocType(i.toString(), { + verifyType: verifySymbolPresentWithKind, + verifyValue: verifySymbolPresentWithWarning, + verifyTypeMember: verifySymbolPresentWithWarning, + }); +} +verifyCompletionsInJsDocType("globalValue", { + verifyType: verifySymbolPresentWithWarning, + verifyValue: verifySymbolPresentWithKind, + verifyTypeMember: verifySymbolPresentWithWarning, +}); +for (let i = 1; i <= 3; i++) { + verifyCompletionsInJsDocType(i.toString() + "TypeMember", { + verifyType: verifySymbolPresentWithWarning, + verifyValue: verifySymbolPresentWithWarning, + verifyTypeMember: verifySymbolPresentWithKind, + }); +} +goTo.marker("propertyName"); +verify.completionListIsEmpty(); diff --git a/tests/cases/fourslash/jsFileJsdocTypedefTagTypeExpressionCompletion2.ts b/tests/cases/fourslash/jsFileJsdocTypedefTagTypeExpressionCompletion2.ts new file mode 100644 index 00000000000..b327fdf427b --- /dev/null +++ b/tests/cases/fourslash/jsFileJsdocTypedefTagTypeExpressionCompletion2.ts @@ -0,0 +1,65 @@ +/// + +// @allowNonTsExtensions: true +// @Filename: jsFileJsdocTypedefTagTypeExpressionCompletion2_typedef.js + +//// class Foo { +//// constructor(value: number) { this.property1 = "hello"; } +//// static method1() {} +//// method3() { return 3; } +//// /** +//// * @param {string} foo A value. +//// * @returns {number} Another value +//// * @mytag +//// */ +//// method4(foo) { return 3; } +//// } +//// /** +//// * @type { /*type*/Foo } +//// */ +////var x; +/////*globalValue*/ +////x./*valueMember*/ + +interface VeriferCompletionsInJsDoc { + verifyValueOrType(symbol: string, kind: string): void; + verifyValue(symbol: string, kind: string): void; + verifyValueMember(symbol: string, kind: string): void; +} + +function verifyCompletionsInJsDocType(marker: string, { verifyValueOrType, verifyValue, verifyValueMember }: VeriferCompletionsInJsDoc) { + goTo.marker(marker); + + verifyValueOrType("Foo", "class"); + + verifyValue("x", "var"); + + verifyValueMember("property1", "property"); + verifyValueMember("method3", "method"); + verifyValueMember("method4", "method"); + verifyValueMember("foo", "warning"); +} + +function verifySymbolPresentWithKind(symbol: string, kind: string) { + return verify.completionListContains(symbol, /*text*/ undefined, /*documentation*/ undefined, kind); +} + +function verifySymbolPresentWithWarning(symbol: string) { + return verifySymbolPresentWithKind(symbol, "warning"); +} + +verifyCompletionsInJsDocType("type", { + verifyValueOrType: verifySymbolPresentWithKind, + verifyValue: verifySymbolPresentWithWarning, + verifyValueMember: verifySymbolPresentWithWarning, +}); +verifyCompletionsInJsDocType("globalValue", { + verifyValueOrType: verifySymbolPresentWithKind, + verifyValue: verifySymbolPresentWithKind, + verifyValueMember: verifySymbolPresentWithWarning, +}); +verifyCompletionsInJsDocType("valueMember", { + verifyValueOrType: verifySymbolPresentWithWarning, + verifyValue: verifySymbolPresentWithWarning, + verifyValueMember: verifySymbolPresentWithKind, +}); diff --git a/tests/cases/fourslash/jsFileJsdocTypedefTagTypeExpressionCompletion3.ts b/tests/cases/fourslash/jsFileJsdocTypedefTagTypeExpressionCompletion3.ts new file mode 100644 index 00000000000..66c3856d0b7 --- /dev/null +++ b/tests/cases/fourslash/jsFileJsdocTypedefTagTypeExpressionCompletion3.ts @@ -0,0 +1,127 @@ +/// + +// @allowNonTsExtensions: true +// @Filename: jsFileJsdocTypedefTagTypeExpressionCompletion3_typedef.js + +//// /** +//// * @typedef {{ age: number }} Foo.Namespace.SomeType +//// */ +//// class Foo { +//// constructor(value) { this.property1 = "hello"; } +//// static method1() {} +//// method3() { return 3; } +//// /** +//// * @param {string} foo A value. +//// * @returns {number} Another value +//// * @mytag +//// */ +//// method4(foo) { return 3; } +//// } +//// /** +//// * @type { /*type1*/Foo./*typeFooMember*/Namespace./*NamespaceMember*/SomeType } +//// */ +////var x; +/////*globalValue*/ +////x./*valueMemberOfSomeType*/ +//// /** +//// * @type { /*type2*/Foo } +//// */ +////var x1; +////x1./*valueMemberOfFooInstance*/; +////Foo./*valueMemberOfFoo*/; + +function verifySymbolPresentWithKind(symbol: string, kind: string) { + return verify.completionListContains(symbol, /*text*/ undefined, /*documentation*/ undefined, kind); +} + +function verifySymbolPresentWithWarning(symbol: string) { + return verifySymbolPresentWithKind(symbol, "warning"); +} + +for (const marker of ["type1", "type2"]) { + goTo.marker(marker); + verifySymbolPresentWithKind("Foo", "class"); + + verifySymbolPresentWithWarning("Namespace"); + verifySymbolPresentWithWarning("SomeType"); + + verifySymbolPresentWithWarning("x"); + verifySymbolPresentWithWarning("x1"); + verifySymbolPresentWithWarning("method1"); + verifySymbolPresentWithWarning("property1"); + verifySymbolPresentWithWarning("method3"); + verifySymbolPresentWithWarning("method4"); + verifySymbolPresentWithWarning("foo"); +} + +goTo.marker("typeFooMember"); +verifySymbolPresentWithWarning("Foo"); +verifySymbolPresentWithKind("Namespace", "module"); +verifySymbolPresentWithWarning("SomeType"); +verifySymbolPresentWithWarning("x"); +verifySymbolPresentWithWarning("x1"); +verifySymbolPresentWithWarning("method1"); +verifySymbolPresentWithWarning("property1"); +verifySymbolPresentWithWarning("method3"); +verifySymbolPresentWithWarning("method4"); +verifySymbolPresentWithWarning("foo"); + +goTo.marker("NamespaceMember"); +verifySymbolPresentWithWarning("Foo"); +verifySymbolPresentWithWarning("Namespace"); +verifySymbolPresentWithKind("SomeType", "type"); +verifySymbolPresentWithWarning("x"); +verifySymbolPresentWithWarning("x1"); +verifySymbolPresentWithWarning("method1"); +verifySymbolPresentWithWarning("property1"); +verifySymbolPresentWithWarning("method3"); +verifySymbolPresentWithWarning("method4"); +verifySymbolPresentWithWarning("foo"); + +goTo.marker("globalValue"); +verifySymbolPresentWithKind("Foo", "class"); +verifySymbolPresentWithWarning("Namespace"); +verifySymbolPresentWithWarning("SomeType"); +verifySymbolPresentWithKind("x", "var"); +verifySymbolPresentWithKind("x1", "var"); +verifySymbolPresentWithWarning("method1"); +verifySymbolPresentWithWarning("property1"); +verifySymbolPresentWithWarning("method3"); +verifySymbolPresentWithWarning("method4"); +verifySymbolPresentWithWarning("foo"); + +goTo.marker("valueMemberOfSomeType"); +verifySymbolPresentWithWarning("Foo"); +verifySymbolPresentWithWarning("Namespace"); +verifySymbolPresentWithWarning("SomeType"); +verifySymbolPresentWithWarning("x"); +verifySymbolPresentWithWarning("x1"); +verifySymbolPresentWithWarning("method1"); +verifySymbolPresentWithWarning("property1"); +verifySymbolPresentWithWarning("method3"); +verifySymbolPresentWithWarning("method4"); +verifySymbolPresentWithWarning("foo"); + +goTo.marker("valueMemberOfFooInstance"); +verifySymbolPresentWithWarning("Foo"); +verifySymbolPresentWithWarning("Namespace"); +verifySymbolPresentWithWarning("SomeType"); +verifySymbolPresentWithWarning("x"); +verifySymbolPresentWithWarning("x1"); +verifySymbolPresentWithWarning("method1"); +verifySymbolPresentWithKind("property1", "property"); +verifySymbolPresentWithKind("method3", "method"); +verifySymbolPresentWithKind("method4", "method"); +verifySymbolPresentWithKind("foo", "warning"); + +goTo.marker("valueMemberOfFoo"); +verifySymbolPresentWithWarning("Foo"); +verifySymbolPresentWithWarning("Namespace"); +verifySymbolPresentWithWarning("SomeType"); +verifySymbolPresentWithWarning("x"); +verifySymbolPresentWithWarning("x1"); +verifySymbolPresentWithKind("method1", "method"); +verifySymbolPresentWithWarning("property1"); +verifySymbolPresentWithWarning("method3"); +verifySymbolPresentWithWarning("method4"); +verifySymbolPresentWithWarning("foo"); \ No newline at end of file diff --git a/tests/cases/fourslash/jsdocTypedefTagTypeExpressionCompletion.ts b/tests/cases/fourslash/jsdocTypedefTagTypeExpressionCompletion.ts new file mode 100644 index 00000000000..379cc60e058 --- /dev/null +++ b/tests/cases/fourslash/jsdocTypedefTagTypeExpressionCompletion.ts @@ -0,0 +1,140 @@ +/// + +////interface I { +//// age: number; +////} +//// class Foo { +//// property1: string; +//// constructor(value: number) { this.property1 = "hello"; } +//// static method1() {} +//// method3(): number { return 3; } +//// /** +//// * @param {string} foo A value. +//// * @returns {number} Another value +//// * @mytag +//// */ +//// method4(foo: string) { return 3; } +//// } +//// namespace Foo.Namespace { export interface SomeType { age2: number } } +//// /** +//// * @type { /*type1*/Foo./*typeFooMember*/Namespace./*NamespaceMember*/SomeType } +//// */ +////var x; +/////*globalValue*/ +////x./*valueMemberOfSomeType*/ +////var x1: Foo; +////x1./*valueMemberOfFooInstance*/; +////Foo./*valueMemberOfFoo*/; +//// /** +//// * @type { {/*propertyName*/ageX: number} } +//// */ +////var y; + +function verifySymbolPresentWithKind(symbol: string, kind: string) { + return verify.completionListContains(symbol, /*text*/ undefined, /*documentation*/ undefined, kind); +} + +function verifySymbolNotPresent(symbol: string) { + return verify.not.completionListContains(symbol); +} + +goTo.marker("type1"); +verifySymbolPresentWithKind("Foo", "class"); +verifySymbolPresentWithKind("I", "interface"); +verifySymbolNotPresent("Namespace"); +verifySymbolNotPresent("SomeType"); +verifySymbolNotPresent("x"); +verifySymbolNotPresent("x1"); +verifySymbolNotPresent("y"); +verifySymbolNotPresent("method1"); +verifySymbolNotPresent("property1"); +verifySymbolNotPresent("method3"); +verifySymbolNotPresent("method4"); +verifySymbolNotPresent("foo"); + +goTo.marker("typeFooMember"); +verifySymbolNotPresent("Foo"); +verifySymbolNotPresent("I"); +verifySymbolPresentWithKind("Namespace", "module"); +verifySymbolNotPresent("SomeType"); +verifySymbolNotPresent("x"); +verifySymbolNotPresent("x1"); +verifySymbolNotPresent("y"); +verifySymbolNotPresent("method1"); +verifySymbolNotPresent("property1"); +verifySymbolNotPresent("method3"); +verifySymbolNotPresent("method4"); +verifySymbolNotPresent("foo"); + +goTo.marker("NamespaceMember"); +verifySymbolNotPresent("Foo"); +verifySymbolNotPresent("I"); +verifySymbolNotPresent("Namespace"); +verifySymbolPresentWithKind("SomeType", "interface"); +verifySymbolNotPresent("x"); +verifySymbolNotPresent("x1"); +verifySymbolNotPresent("y"); +verifySymbolNotPresent("method1"); +verifySymbolNotPresent("property1"); +verifySymbolNotPresent("method3"); +verifySymbolNotPresent("method4"); +verifySymbolNotPresent("foo"); + +goTo.marker("globalValue"); +verifySymbolPresentWithKind("Foo", "class"); +verifySymbolNotPresent("I"); +verifySymbolNotPresent("Namespace"); +verifySymbolNotPresent("SomeType"); +verifySymbolPresentWithKind("x", "var"); +verifySymbolPresentWithKind("x1", "var"); +verifySymbolPresentWithKind("y", "var"); +verifySymbolNotPresent("method1"); +verifySymbolNotPresent("property1"); +verifySymbolNotPresent("method3"); +verifySymbolNotPresent("method4"); +verifySymbolNotPresent("foo"); + +goTo.marker("valueMemberOfSomeType"); +verifySymbolNotPresent("Foo"); +verifySymbolNotPresent("I"); +verifySymbolNotPresent("Namespace"); +verifySymbolNotPresent("SomeType"); +verifySymbolNotPresent("x"); +verifySymbolNotPresent("x1"); +verifySymbolNotPresent("y"); +verifySymbolNotPresent("method1"); +verifySymbolNotPresent("property1"); +verifySymbolNotPresent("method3"); +verifySymbolNotPresent("method4"); +verifySymbolNotPresent("foo"); + +goTo.marker("valueMemberOfFooInstance"); +verifySymbolNotPresent("Foo"); +verifySymbolNotPresent("I"); +verifySymbolNotPresent("Namespace"); +verifySymbolNotPresent("SomeType"); +verifySymbolNotPresent("x"); +verifySymbolNotPresent("x1"); +verifySymbolNotPresent("y"); +verifySymbolNotPresent("method1"); +verifySymbolPresentWithKind("property1", "property"); +verifySymbolPresentWithKind("method3", "method"); +verifySymbolPresentWithKind("method4", "method"); +verifySymbolNotPresent("foo"); + +goTo.marker("valueMemberOfFoo"); +verifySymbolNotPresent("Foo"); +verifySymbolNotPresent("I"); +verifySymbolNotPresent("Namespace"); +verifySymbolNotPresent("SomeType"); +verifySymbolNotPresent("x"); +verifySymbolNotPresent("x1"); +verifySymbolNotPresent("y"); +verifySymbolPresentWithKind("method1", "method"); +verifySymbolNotPresent("property1"); +verifySymbolNotPresent("method3"); +verifySymbolNotPresent("method4"); +verifySymbolNotPresent("foo"); + +goTo.marker("propertyName"); +verify.completionListIsEmpty(); \ No newline at end of file