diff --git a/Gulpfile.ts b/Gulpfile.ts index aef7cc4c6dd79..63faf99259923 100644 --- a/Gulpfile.ts +++ b/Gulpfile.ts @@ -747,7 +747,7 @@ declare module "convert-source-map" { export function fromSource(source: string, largeSource?: boolean): SourceMapConverter; } -gulp.task("browserify", "Runs browserify on run.js to produce a file suitable for running tests in the browser", [servicesFile], (done) => { +gulp.task("browserify", "Runs browserify on run.js to produce a file suitable for running tests in the browser", [servicesFile, run], (done) => { const testProject = tsc.createProject("src/harness/tsconfig.json", getCompilerSettings({ outFile: "../../built/local/bundle.js" }, /*useBuiltCompiler*/ true)); return testProject.src() .pipe(newer("built/local/bundle.js")) diff --git a/Jakefile.js b/Jakefile.js index 3de055b498e4b..730754f425615 100644 --- a/Jakefile.js +++ b/Jakefile.js @@ -959,7 +959,7 @@ var nodeServerInFile = "tests/webTestServer.ts"; compileFile(nodeServerOutFile, [nodeServerInFile], [builtLocalDirectory, tscFile], [], /*useBuiltCompiler:*/ true, { noOutFile: true, lib: "es6" }); desc("Runs browserify on run.js to produce a file suitable for running tests in the browser"); -task("browserify", ["tests", builtLocalDirectory, nodeServerOutFile], function() { +task("browserify", ["tests", run, builtLocalDirectory, nodeServerOutFile], function() { var cmd = 'browserify built/local/run.js -t ./scripts/browserify-optional -d -o built/local/bundle.js'; exec(cmd); }, { async: true }); diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 49248144524d1..7d57825bf445a 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -14653,12 +14653,31 @@ namespace ts { ? (node).expression : (node).left; - const type = checkExpression(left); + return isValidPropertyAccessWithType(node, left, propertyName, getWidenedType(checkExpression(left))); + } + + function isValidPropertyAccessWithType( + node: PropertyAccessExpression | QualifiedName, + left: LeftHandSideExpression | QualifiedName, + propertyName: string, + type: Type): boolean { + if (type !== unknownType && !isTypeAny(type)) { - const prop = getPropertyOfType(getWidenedType(type), propertyName); + const prop = getPropertyOfType(type, propertyName); if (prop) { return checkPropertyAccessibility(node, left, type, prop); } + + // In js files properties of unions are allowed in completion + if (isInJavaScriptFile(left) && (type.flags & TypeFlags.Union)) { + for (const elementType of (type).types) { + if (isValidPropertyAccessWithType(node, left, propertyName, elementType)) { + return true; + } + } + } + + return false; } return true; } diff --git a/src/harness/fourslash.ts b/src/harness/fourslash.ts index ceeec7f9b9c24..7fdbef74ad7a8 100644 --- a/src/harness/fourslash.ts +++ b/src/harness/fourslash.ts @@ -814,8 +814,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. @@ -852,6 +852,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 071496a422436..6f1f3fae1ea23 100644 --- a/src/services/completions.ts +++ b/src/services/completions.ts @@ -366,7 +366,7 @@ namespace ts.Completions { let request: Request | undefined; let start = timestamp(); - const currentToken = getTokenAtPosition(sourceFile, position, /*includeJsDocComment*/ false); + let currentToken = getTokenAtPosition(sourceFile, position, /*includeJsDocComment*/ false); // TODO: GH#15853 // We will check for jsdoc comments with insideComment and getJsDocTagAtPosition. (TODO: that seems rather inefficient to check the same thing so many times.) log("getCompletionData: Get current token: " + (timestamp() - start)); @@ -376,6 +376,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)) { if (sourceFile.text.charCodeAt(position - 1) === CharacterCodes.at) { @@ -410,25 +411,23 @@ 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(currentToken, position); if (tag) { if (tag.tagName.pos <= position && position <= tag.tagName.end) { request = { kind: "JsDocTagName" }; } - - switch (tag.kind) { - case SyntaxKind.JSDocTypeTag: - case SyntaxKind.JSDocParameterTag: - case SyntaxKind.JSDocReturnTag: - const tagWithExpression = tag; - if (tagWithExpression.typeExpression && tagWithExpression.typeExpression.pos < position && position < tagWithExpression.typeExpression.end) { - insideJsDocTagExpression = true; - } - else if (isJSDocParameterTag(tag) && (nodeIsMissing(tag.name) || tag.name.pos <= position && position <= tag.name.end)) { - request = { kind: "JsDocParameterName", tag }; - } - 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); + } + } + if (isJSDocParameterTag(tag) && (nodeIsMissing(tag.name) || tag.name.pos <= position && position <= tag.name.end)) { + request = { kind: "JsDocParameterName", tag }; } } @@ -436,7 +435,7 @@ namespace ts.Completions { return { symbols: undefined, isGlobalCompletion: false, isMemberCompletion: false, isNewIdentifierLocation: false, location: undefined, isRightOfDot: false, request, 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."); @@ -445,7 +444,7 @@ namespace ts.Completions { } start = timestamp(); - const previousToken = findPrecedingToken(position, sourceFile, /*startNode*/ undefined, /*includeJsDoc*/ true); + 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. @@ -456,7 +455,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, /*startNode*/ undefined, /*includeJsDoc*/ true); + contextToken = findPrecedingToken(contextToken.getFullStart(), sourceFile, /*startNode*/ undefined, insideJsDocTagTypeExpression); log("getCompletionData: Get previous token 2: " + (timestamp() - start)); } @@ -468,7 +467,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)) { @@ -572,12 +571,29 @@ namespace ts.Completions { return { symbols, isGlobalCompletion, isMemberCompletion, isNewIdentifierLocation, location, isRightOfDot: (isRightOfDot || isRightOfOpenTag), request, 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; isMemberCompletion = true; isNewIdentifierLocation = false; + // Since this is qualified name check its a type node location + 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); @@ -589,16 +605,24 @@ namespace ts.Completions { if (symbol && symbol.flags & SymbolFlags.HasExports) { // Extract module or enum members const exportedSymbols = typeChecker.getExportsOfModule(symbol); + const isValidValueAccess = (symbol: Symbol) => typeChecker.isValidPropertyAccess((node.parent), symbol.name); + const isValidTypeAccess = (symbol: Symbol) => symbolCanbeReferencedAtTypeLocation(symbol); + const isValidAccess = isRhsOfImportDeclaration ? + // Any kind is allowed when dotting off namespace in internal import equals declaration + (symbol: Symbol) => isValidTypeAccess(symbol) || isValidValueAccess(symbol) : + isTypeLocation ? isValidTypeAccess : isValidValueAccess; forEach(exportedSymbols, symbol => { - if (typeChecker.isValidPropertyAccess((node.parent), symbol.name)) { + if (isValidAccess(symbol)) { symbols.push(symbol); } }); } } - const type = typeChecker.getTypeAtLocation(node); - addTypeProperties(type); + if (!isTypeLocation) { + const type = typeChecker.getTypeAtLocation(node); + addTypeProperties(type); + } } function addTypeProperties(type: Type) { @@ -706,13 +730,87 @@ namespace ts.Completions { isStatement(scopeNode); } - /// TODO filter meaning based on the current context const symbolMeanings = SymbolFlags.Type | SymbolFlags.Value | SymbolFlags.Namespace | SymbolFlags.Alias; - symbols = typeChecker.getSymbolsInScope(scopeNode, symbolMeanings); + symbols = filterGlobalCompletion(typeChecker.getSymbolsInScope(scopeNode, symbolMeanings)); return true; } + function filterGlobalCompletion(symbols: Symbol[]) { + return filter(symbols, symbol => { + if (!isSourceFile(location)) { + // export = /**/ here we want to get all meanings, so any symbol is ok + if (isExportAssignment(location.parent)) { + return true; + } + + // This is an alias, follow what it aliases + if (symbol && symbol.flags & SymbolFlags.Alias) { + symbol = typeChecker.getAliasedSymbol(symbol); + } + + // import m = /**/ <-- It can only access namespace (if typing import = x. this would get member symbols and not namespace) + if (isInRightSideOfInternalImportEqualsDeclaration(location)) { + return !!(symbol.flags & SymbolFlags.Namespace); + } + + if (insideJsDocTagTypeExpression || + (!isContextTokenValueLocation(contextToken) && + (isPartOfTypeNode(location) || isContextTokenTypeLocation(contextToken)))) { + // Its a type, but you can reach it by namespace.type as well + return symbolCanbeReferencedAtTypeLocation(symbol); + } + } + + // expressions are value space (which includes the value namespaces) + return !!(symbol.flags & SymbolFlags.Value); + }); + } + + function isContextTokenValueLocation(contextToken: Node) { + return contextToken && + contextToken.kind === SyntaxKind.TypeOfKeyword && + contextToken.parent.kind === SyntaxKind.TypeQuery; + } + + function isContextTokenTypeLocation(contextToken: Node) { + if (contextToken) { + const parentKind = contextToken.parent.kind; + switch (contextToken.kind) { + case SyntaxKind.ColonToken: + return parentKind === SyntaxKind.PropertyDeclaration || + parentKind === SyntaxKind.PropertySignature || + parentKind === SyntaxKind.Parameter || + parentKind === SyntaxKind.VariableDeclaration || + isFunctionLikeKind(parentKind); + + case SyntaxKind.EqualsToken: + return parentKind === SyntaxKind.TypeAliasDeclaration; + + case SyntaxKind.AsKeyword: + return parentKind === SyntaxKind.AsExpression; + } + } + } + + function symbolCanbeReferencedAtTypeLocation(symbol: Symbol): boolean { + // This is an alias, follow what it aliases + if (symbol && symbol.flags & SymbolFlags.Alias) { + 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); + } + } + /** * Finds the first node that "embraces" the position, so that one may * accurately aggregate locals from the closest containing scope. @@ -1140,21 +1238,6 @@ namespace ts.Completions { return undefined; } - function isFunction(kind: SyntaxKind): boolean { - if (!isFunctionLikeKind(kind)) { - return false; - } - - switch (kind) { - case SyntaxKind.Constructor: - case SyntaxKind.ConstructorType: - case SyntaxKind.FunctionType: - return false; - default: - return true; - } - } - /** * @returns true if we are certain that the currently edited location must define a new location; false otherwise. */ @@ -1166,7 +1249,7 @@ namespace ts.Completions { containingNodeKind === SyntaxKind.VariableDeclarationList || containingNodeKind === SyntaxKind.VariableStatement || containingNodeKind === SyntaxKind.EnumDeclaration || // enum a { foo, | - isFunction(containingNodeKind) || + isFunctionLikeButNotConstructor(containingNodeKind) || containingNodeKind === SyntaxKind.ClassDeclaration || // class A= position) || // cursor in the leading trivia (child.kind === SyntaxKind.JsxText && start === child.end); // whitespace only JsxText diff --git a/tests/cases/fourslash/commentsInheritance.ts b/tests/cases/fourslash/commentsInheritance.ts index 6e3e92cfcff18..7afe18f400ce4 100644 --- a/tests/cases/fourslash/commentsInheritance.ts +++ b/tests/cases/fourslash/commentsInheritance.ts @@ -346,7 +346,7 @@ verify.quickInfos({ }); goTo.marker('16'); -verify.completionListContains("i1", "interface i1", "i1 is interface with properties"); +verify.not.completionListContains("i1", "interface i1", "i1 is interface with properties"); verify.completionListContains("i1_i", "var i1_i: i1", ""); verify.completionListContains("c1", "class c1", ""); verify.completionListContains("c1_i", "var c1_i: c1", ""); @@ -603,9 +603,9 @@ verify.quickInfos({ }); goTo.marker('51'); -verify.completionListContains("i2", "interface i2", ""); +verify.not.completionListContains("i2", "interface i2", ""); verify.completionListContains("i2_i", "var i2_i: i2", ""); -verify.completionListContains("i3", "interface i3", ""); +verify.not.completionListContains("i3", "interface i3", ""); verify.completionListContains("i3_i", "var i3_i: i3", ""); goTo.marker('51i'); diff --git a/tests/cases/fourslash/commentsInterface.ts b/tests/cases/fourslash/commentsInterface.ts index 472798fa8e1c5..7a09329a0fd27 100644 --- a/tests/cases/fourslash/commentsInterface.ts +++ b/tests/cases/fourslash/commentsInterface.ts @@ -163,11 +163,11 @@ verify.currentParameterHelpArgumentDocCommentIs(""); verify.quickInfoAt("33q", "(method) i2.nc_fnfoo(b: number): string"); goTo.marker('34'); -verify.completionListContains("i1", "interface i1", "this is interface 1"); +verify.not.completionListContains("i1", "interface i1", "this is interface 1"); verify.completionListContains("i1_i", "var i1_i: i1", ""); -verify.completionListContains("nc_i1", "interface nc_i1", ""); +verify.not.completionListContains("nc_i1", "interface nc_i1", ""); verify.completionListContains("nc_i1_i", "var nc_i1_i: nc_i1", ""); -verify.completionListContains("i2", "interface i2", "this is interface 2 with memebers"); +verify.not.completionListContains("i2", "interface i2", "this is interface 2 with memebers"); verify.completionListContains("i2_i", "var i2_i: i2", ""); verify.completionListContains("i2_i_x", "var i2_i_x: number", ""); verify.completionListContains("i2_i_foo", "var i2_i_foo: (b: number) => string", ""); @@ -194,7 +194,7 @@ verify.completionListContains("a", "(parameter) a: number", "i3_i a"); verify.quickInfoAt("40q", "var i3_i: i3"); goTo.marker('40'); -verify.completionListContains("i3", "interface i3", ""); +verify.not.completionListContains("i3", "interface i3", ""); verify.completionListContains("i3_i", "var i3_i: i3", ""); goTo.marker('41'); diff --git a/tests/cases/fourslash/commentsOverloads.ts b/tests/cases/fourslash/commentsOverloads.ts index ec4a63349f9c7..6add2609897ba 100644 --- a/tests/cases/fourslash/commentsOverloads.ts +++ b/tests/cases/fourslash/commentsOverloads.ts @@ -295,13 +295,13 @@ verify.completionListContains('f3', 'function f3(a: number): number (+1 overload verify.completionListContains('f4', 'function f4(a: number): number (+1 overload)', 'this is signature 4 - with number parameter'); goTo.marker('18'); -verify.completionListContains('i1', 'interface i1', ''); +verify.not.completionListContains('i1', 'interface i1', ''); verify.completionListContains('i1_i', 'var i1_i: new i1(b: number) => any (+1 overload)', ''); -verify.completionListContains('i2', 'interface i2', ''); +verify.not.completionListContains('i2', 'interface i2', ''); verify.completionListContains('i2_i', 'var i2_i: new i2(a: string) => any (+1 overload)', ''); -verify.completionListContains('i3', 'interface i3', ''); +verify.not.completionListContains('i3', 'interface i3', ''); verify.completionListContains('i3_i', 'var i3_i: new i3(a: string) => any (+1 overload)', 'new 1'); -verify.completionListContains('i4', 'interface i4', ''); +verify.not.completionListContains('i4', 'interface i4', ''); verify.completionListContains('i4_i', 'var i4_i: new i4(a: string) => any (+1 overload)', ''); goTo.marker('19'); diff --git a/tests/cases/fourslash/completionListAfterFunction2.ts b/tests/cases/fourslash/completionListAfterFunction2.ts index c123e0849724a..0dfbd4fb461a6 100644 --- a/tests/cases/fourslash/completionListAfterFunction2.ts +++ b/tests/cases/fourslash/completionListAfterFunction2.ts @@ -9,5 +9,6 @@ goTo.marker("1"); verify.not.completionListContains("a"); goTo.marker("2"); +verify.not.completionListContains("b"); +edit.insert("typeof "); verify.completionListContains("b"); - diff --git a/tests/cases/fourslash/completionListCladule.ts b/tests/cases/fourslash/completionListCladule.ts index 4225e6be26353..6d9e9145b66bc 100644 --- a/tests/cases/fourslash/completionListCladule.ts +++ b/tests/cases/fourslash/completionListCladule.ts @@ -8,7 +8,7 @@ //// export var x: number; ////} ////Foo/*c1*/; // should get "x", "prototype" -////var s: Foo/*c2*/; // should get "x" and "prototype" +////var s: Foo/*c2*/; // no types, in Foo, so shouldnt have anything ////var f = new Foo(); ////f/*c3*/; @@ -20,9 +20,7 @@ verify.completionListContains("staticMethod"); goTo.marker("c2"); edit.insert("."); -verify.completionListContains("x"); -verify.completionListContains("staticMethod"); -verify.completionListContains("prototype"); +verify.completionListIsEmpty(); goTo.marker("c3"); edit.insert("."); diff --git a/tests/cases/fourslash/completionListInClassExpressionWithTypeParameter.ts b/tests/cases/fourslash/completionListInClassExpressionWithTypeParameter.ts index 6f016b73a761a..47f030bf90706 100644 --- a/tests/cases/fourslash/completionListInClassExpressionWithTypeParameter.ts +++ b/tests/cases/fourslash/completionListInClassExpressionWithTypeParameter.ts @@ -1,13 +1,16 @@ -/// +/// //// var x = class myClass { //// getClassName (){ //// /*0*/ +//// var tmp: /*0Type*/; //// } //// prop: Ty/*1*/ //// } goTo.marker("0"); +verify.not.completionListContains("TypeParam", "(type parameter) TypeParam in myClass", /*documentation*/ undefined, "type parameter"); +goTo.marker("0Type"); verify.completionListContains("TypeParam", "(type parameter) TypeParam in myClass", /*documentation*/ undefined, "type parameter"); goTo.marker("1"); diff --git a/tests/cases/fourslash/completionListInClosedObjectTypeLiteralInSignature01.ts b/tests/cases/fourslash/completionListInClosedObjectTypeLiteralInSignature01.ts index 08f3b0e16b2f0..856d94492e664 100644 --- a/tests/cases/fourslash/completionListInClosedObjectTypeLiteralInSignature01.ts +++ b/tests/cases/fourslash/completionListInClosedObjectTypeLiteralInSignature01.ts @@ -14,5 +14,5 @@ verify.completionListContains("TString"); verify.completionListContains("TNumber"); // Ideally the following shouldn't show up since they're not types. -verify.completionListContains("foo"); -verify.completionListContains("obj"); \ No newline at end of file +verify.not.completionListContains("foo"); +verify.not.completionListContains("obj"); \ No newline at end of file diff --git a/tests/cases/fourslash/completionListInClosedObjectTypeLiteralInSignature02.ts b/tests/cases/fourslash/completionListInClosedObjectTypeLiteralInSignature02.ts index 36e9dc759e7ad..0472a9c04fa8c 100644 --- a/tests/cases/fourslash/completionListInClosedObjectTypeLiteralInSignature02.ts +++ b/tests/cases/fourslash/completionListInClosedObjectTypeLiteralInSignature02.ts @@ -14,5 +14,5 @@ verify.completionListContains("TString"); verify.completionListContains("TNumber"); // REVIEW: Is this intended behavior? // Ideally the following shouldn't show up since they're not types. -verify.completionListContains("foo"); -verify.completionListContains("obj"); \ No newline at end of file +verify.not.completionListContains("foo"); +verify.not.completionListContains("obj"); \ No newline at end of file diff --git a/tests/cases/fourslash/completionListInClosedObjectTypeLiteralInSignature03.ts b/tests/cases/fourslash/completionListInClosedObjectTypeLiteralInSignature03.ts index 388385f4c39ac..1dc34dcffd454 100644 --- a/tests/cases/fourslash/completionListInClosedObjectTypeLiteralInSignature03.ts +++ b/tests/cases/fourslash/completionListInClosedObjectTypeLiteralInSignature03.ts @@ -14,5 +14,5 @@ verify.completionListContains("TString"); verify.completionListContains("TNumber"); // REVIEW: Is this intended behavior? // Ideally the following shouldn't show up since they're not types. -verify.completionListContains("foo"); -verify.completionListContains("obj"); \ No newline at end of file +verify.not.completionListContains("foo"); +verify.not.completionListContains("obj"); \ No newline at end of file diff --git a/tests/cases/fourslash/completionListInExtendsClause.ts b/tests/cases/fourslash/completionListInExtendsClause.ts index b765f77d5d0c0..79451e4fd57eb 100644 --- a/tests/cases/fourslash/completionListInExtendsClause.ts +++ b/tests/cases/fourslash/completionListInExtendsClause.ts @@ -27,4 +27,4 @@ goTo.marker("3"); verify.completionListIsEmpty(); goTo.marker("4"); -verify.not.completionListIsEmpty(); \ No newline at end of file +verify.completionListIsEmpty(); \ No newline at end of file diff --git a/tests/cases/fourslash/completionListInScope.ts b/tests/cases/fourslash/completionListInScope.ts index 7488db8dd4296..8773f6d4588ed 100644 --- a/tests/cases/fourslash/completionListInScope.ts +++ b/tests/cases/fourslash/completionListInScope.ts @@ -85,11 +85,11 @@ verify.completionListContains("exportedInterface"); verify.completionListContains("localClass"); verify.completionListContains("exportedClass"); -verify.completionListContains("localModule"); -verify.completionListContains("exportedModule"); +verify.not.completionListContains("localModule"); +verify.not.completionListContains("exportedModule"); verify.completionListContains("exportedClass2"); -verify.completionListContains("exportedModule2"); +verify.not.completionListContains("exportedModule2"); goTo.marker("insideMethod"); verify.not.completionListContains("property"); diff --git a/tests/cases/fourslash/completionListInTypeParameterOfTypeAlias1.ts b/tests/cases/fourslash/completionListInTypeParameterOfTypeAlias1.ts index e6017eedbfcb3..57931c7b6d1de 100644 --- a/tests/cases/fourslash/completionListInTypeParameterOfTypeAlias1.ts +++ b/tests/cases/fourslash/completionListInTypeParameterOfTypeAlias1.ts @@ -1,4 +1,4 @@ -/// +/// ////type List1 = T[]; @@ -8,7 +8,7 @@ goTo.marker("0"); verify.completionListIsEmpty(); goTo.marker("1"); -verify.not.completionListIsEmpty(); +verify.completionListIsEmpty(); goTo.marker("2"); verify.completionListContains("T"); goTo.marker("3"); diff --git a/tests/cases/fourslash/completionListInTypeParameterOfTypeAlias2.ts b/tests/cases/fourslash/completionListInTypeParameterOfTypeAlias2.ts index 80a910da79858..44f7342029e55 100644 --- a/tests/cases/fourslash/completionListInTypeParameterOfTypeAlias2.ts +++ b/tests/cases/fourslash/completionListInTypeParameterOfTypeAlias2.ts @@ -1,4 +1,4 @@ -/// +/// ////type Map1 = []; @@ -8,12 +8,12 @@ goTo.marker("0"); verify.completionListIsEmpty(); goTo.marker("1"); -verify.completionListContains("V"); +verify.completionListIsEmpty(); goTo.marker("2"); verify.completionListContains("K"); verify.completionListContains("V"); goTo.marker("3"); verify.not.completionListContains("K"); verify.not.completionListContains("V"); -verify.completionListContains("K1"); -verify.completionListContains("V1"); \ No newline at end of file +verify.not.completionListContains("K1"); +verify.not.completionListContains("V1"); \ No newline at end of file diff --git a/tests/cases/fourslash/completionListInTypeParameterOfTypeAlias3.ts b/tests/cases/fourslash/completionListInTypeParameterOfTypeAlias3.ts index e383174225779..a523aec98b368 100644 --- a/tests/cases/fourslash/completionListInTypeParameterOfTypeAlias3.ts +++ b/tests/cases/fourslash/completionListInTypeParameterOfTypeAlias3.ts @@ -1,13 +1,13 @@ -/// +/// //// type constructorType = new +/// ////var x : (s/*1*/ ////var y : (s:string, list/*2*/ -goTo.eachMarker(() => { - verify.not.completionListIsEmpty(); - verify.completionListAllowsNewIdentifier(); -}); +goTo.marker("1"); +verify.not.completionListIsEmpty();// As this can either be type or become arrow function parameter +verify.completionListAllowsNewIdentifier(); + +goTo.marker("2"); +verify.completionListIsEmpty(); // Parameter name +verify.completionListAllowsNewIdentifier(); \ No newline at end of file diff --git a/tests/cases/fourslash/completionListOnAliases2.ts b/tests/cases/fourslash/completionListOnAliases2.ts index 7ff50a1a2b57e..63f895f276e8d 100644 --- a/tests/cases/fourslash/completionListOnAliases2.ts +++ b/tests/cases/fourslash/completionListOnAliases2.ts @@ -25,23 +25,47 @@ ////import a = M.A; //// ////m./*1*/; +////var tmp: m./*1Type*/; ////c./*2*/; ////e./*3*/; ////n./*4*/; ////v./*5*/; ////f./*6*/; ////a./*7*/; +////var tmp2: a./*7Type*/; + +function getVerify(isTypeLocation?: boolean) { + return { + verifyValue: isTypeLocation ? verify.not : verify, + verifyType: isTypeLocation ? verify : verify.not, + verifyValueOrType: verify + }; +} +function typeLocationVerify(valueMarker: string, verify: (typeMarker: string) => void) { + verify(valueMarker + "Type"); + return valueMarker; +} + +function verifyModuleM(marker: string) { + const isTypeLocation = marker.indexOf("Type") !== -1; + const { verifyValue, verifyType, verifyValueOrType } = getVerify(isTypeLocation); + if (!isTypeLocation) { + marker = typeLocationVerify(marker, verifyModuleM); + } + goTo.marker(marker); + + verifyType.completionListContains("I"); + verifyValueOrType.completionListContains("C"); + verifyValueOrType.completionListContains("E"); + verifyValue.completionListContains("N"); + verifyValue.completionListContains("V"); + verifyValue.completionListContains("F"); + verifyValueOrType.completionListContains("A"); +} // Module m -goTo.marker("1"); -verify.completionListContains("I"); -verify.completionListContains("C"); -verify.completionListContains("E"); -verify.completionListContains("N"); -verify.completionListContains("V"); -verify.completionListContains("F"); -verify.completionListContains("A"); +verifyModuleM("1"); // Class C goTo.marker("2"); @@ -64,11 +88,4 @@ goTo.marker("6"); verify.completionListContains("call"); // alias a -goTo.marker("7"); -verify.completionListContains("I"); -verify.completionListContains("C"); -verify.completionListContains("E"); -verify.completionListContains("N"); -verify.completionListContains("V"); -verify.completionListContains("F"); -verify.completionListContains("A"); +verifyModuleM("7"); \ No newline at end of file diff --git a/tests/cases/fourslash/completionListOnParamInClass.ts b/tests/cases/fourslash/completionListOnParamInClass.ts index 25eaaa872ead4..44c1c22d5c852 100644 --- a/tests/cases/fourslash/completionListOnParamInClass.ts +++ b/tests/cases/fourslash/completionListOnParamInClass.ts @@ -5,5 +5,5 @@ ////} goTo.marker(); -verify.completionListContains('parseInt'); - +verify.not.completionListContains('parseInt'); +verify.completionListContains('encoder'); diff --git a/tests/cases/fourslash/completionListWithMeanings.ts b/tests/cases/fourslash/completionListWithMeanings.ts new file mode 100644 index 0000000000000..61dc95adca8b1 --- /dev/null +++ b/tests/cases/fourslash/completionListWithMeanings.ts @@ -0,0 +1,70 @@ +/// + +////namespace m { export interface point2 { } } +////namespace m2 { export var zz = 10; } +////namespace m3 { export var zz2 = 10; export interface point3 { } } +////interface point { +//// x: number; +//// y: number; +////} +////var xx = 10; +////var tt = /*valueExpr*/xx; +////var yy: /*typeExpr*/point = { x: 4, y: 3 + /*valueExprInObjectLiteral*/tt }; +////var kk: m3.point3/*membertypeExpr*/ = m3.zz2/*membervalueExpr*/; +////var zz = { x: 4, y: 3 }; + +const markers = test.markerNames(); + +function getVerifyBasedOnMarker(marker: string, meaning: string) { + return marker.indexOf(meaning) === 0 ? verify : verify.not; +} + +function verifyCompletions(verify: FourSlashInterface.verifyNegatable, completions: CompletionInfo[]) { + for (const info of completions) { + verify.completionListContains(info[0], info[1]); + } +} + +type CompletionInfo = [string, string]; +function verifyCompletionsExistForMeaning(marker: string, meaning: string, completions: CompletionInfo[]) { + verifyCompletions(getVerifyBasedOnMarker(marker, meaning), completions); +} + +function verifyCompletionsDoNotExistForMeaning(marker: string, meaning: string, completions: CompletionInfo[]) { + verifyCompletions(getVerifyBasedOnMarker(marker, meaning) === verify.not ? verify : verify.not, completions); +} + +const values: CompletionInfo[] = [ + ["xx", "var xx: number"], + ["tt", "var tt: number"], + ["yy", "var yy: point"], + ["zz", "var zz: point"], + ["m2", "namespace m2"], // With no type side, allowed only in value +]; + +const types: CompletionInfo[] = [ + ["point", "interface point"], + ["m", "namespace m"], // Uninstantiated namespace only allowed at type locations +]; + +const namespaces: CompletionInfo[] = [ + ["m3", "namespace m3"], // Has both type and values, allowed in all locations +]; + +const membervalues: CompletionInfo[] = [ + ["zz2", "var m3.zz2: number"], +]; + + +const membertypes: CompletionInfo[] = [ + ["point3", "interface m3.point3"], +]; + +for (const marker of markers) { + goTo.marker(marker); + verifyCompletionsExistForMeaning(marker, "value", values); + verifyCompletionsExistForMeaning(marker, "type", types); + verifyCompletionsExistForMeaning(marker, "membervalue", membervalues); + verifyCompletionsExistForMeaning(marker, "membertype", membertypes); + verifyCompletionsDoNotExistForMeaning(marker, "member", namespaces); +} \ No newline at end of file diff --git a/tests/cases/fourslash/completionListWithModulesFromModule.ts b/tests/cases/fourslash/completionListWithModulesFromModule.ts index 3a1f3daa29edd..462faa5ebf510 100644 --- a/tests/cases/fourslash/completionListWithModulesFromModule.ts +++ b/tests/cases/fourslash/completionListWithModulesFromModule.ts @@ -191,6 +191,7 @@ //// sifn(shadow: any): any; //// } //// /*shadowNamespaceWithNoExport*/ +//// var tmp: /*shadowNamespaceWithNoExportType*/ ////} //// ////namespace mod4 { @@ -214,12 +215,14 @@ //// sifn(shadow: any): any; //// } //// /*shadowNamespaceWithExport*/ +//// var tmp: /*shadowNamespaceWithExportType*/ ////} //// ////namespace mod5 { //// import Mod1 = mod1; //// import iMod1 = mod1.mod1emod; //// /*namespaceWithImport*/ +//// var tmp: /*namespaceWithImportType*/ ////} //// ////function shwfn() { @@ -276,51 +279,87 @@ function goToMarkAndVerifyShadow() verify.not.completionListContains('mod2emod'); } +function getVerify(isTypeLocation?: boolean) { + return { + verifyValue: isTypeLocation ? verify.not : verify, + verifyType: isTypeLocation ? verify : verify.not, + verifyValueOrType: verify + }; +} + +function typeLocationVerify(valueMarker: string, verify: (typeMarker: string) => void) { + verify(valueMarker + "Type"); + return valueMarker; +} // from a shadow namespace with no export -goTo.marker('shadowNamespaceWithNoExport'); -verify.completionListContains('shwvar', 'var shwvar: string'); -verify.completionListContains('shwfn', 'function shwfn(shadow: any): void'); -verify.completionListContains('shwcls', 'class shwcls'); -verify.completionListContains('shwint', 'interface shwint'); -goToMarkAndVerifyShadow(); +verifyShadowNamespaceWithNoExport(); +function verifyShadowNamespaceWithNoExport(marker?: string) { + const { verifyValue, verifyType, verifyValueOrType } = getVerify(!!marker); + if (!marker) { + marker = typeLocationVerify('shadowNamespaceWithNoExport', verifyShadowNamespaceWithNoExport); + } + goTo.marker(marker); + + verifyValue.completionListContains('shwvar', 'var shwvar: string'); + verifyValue.completionListContains('shwfn', 'function shwfn(shadow: any): void'); + verifyValueOrType.completionListContains('shwcls', 'class shwcls'); + verifyType.completionListContains('shwint', 'interface shwint'); + + goToMarkAndVerifyShadow(); +} // from a shadow namespace with export -goTo.marker('shadowNamespaceWithExport'); -verify.completionListContains('shwvar', 'var mod4.shwvar: string'); -verify.completionListContains('shwfn', 'function mod4.shwfn(shadow: any): void'); -verify.completionListContains('shwcls', 'class mod4.shwcls'); -verify.completionListContains('shwint', 'interface mod4.shwint'); -goToMarkAndVerifyShadow(); +verifyShadowNamespaceWithNoExport(); +function verifyShadowNamespaceWithExport(marker?: string) { + const { verifyValue, verifyType, verifyValueOrType } = getVerify(!!marker); + if (!marker) { + marker = typeLocationVerify('shadowNamespaceWithExport', verifyShadowNamespaceWithExport); + } + goTo.marker(marker); + verifyValue.completionListContains('shwvar', 'var mod4.shwvar: string'); + verifyValue.completionListContains('shwfn', 'function mod4.shwfn(shadow: any): void'); + verifyValueOrType.completionListContains('shwcls', 'class mod4.shwcls'); + verifyType.completionListContains('shwint', 'interface mod4.shwint'); + goToMarkAndVerifyShadow(); +} // from a namespace with import -goTo.marker('namespaceWithImport'); -verify.completionListContains('mod1', 'namespace mod1'); -verify.completionListContains('mod2', 'namespace mod2'); -verify.completionListContains('mod3', 'namespace mod3'); -verify.completionListContains('shwvar', 'var shwvar: number'); -verify.completionListContains('shwfn', 'function shwfn(): void'); -verify.completionListContains('shwcls', 'class shwcls'); -verify.completionListContains('shwint', 'interface shwint'); +verifyShadowNamespaceWithNoExport(); +function verifyNamespaceWithImport(marker?: string) { + const { verifyValue, verifyType, verifyValueOrType } = getVerify(!!marker); + if (!marker) { + marker = typeLocationVerify('namespaceWithImport', verifyNamespaceWithImport); + } + goTo.marker(marker); -sharedNegativeVerify(); + verifyValue.completionListContains('mod1', 'namespace mod1'); + verifyValue.completionListContains('mod2', 'namespace mod2'); + verifyValue.completionListContains('mod3', 'namespace mod3'); + verifyValue.completionListContains('shwvar', 'var shwvar: number'); + verifyValue.completionListContains('shwfn', 'function shwfn(): void'); + verifyValueOrType.completionListContains('shwcls', 'class shwcls'); + verifyType.completionListContains('shwint', 'interface shwint'); + + sharedNegativeVerify(); -verify.not.completionListContains('mod1var'); -verify.not.completionListContains('mod1fn'); -verify.not.completionListContains('mod1cls'); -verify.not.completionListContains('mod1int'); -verify.not.completionListContains('mod1mod'); -verify.not.completionListContains('mod1evar'); -verify.not.completionListContains('mod1efn'); -verify.not.completionListContains('mod1ecls'); -verify.not.completionListContains('mod1eint'); -verify.not.completionListContains('mod1emod'); -verify.not.completionListContains('mX'); -verify.not.completionListContains('mFunc'); -verify.not.completionListContains('mClass'); -verify.not.completionListContains('mInt'); -verify.not.completionListContains('mMod'); -verify.not.completionListContains('meX'); -verify.not.completionListContains('meFunc'); -verify.not.completionListContains('meClass'); -verify.not.completionListContains('meInt'); -verify.not.completionListContains('meMod'); \ No newline at end of file + verify.not.completionListContains('mod1var'); + verify.not.completionListContains('mod1fn'); + verify.not.completionListContains('mod1cls'); + verify.not.completionListContains('mod1int'); + verify.not.completionListContains('mod1mod'); + verify.not.completionListContains('mod1evar'); + verify.not.completionListContains('mod1efn'); + verify.not.completionListContains('mod1ecls'); + verify.not.completionListContains('mod1eint'); + verify.not.completionListContains('mod1emod'); + verify.not.completionListContains('mX'); + verify.not.completionListContains('mFunc'); + verify.not.completionListContains('mClass'); + verify.not.completionListContains('mInt'); + verify.not.completionListContains('mMod'); + verify.not.completionListContains('meX'); + verify.not.completionListContains('meFunc'); + verify.not.completionListContains('meClass'); + verify.not.completionListContains('meInt'); + verify.not.completionListContains('meMod'); +} \ No newline at end of file diff --git a/tests/cases/fourslash/completionListWithModulesInsideModuleScope.ts b/tests/cases/fourslash/completionListWithModulesInsideModuleScope.ts index 916ad10fe9c21..5d950a5d62091 100644 --- a/tests/cases/fourslash/completionListWithModulesInsideModuleScope.ts +++ b/tests/cases/fourslash/completionListWithModulesInsideModuleScope.ts @@ -62,6 +62,7 @@ //// namespace m1Mod { } //// export namespace m1eMod { } //// /*namespace*/ +//// var tmp: /*namespaceType*/ //// } //// export var mod1evar = 1; //// export function mod1efn() { @@ -124,8 +125,10 @@ //// namespace mMod { } //// export namespace meMod { } //// /*exportedNamespace*/ +//// var tmp: /*exportedNamespaceType*/ //// } //// /*mod1*/ +//// var tmp: /*mod1Type*/; ////} //// ////// EXTENDING NAMESPACE 1 @@ -133,6 +136,7 @@ //// export var mod1eexvar = 1; //// var mod1exvar = 2; //// /*extendedNamespace*/ +//// var tmp: /*extendedNamespaceType*/; ////} //// ////namespace mod2 { @@ -225,28 +229,46 @@ //// ////var shwvar = 1; -function goToMarkAndGeneralVerify(marker: string, isClassScope?: boolean) +interface GotoMarkVerifyOptions { + isClassScope?: boolean; + isTypeLocation?: boolean; +} + +function getVerify(isTypeLocation: boolean) { + return { + verifyValue: isTypeLocation ? verify.not : verify, + verifyType: isTypeLocation ? verify : verify.not, + verifyValueOrType: verify, + verifyNotValueOrType: verify.not, + }; +} + +function goToMarkAndGeneralVerify(marker: string, { isClassScope, isTypeLocation }: GotoMarkVerifyOptions = {}) { goTo.marker(marker); - const verifyModule = isClassScope ? verify.not : verify; - verifyModule.completionListContains('mod1var', 'var mod1var: number'); - verifyModule.completionListContains('mod1fn', 'function mod1fn(): void'); - verifyModule.completionListContains('mod1cls', 'class mod1cls'); - verifyModule.completionListContains('mod1int', 'interface mod1int'); - verifyModule.completionListContains('mod1mod', 'namespace mod1mod'); - verifyModule.completionListContains('mod1evar', 'var mod1.mod1evar: number'); - verifyModule.completionListContains('mod1efn', 'function mod1.mod1efn(): void'); - verifyModule.completionListContains('mod1ecls', 'class mod1.mod1ecls'); - verifyModule.completionListContains('mod1eint', 'interface mod1.mod1eint'); - verifyModule.completionListContains('mod1emod', 'namespace mod1.mod1emod'); - verifyModule.completionListContains('mod1eexvar', 'var mod1.mod1eexvar: number'); - verifyModule.completionListContains('mod2', 'namespace mod2'); - verifyModule.completionListContains('mod3', 'namespace mod3'); - verifyModule.completionListContains('shwvar', 'var shwvar: number'); - verifyModule.completionListContains('shwfn', 'function shwfn(): void'); - verifyModule.completionListContains('shwcls', 'class shwcls'); - verifyModule.completionListContains('shwint', 'interface shwint'); + const verifyValueInModule = isClassScope || isTypeLocation ? verify.not : verify; + const verifyValueOrTypeInModule = isClassScope ? verify.not : verify; + const verifyTypeInModule = isTypeLocation ? verify : verify.not; + verifyValueInModule.completionListContains('mod1var', 'var mod1var: number'); + verifyValueInModule.completionListContains('mod1fn', 'function mod1fn(): void'); + verifyValueInModule.completionListContains('mod1evar', 'var mod1.mod1evar: number'); + verifyValueInModule.completionListContains('mod1efn', 'function mod1.mod1efn(): void'); + verifyValueInModule.completionListContains('mod1eexvar', 'var mod1.mod1eexvar: number'); + verifyValueInModule.completionListContains('mod3', 'namespace mod3'); + verifyValueInModule.completionListContains('shwvar', 'var shwvar: number'); + verifyValueInModule.completionListContains('shwfn', 'function shwfn(): void'); + + verifyTypeInModule.completionListContains('mod1int', 'interface mod1int'); + verifyTypeInModule.completionListContains('mod1eint', 'interface mod1.mod1eint'); + verifyTypeInModule.completionListContains('shwint', 'interface shwint'); + + verifyValueOrTypeInModule.completionListContains('mod1cls', 'class mod1cls'); + verifyValueOrTypeInModule.completionListContains('mod1mod', 'namespace mod1mod'); + verifyValueOrTypeInModule.completionListContains('mod1ecls', 'class mod1.mod1ecls'); + verifyValueOrTypeInModule.completionListContains('mod1emod', 'namespace mod1.mod1emod'); + verifyValueOrTypeInModule.completionListContains('mod2', 'namespace mod2'); + verifyValueOrTypeInModule.completionListContains('shwcls', 'class shwcls'); verify.not.completionListContains('mod2var'); verify.not.completionListContains('mod2fn'); @@ -274,6 +296,8 @@ function goToMarkAndGeneralVerify(marker: string, isClassScope?: boolean) // from mod1 goToMarkAndGeneralVerify('mod1'); +// from mod1 in type position +goToMarkAndGeneralVerify('mod1Type', { isTypeLocation: true }); // from function in mod1 goToMarkAndGeneralVerify('function'); @@ -281,7 +305,7 @@ verify.completionListContains('bar', '(local var) bar: number'); verify.completionListContains('foob', '(local function) foob(): void'); // from class in mod1 -goToMarkAndGeneralVerify('class', /*isClassScope*/ true); +goToMarkAndGeneralVerify('class', { isClassScope: true }); //verify.not.completionListContains('ceFunc'); //verify.not.completionListContains('ceVar'); @@ -289,17 +313,28 @@ goToMarkAndGeneralVerify('class', /*isClassScope*/ true); goToMarkAndGeneralVerify('interface'); // from namespace in mod1 -goToMarkAndGeneralVerify('namespace'); -verify.completionListContains('m1X', 'var m1X: number'); -verify.completionListContains('m1Func', 'function m1Func(): void'); -verify.completionListContains('m1Class', 'class m1Class'); -verify.completionListContains('m1Int', 'interface m1Int'); -verify.completionListContains('m1Mod', 'namespace m1Mod'); -verify.completionListContains('m1eX', 'var mod1mod.m1eX: number'); -verify.completionListContains('m1eFunc', 'function mod1mod.m1eFunc(): void'); -verify.completionListContains('m1eClass', 'class mod1mod.m1eClass'); -verify.completionListContains('m1eInt', 'interface mod1mod.m1eInt'); -verify.completionListContains('m1eMod', 'namespace mod1mod.m1eMod'); +verifyNamespaceInMod1('namespace'); +verifyNamespaceInMod1('namespaceType', /*isTypeLocation*/ true); + +function verifyNamespaceInMod1(marker: string, isTypeLocation?: boolean) { + goToMarkAndGeneralVerify(marker, { isTypeLocation }); + + const { verifyValue, verifyType, verifyValueOrType, verifyNotValueOrType } = getVerify(isTypeLocation); + + verifyValue.completionListContains('m1X', 'var m1X: number'); + verifyValue.completionListContains('m1Func', 'function m1Func(): void'); + verifyValue.completionListContains('m1eX', 'var mod1mod.m1eX: number'); + verifyValue.completionListContains('m1eFunc', 'function mod1mod.m1eFunc(): void'); + + verifyType.completionListContains('m1Int', 'interface m1Int'); + verifyType.completionListContains('m1eInt', 'interface mod1mod.m1eInt'); + + verifyValueOrType.completionListContains('m1Class', 'class m1Class'); + verifyValueOrType.completionListContains('m1eClass', 'class mod1mod.m1eClass'); + + verifyNotValueOrType.completionListContains('m1Mod', 'namespace m1Mod'); + verifyNotValueOrType.completionListContains('m1eMod', 'namespace mod1mod.m1eMod'); +} // from exported function in mod1 goToMarkAndGeneralVerify('exportedFunction'); @@ -307,59 +342,77 @@ verify.completionListContains('bar', '(local var) bar: number'); verify.completionListContains('foob', '(local function) foob(): void'); // from exported class in mod1 -goToMarkAndGeneralVerify('exportedClass', /*isClassScope*/ true); -//verify.not.completionListContains('ceFunc'); -//verify.not.completionListContains('ceVar'); +goToMarkAndGeneralVerify('exportedClass', { isClassScope: true }); +verify.not.completionListContains('ceFunc'); +verify.not.completionListContains('ceVar'); // from exported interface in mod1 goToMarkAndGeneralVerify('exportedInterface'); // from exported namespace in mod1 -goToMarkAndGeneralVerify('exportedNamespace'); -verify.completionListContains('mX', 'var mX: number'); -verify.completionListContains('mFunc', 'function mFunc(): void'); -verify.completionListContains('mClass', 'class mClass'); -verify.completionListContains('mInt', 'interface mInt'); -verify.completionListContains('mMod', 'namespace mMod'); -verify.completionListContains('meX', 'var mod1.mod1emod.meX: number'); -verify.completionListContains('meFunc', 'function mod1.mod1emod.meFunc(): void'); -verify.completionListContains('meClass', 'class mod1.mod1emod.meClass'); -verify.completionListContains('meInt', 'interface mod1.mod1emod.meInt'); -verify.completionListContains('meMod', 'namespace mod1.mod1emod.meMod'); +verifyExportedNamespace('exportedNamespace'); +verifyExportedNamespace('exportedNamespaceType', /*isTypeLocation*/ true); +function verifyExportedNamespace(marker: string, isTypeLocation?: boolean) { + goToMarkAndGeneralVerify(marker, { isTypeLocation }); + const { verifyValue, verifyType, verifyValueOrType, verifyNotValueOrType } = getVerify(isTypeLocation); + verifyValue.completionListContains('mX', 'var mX: number'); + verifyValue.completionListContains('mFunc', 'function mFunc(): void'); + verifyValue.completionListContains('meX', 'var mod1.mod1emod.meX: number'); + verifyValue.completionListContains('meFunc', 'function mod1.mod1emod.meFunc(): void'); + + verifyType.completionListContains('mInt', 'interface mInt'); + verifyType.completionListContains('meInt', 'interface mod1.mod1emod.meInt'); + + verifyValueOrType.completionListContains('mClass', 'class mClass'); + verifyValueOrType.completionListContains('meClass', 'class mod1.mod1emod.meClass'); + + verifyNotValueOrType.completionListContains('mMod', 'namespace mMod'); + verifyNotValueOrType.completionListContains('meMod', 'namespace mod1.mod1emod.meMod'); +} // from extended namespace -goTo.marker('extendedNamespace'); -verify.completionListContains('mod1evar', 'var mod1.mod1evar: number'); -verify.completionListContains('mod1efn', 'function mod1.mod1efn(): void'); -verify.completionListContains('mod1ecls', 'class mod1.mod1ecls'); -verify.completionListContains('mod1eint', 'interface mod1.mod1eint'); -verify.completionListContains('mod1emod', 'namespace mod1.mod1emod'); -verify.completionListContains('mod1eexvar', 'var mod1.mod1eexvar: number'); -verify.completionListContains('mod2', 'namespace mod2'); -verify.completionListContains('mod3', 'namespace mod3'); -verify.completionListContains('shwvar', 'var shwvar: number'); -verify.completionListContains('shwfn', 'function shwfn(): void'); -verify.completionListContains('shwcls', 'class shwcls'); -verify.completionListContains('shwint', 'interface shwint'); - -verify.not.completionListContains('mod2var'); -verify.not.completionListContains('mod2fn'); -verify.not.completionListContains('mod2cls'); -verify.not.completionListContains('mod2int'); -verify.not.completionListContains('mod2mod'); -verify.not.completionListContains('mod2evar'); -verify.not.completionListContains('mod2efn'); -verify.not.completionListContains('mod2ecls'); -verify.not.completionListContains('mod2eint'); -verify.not.completionListContains('mod2emod'); -verify.not.completionListContains('sfvar'); -verify.not.completionListContains('sffn'); -verify.not.completionListContains('scvar'); -verify.not.completionListContains('scfn'); -verify.not.completionListContains('scpfn'); -verify.not.completionListContains('scpvar'); -verify.not.completionListContains('scsvar'); -verify.not.completionListContains('scsfn'); -verify.not.completionListContains('sivar'); -verify.not.completionListContains('sifn'); -verify.not.completionListContains('mod2eexvar'); \ No newline at end of file +verifyExtendedNamespace('extendedNamespace'); +verifyExtendedNamespace('extendedNamespaceType', /*isTypeLocation*/ true); + +function verifyExtendedNamespace(marker: string, isTypeLocation?: boolean) { + goTo.marker(marker); + const { verifyValue, verifyType, verifyValueOrType, verifyNotValueOrType } = getVerify(isTypeLocation); + + verifyValue.completionListContains('mod1evar', 'var mod1.mod1evar: number'); + verifyValue.completionListContains('mod1efn', 'function mod1.mod1efn(): void'); + verifyValue.completionListContains('mod1eexvar', 'var mod1.mod1eexvar: number'); + verifyValue.completionListContains('mod3', 'namespace mod3'); + verifyValue.completionListContains('shwvar', 'var shwvar: number'); + verifyValue.completionListContains('shwfn', 'function shwfn(): void'); + + verifyType.completionListContains('mod1eint', 'interface mod1.mod1eint'); + verifyType.completionListContains('shwint', 'interface shwint'); + + verifyValueOrType.completionListContains('mod1ecls', 'class mod1.mod1ecls'); + verifyValueOrType.completionListContains('mod1emod', 'namespace mod1.mod1emod'); + verifyValueOrType.completionListContains('mod2', 'namespace mod2'); + verifyValueOrType.completionListContains('shwcls', 'class shwcls'); + + + verify.not.completionListContains('mod2var'); + verify.not.completionListContains('mod2fn'); + verify.not.completionListContains('mod2cls'); + verify.not.completionListContains('mod2int'); + verify.not.completionListContains('mod2mod'); + verify.not.completionListContains('mod2evar'); + verify.not.completionListContains('mod2efn'); + verify.not.completionListContains('mod2ecls'); + verify.not.completionListContains('mod2eint'); + verify.not.completionListContains('mod2emod'); + verify.not.completionListContains('sfvar'); + verify.not.completionListContains('sffn'); + verify.not.completionListContains('scvar'); + verify.not.completionListContains('scfn'); + verify.not.completionListContains('scpfn'); + verify.not.completionListContains('scpvar'); + verify.not.completionListContains('scsvar'); + verify.not.completionListContains('scsfn'); + verify.not.completionListContains('sivar'); + verify.not.completionListContains('sifn'); + verify.not.completionListContains('mod2eexvar'); +} \ No newline at end of file diff --git a/tests/cases/fourslash/completionListWithModulesOutsideModuleScope.ts b/tests/cases/fourslash/completionListWithModulesOutsideModuleScope.ts index d6c44f4b7ebf6..c72159b002799 100644 --- a/tests/cases/fourslash/completionListWithModulesOutsideModuleScope.ts +++ b/tests/cases/fourslash/completionListWithModulesOutsideModuleScope.ts @@ -266,7 +266,7 @@ verify.completionListContains('mod3', 'namespace mod3'); verify.completionListContains('shwvar', 'var shwvar: number'); verify.completionListContains('shwfn', 'function shwfn(): void'); verify.completionListContains('shwcls', 'class shwcls'); -verify.completionListContains('shwint', 'interface shwint'); +verify.not.completionListContains('shwint', 'interface shwint'); verifyNotContainFunctionMembers(); verifyNotContainClassMembers(); diff --git a/tests/cases/fourslash/completionListWithModulesOutsideModuleScope2.ts b/tests/cases/fourslash/completionListWithModulesOutsideModuleScope2.ts index 340d0bd31913d..c8aa1933defa5 100644 --- a/tests/cases/fourslash/completionListWithModulesOutsideModuleScope2.ts +++ b/tests/cases/fourslash/completionListWithModulesOutsideModuleScope2.ts @@ -274,7 +274,7 @@ function goToMarkerAndVerify(marker: string) verify.completionListContains('shwvar', 'var shwvar: number'); verify.completionListContains('shwfn', 'function shwfn(): void'); verify.completionListContains('shwcls', 'class shwcls'); - verify.completionListContains('shwint', 'interface shwint'); + verify.not.completionListContains('shwint', 'interface shwint'); verify.not.completionListContains('mod2var'); verify.not.completionListContains('mod2fn'); diff --git a/tests/cases/fourslash/completionWithNamespaceInsideFunction.ts b/tests/cases/fourslash/completionWithNamespaceInsideFunction.ts index fb537bca71a12..f9259dd2eed2f 100644 --- a/tests/cases/fourslash/completionWithNamespaceInsideFunction.ts +++ b/tests/cases/fourslash/completionWithNamespaceInsideFunction.ts @@ -10,15 +10,37 @@ //// /*2*/ ////} /////*3*/ +////function f2() { +//// namespace n2 { +//// class I2 { +//// x: number +//// } +//// /*11*/ +//// } +//// /*22*/ +////} +/////*33*/ goTo.marker('1'); verify.completionListContains("f", "function f(): void"); -verify.completionListContains("n", "namespace n"); -verify.completionListContains("I", "interface I"); +verify.not.completionListContains("n", "namespace n"); +verify.not.completionListContains("I", "interface I"); goTo.marker('2'); verify.completionListContains("f", "function f(): void"); -verify.completionListContains("n", "namespace n"); +verify.not.completionListContains("n", "namespace n"); goTo.marker('3'); -verify.completionListContains("f", "function f(): void"); \ No newline at end of file +verify.completionListContains("f", "function f(): void"); + +goTo.marker('11'); +verify.completionListContains("f2", "function f2(): void"); +verify.completionListContains("n2", "namespace n2"); +verify.completionListContains("I2", "class I2"); + +goTo.marker('22'); +verify.completionListContains("f2", "function f2(): void"); +verify.completionListContains("n2", "namespace n2"); + +goTo.marker('33'); +verify.completionListContains("f2", "function f2(): void"); \ No newline at end of file diff --git a/tests/cases/fourslash/externalModuleWithExportAssignment.ts b/tests/cases/fourslash/externalModuleWithExportAssignment.ts index 2c68934e49e38..90009fe9d4628 100644 --- a/tests/cases/fourslash/externalModuleWithExportAssignment.ts +++ b/tests/cases/fourslash/externalModuleWithExportAssignment.ts @@ -56,8 +56,8 @@ goTo.marker('9'); verify.quickInfoIs("(property) test1: a1.connectModule(res: any, req: any, next: any) => void", undefined); verify.completionListContains("test1", "(property) test1: a1.connectModule(res: any, req: any, next: any) => void", undefined); verify.completionListContains("test2", "(method) test2(): a1.connectModule", undefined); -verify.completionListContains("connectModule"); -verify.completionListContains("connectExport"); +verify.not.completionListContains("connectModule"); +verify.not.completionListContains("connectExport"); goTo.marker('10'); verify.currentSignatureHelpIs("test1(res: any, req: any, next: any): void"); diff --git a/tests/cases/fourslash/jsFileJsdocTypedefTagTypeExpressionCompletion.ts b/tests/cases/fourslash/jsFileJsdocTypedefTagTypeExpressionCompletion.ts new file mode 100644 index 0000000000000..d6c3ca4f91468 --- /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 VerifyCompletionsInJsDoc { + 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 }: VerifyCompletionsInJsDoc) { + 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 0000000000000..038c5db55283b --- /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 VerifyCompletionsInJsDoc { + 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 }: VerifyCompletionsInJsDoc) { + 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 0000000000000..66c3856d0b745 --- /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 0000000000000..379cc60e0587b --- /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 diff --git a/tests/cases/fourslash/memberListOfModule.ts b/tests/cases/fourslash/memberListOfModule.ts index 4724691c0a77c..0e095c94cbd95 100644 --- a/tests/cases/fourslash/memberListOfModule.ts +++ b/tests/cases/fourslash/memberListOfModule.ts @@ -14,6 +14,6 @@ ////var x: Foo./**/ goTo.marker(); -verify.completionListCount(2); +verify.completionListCount(1); verify.completionListContains('Bar'); -verify.completionListContains('Blah'); \ No newline at end of file +verify.not.completionListContains('Blah'); \ No newline at end of file