Merge branch 'completionWithMeaning'

This commit is contained in:
Mohamed Hegazy 2017-06-13 17:41:34 -07:00
commit 68008915d6
40 changed files with 1000 additions and 279 deletions

View File

@ -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"))

View File

@ -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 });

View File

@ -14593,12 +14593,31 @@ namespace ts {
? (<PropertyAccessExpression>node).expression
: (<QualifiedName>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 (<UnionType>type).types) {
if (isValidPropertyAccessWithType(node, left, propertyName, elementType)) {
return true;
}
}
}
return false;
}
return true;
}

View File

@ -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 + ".";

View File

@ -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 = <JSDocTypeTag | JSDocParameterTag | JSDocReturnTag>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 ||
(<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(<PropertyAccessExpression>(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(<PropertyAccessExpression>(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<T, |
containingNodeKind === SyntaxKind.ClassExpression || // var C = class D<T, |
containingNodeKind === SyntaxKind.InterfaceDeclaration || // interface A<T, |
@ -1184,7 +1267,7 @@ namespace ts.Completions {
case SyntaxKind.OpenParenToken:
return containingNodeKind === SyntaxKind.CatchClause ||
isFunction(containingNodeKind);
isFunctionLikeButNotConstructor(containingNodeKind);
case SyntaxKind.OpenBraceToken:
return containingNodeKind === SyntaxKind.EnumDeclaration || // enum a { |
@ -1202,7 +1285,7 @@ namespace ts.Completions {
containingNodeKind === SyntaxKind.ClassExpression || // var C = class D< |
containingNodeKind === SyntaxKind.InterfaceDeclaration || // interface A< |
containingNodeKind === SyntaxKind.TypeAliasDeclaration || // type List< |
isFunction(containingNodeKind);
isFunctionLikeKind(containingNodeKind);
case SyntaxKind.StaticKeyword:
return containingNodeKind === SyntaxKind.PropertyDeclaration && !isClassLike(contextToken.parent.parent);
@ -1271,6 +1354,10 @@ namespace ts.Completions {
return false;
}
function isFunctionLikeButNotConstructor(kind: SyntaxKind) {
return isFunctionLikeKind(kind) && kind !== SyntaxKind.Constructor;
}
function isDotOfNumericLiteral(contextToken: Node): boolean {
if (contextToken.kind === SyntaxKind.NumericLiteral) {
const text = contextToken.getFullText();

View File

@ -82,7 +82,7 @@ namespace ts {
else if (node.parent.kind === SyntaxKind.ExportAssignment) {
return SemanticMeaning.All;
}
else if (isInRightSideOfImport(node)) {
else if (isInRightSideOfInternalImportEqualsDeclaration(node)) {
return getMeaningFromRightHandSideOfImportEquals(node);
}
else if (isDeclarationName(node)) {
@ -118,7 +118,7 @@ namespace ts {
return SemanticMeaning.Namespace;
}
function isInRightSideOfImport(node: Node) {
export function isInRightSideOfInternalImportEqualsDeclaration(node: Node) {
while (node.parent.kind === SyntaxKind.QualifiedName) {
node = node.parent;
}
@ -745,7 +745,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 = (includeJsDoc && child.jsDoc ? child.jsDoc[0] : child).getStart(sourceFile);
const start = child.getStart(sourceFile, includeJsDoc);
const lookInPreviousChild =
(start >= position) || // cursor in the leading trivia
(child.kind === SyntaxKind.JsxText && start === child.end); // whitespace only JsxText

View File

@ -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');

View File

@ -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');

View File

@ -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');

View File

@ -9,5 +9,6 @@ goTo.marker("1");
verify.not.completionListContains("a");
goTo.marker("2");
verify.not.completionListContains("b");
edit.insert("typeof ");
verify.completionListContains("b");

View File

@ -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(".");

View File

@ -1,13 +1,16 @@
///<reference path="fourslash.ts" />
///<reference path="fourslash.ts" />
//// var x = class myClass <TypeParam> {
//// getClassName (){
//// /*0*/
//// var tmp: /*0Type*/;
//// }
//// prop: Ty/*1*/
//// }
goTo.marker("0");
verify.not.completionListContains("TypeParam", "(type parameter) TypeParam in myClass<TypeParam>", /*documentation*/ undefined, "type parameter");
goTo.marker("0Type");
verify.completionListContains("TypeParam", "(type parameter) TypeParam in myClass<TypeParam>", /*documentation*/ undefined, "type parameter");
goTo.marker("1");

View File

@ -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");
verify.not.completionListContains("foo");
verify.not.completionListContains("obj");

View File

@ -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");
verify.not.completionListContains("foo");
verify.not.completionListContains("obj");

View File

@ -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");
verify.not.completionListContains("foo");
verify.not.completionListContains("obj");

View File

@ -27,4 +27,4 @@ goTo.marker("3");
verify.completionListIsEmpty();
goTo.marker("4");
verify.not.completionListIsEmpty();
verify.completionListIsEmpty();

View File

@ -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");

View File

@ -1,4 +1,4 @@
/// <reference path='fourslash.ts'/>
/// <reference path='fourslash.ts'/>
////type List1</*0*/
////type List2</*1*/T> = 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");

View File

@ -1,4 +1,4 @@
/// <reference path='fourslash.ts'/>
/// <reference path='fourslash.ts'/>
////type Map1<K, /*0*/
////type Map1<K, /*1*/V> = [];
@ -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");
verify.not.completionListContains("K1");
verify.not.completionListContains("V1");

View File

@ -1,13 +1,13 @@
/// <reference path='fourslash.ts'/>
/// <reference path='fourslash.ts'/>
//// type constructorType<T1, T2> = new <T/*1*/, /*2*/
goTo.marker("1");
verify.completionListContains("T");
verify.completionListContains("T1");
verify.completionListContains("T2");
verify.not.completionListContains("T");
verify.not.completionListContains("T1");
verify.not.completionListContains("T2");
goTo.marker("2");
verify.completionListContains("T");
verify.completionListContains("T1");
verify.completionListContains("T2");
verify.not.completionListContains("T");
verify.not.completionListContains("T1");
verify.not.completionListContains("T2");

View File

@ -7,7 +7,7 @@
goTo.marker("1");
verify.completionListContains("C");
verify.completionListContains("foo"); // ideally this shouldn't show up for a type
verify.not.completionListContains("foo"); // ideally this shouldn't show up for a type
edit.insert("typeof ");
verify.completionListContains("C");
verify.completionListContains("foo");

View File

@ -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");
verify.not.completionListContains("foo");
verify.not.completionListContains("obj");

View File

@ -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");
verify.not.completionListContains("foo");
verify.not.completionListContains("obj");

View File

@ -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");
verify.not.completionListContains("foo");
verify.not.completionListContains("obj");

View File

@ -21,36 +21,40 @@
////
////interface TestInterface implements Module./*TypeReferenceInImplementsList*/ { }
goTo.marker("ValueReference");
verify.completionListContains("exportedVariable");
verify.completionListContains("exportedFunction");
verify.completionListContains("exportedClass");
verify.completionListContains("exportedModule");
// No inner declarations
verify.not.completionListContains("innerVariable");
verify.not.completionListContains("innerClass");
// Include type declarations
verify.completionListContains("exportedInterface");
function getVerify(isTypeLocation: boolean) {
return {
verifyValue: isTypeLocation ? verify.not : verify,
verifyType: isTypeLocation ? verify : verify.not,
verifyValueOrType: verify,
verifyNotValueOrType: verify.not,
};
}
goTo.marker("TypeReference");
verify.completionListContains("exportedClass");
verify.completionListContains("exportedModule");
verify.completionListContains("exportedInterface");
// Include value completions
verify.completionListContains("exportedVariable");
function verifyModuleMembers(marker: string, isTypeLocation: boolean) {
goTo.marker(marker);
goTo.marker("TypeReferenceInExtendsList");
verify.completionListContains("exportedClass");
verify.completionListContains("exportedModule");
verify.completionListContains("exportedInterface");
// Include value completions
verify.completionListContains("exportedVariable");
const { verifyValue, verifyType, verifyValueOrType, verifyNotValueOrType } = getVerify(isTypeLocation);
verifyValue.completionListContains("exportedVariable");
verifyValue.completionListContains("exportedFunction");
verifyValue.completionListContains("exportedModule");
goTo.marker("TypeReferenceInImplementsList");
verify.completionListContains("exportedClass");
verify.completionListContains("exportedModule");
verify.completionListContains("exportedInterface");
// Include value completions
verify.completionListContains("exportedVariable");
verifyValueOrType.completionListContains("exportedClass");
// Include type declarations
verifyType.completionListContains("exportedInterface");
// No inner declarations
verifyNotValueOrType.completionListContains("innerVariable");
verifyNotValueOrType.completionListContains("innerFunction");
verifyNotValueOrType.completionListContains("innerClass");
verifyNotValueOrType.completionListContains("innerModule");
verifyNotValueOrType.completionListContains("innerInterface");
verifyNotValueOrType.completionListContains("exportedInnerModuleVariable");
}
verifyModuleMembers("ValueReference", /*isTypeLocation*/ false);
verifyModuleMembers("TypeReference", /*isTypeLocation*/ true);
verifyModuleMembers("TypeReferenceInExtendsList", /*isTypeLocation*/ false);
verifyModuleMembers("TypeReferenceInImplementsList", /*isTypeLocation*/ true);

View File

@ -1,10 +1,13 @@
/// <reference path='fourslash.ts' />
/// <reference path='fourslash.ts' />
////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();

View File

@ -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");

View File

@ -5,5 +5,5 @@
////}
goTo.marker();
verify.completionListContains('parseInt');
verify.not.completionListContains('parseInt');
verify.completionListContains('encoder');

View File

@ -0,0 +1,70 @@
/// <reference path="fourslash.ts" />
////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 = </*typeExpr2*/point>{ 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);
}

View File

@ -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');
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');
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');
}

View File

@ -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');
verifyExtendedNamespace('extendedNamespace');
verifyExtendedNamespace('extendedNamespaceType', /*isTypeLocation*/ true);
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');
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');
}

View File

@ -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();

View File

@ -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');

View File

@ -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");
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");

View File

@ -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");

View File

@ -0,0 +1,70 @@
/// <reference path="fourslash.ts"/>
// @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();

View File

@ -0,0 +1,65 @@
/// <reference path="fourslash.ts"/>
// @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,
});

View File

@ -0,0 +1,127 @@
/// <reference path="fourslash.ts"/>
// @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");

View File

@ -0,0 +1,140 @@
/// <reference path="fourslash.ts"/>
////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();

View File

@ -14,6 +14,6 @@
////var x: Foo./**/
goTo.marker();
verify.completionListCount(2);
verify.completionListCount(1);
verify.completionListContains('Bar');
verify.completionListContains('Blah');
verify.not.completionListContains('Blah');