diff --git a/src/harness/fourslash.ts b/src/harness/fourslash.ts
index 95a320ac052..5d488259a36 100644
--- a/src/harness/fourslash.ts
+++ b/src/harness/fourslash.ts
@@ -620,7 +620,7 @@ module FourSlash {
this.scenarioActions.push('');
var members = this.getMemberListAtCaret();
- if (members.entries.filter(e => e.name === symbol).length !== 0) {
+ if (members && members.entries.filter(e => e.name === symbol).length !== 0) {
this.raiseError('Member list did contain ' + symbol);
}
}
@@ -691,7 +691,12 @@ module FourSlash {
public verifyCompletionListContains(symbol: string, text?: string, documentation?: string, kind?: string) {
var completions = this.getCompletionListAtCaret();
- this.assertItemInCompletionList(completions.entries, symbol, text, documentation, kind);
+ if (completions) {
+ this.assertItemInCompletionList(completions.entries, symbol, text, documentation, kind);
+ }
+ else {
+ this.raiseError(`No completions at position '${ this.currentCaretPosition }' when looking for '${ symbol }'.`);
+ }
}
public verifyCompletionListDoesNotContain(symbol: string) {
@@ -699,7 +704,7 @@ module FourSlash {
this.scenarioActions.push('');
var completions = this.getCompletionListAtCaret();
- if (completions && completions.entries && completions.entries.filter(e => e.name === symbol).length !== 0) {
+ if (completions && completions.entries.filter(e => e.name === symbol).length !== 0) {
this.raiseError('Completion list did contain ' + symbol);
}
}
diff --git a/src/services/formatting/smartIndenter.ts b/src/services/formatting/smartIndenter.ts
index 1a52c72c9d8..8508e3b932d 100644
--- a/src/services/formatting/smartIndenter.ts
+++ b/src/services/formatting/smartIndenter.ts
@@ -215,11 +215,7 @@ module ts.formatting {
function getStartLineAndCharacterForNode(n: Node, sourceFile: SourceFile): LineAndCharacter {
return sourceFile.getLineAndCharacterOfPosition(n.getStart(sourceFile));
}
-
- function positionBelongsToNode(candidate: Node, position: number, sourceFile: SourceFile): boolean {
- return candidate.end > position || !isCompletedNode(candidate, sourceFile);
- }
-
+
export function childStartsOnTheSameLineWithElseInIfStatement(parent: Node, child: TextRangeWithKind, childStartLine: number, sourceFile: SourceFile): boolean {
if (parent.kind === SyntaxKind.IfStatement && (parent).elseStatement === child) {
let elseKeyword = findChildOfKind(parent, SyntaxKind.ElseKeyword, sourceFile);
@@ -403,128 +399,5 @@ module ts.formatting {
return false;
}
}
-
- /*
- * Checks if node ends with 'expectedLastToken'.
- * If child at position 'length - 1' is 'SemicolonToken' it is skipped and 'expectedLastToken' is compared with child at position 'length - 2'.
- */
- function nodeEndsWith(n: Node, expectedLastToken: SyntaxKind, sourceFile: SourceFile): boolean {
- let children = n.getChildren(sourceFile);
- if (children.length) {
- let last = children[children.length - 1];
- if (last.kind === expectedLastToken) {
- return true;
- }
- else if (last.kind === SyntaxKind.SemicolonToken && children.length !== 1) {
- return children[children.length - 2].kind === expectedLastToken;
- }
- }
- return false;
- }
-
- /*
- * This function is always called when position of the cursor is located after the node
- */
- function isCompletedNode(n: Node, sourceFile: SourceFile): boolean {
- if (n.getFullWidth() === 0) {
- return false;
- }
-
- switch (n.kind) {
- case SyntaxKind.ClassDeclaration:
- case SyntaxKind.InterfaceDeclaration:
- case SyntaxKind.EnumDeclaration:
- case SyntaxKind.ObjectLiteralExpression:
- case SyntaxKind.ObjectBindingPattern:
- case SyntaxKind.TypeLiteral:
- case SyntaxKind.Block:
- case SyntaxKind.ModuleBlock:
- case SyntaxKind.CaseBlock:
- return nodeEndsWith(n, SyntaxKind.CloseBraceToken, sourceFile);
- case SyntaxKind.CatchClause:
- return isCompletedNode((n).block, sourceFile);
- case SyntaxKind.NewExpression:
- if (!(n).arguments) {
- return true;
- }
- // fall through
- case SyntaxKind.CallExpression:
- case SyntaxKind.ParenthesizedExpression:
- case SyntaxKind.ParenthesizedType:
- return nodeEndsWith(n, SyntaxKind.CloseParenToken, sourceFile);
-
- case SyntaxKind.FunctionType:
- case SyntaxKind.ConstructorType:
- return isCompletedNode((n).type, sourceFile);
-
- case SyntaxKind.Constructor:
- case SyntaxKind.GetAccessor:
- case SyntaxKind.SetAccessor:
- case SyntaxKind.FunctionDeclaration:
- case SyntaxKind.FunctionExpression:
- case SyntaxKind.MethodDeclaration:
- case SyntaxKind.MethodSignature:
- case SyntaxKind.ConstructSignature:
- case SyntaxKind.CallSignature:
- case SyntaxKind.ArrowFunction:
- if ((n).body) {
- return isCompletedNode((n).body, sourceFile);
- }
-
- if ((n).type) {
- return isCompletedNode((n).type, sourceFile);
- }
-
- // Even though type parameters can be unclosed, we can get away with
- // having at least a closing paren.
- return hasChildOfKind(n, SyntaxKind.CloseParenToken, sourceFile);
-
- case SyntaxKind.ModuleDeclaration:
- return (n).body && isCompletedNode((n).body, sourceFile);
-
- case SyntaxKind.IfStatement:
- if ((n).elseStatement) {
- return isCompletedNode((n).elseStatement, sourceFile);
- }
- return isCompletedNode((n).thenStatement, sourceFile);
-
- case SyntaxKind.ExpressionStatement:
- return isCompletedNode((n).expression, sourceFile);
-
- case SyntaxKind.ArrayLiteralExpression:
- case SyntaxKind.ArrayBindingPattern:
- case SyntaxKind.ComputedPropertyName:
- case SyntaxKind.TupleType:
- return nodeEndsWith(n, SyntaxKind.CloseBracketToken, sourceFile);
-
- case SyntaxKind.IndexSignature:
- if ((n).type) {
- return isCompletedNode((n).type, sourceFile);
- }
-
- return hasChildOfKind(n, SyntaxKind.CloseBracketToken, sourceFile);
-
- case SyntaxKind.CaseClause:
- case SyntaxKind.DefaultClause:
- // there is no such thing as terminator token for CaseClause/DefaultClause so for simplicitly always consider them non-completed
- return false;
-
- case SyntaxKind.ForStatement:
- case SyntaxKind.ForInStatement:
- case SyntaxKind.ForOfStatement:
- case SyntaxKind.WhileStatement:
- return isCompletedNode((n).statement, sourceFile);
- case SyntaxKind.DoStatement:
- // rough approximation: if DoStatement has While keyword - then if node is completed is checking the presence of ')';
- let hasWhileKeyword = findChildOfKind(n, SyntaxKind.WhileKeyword, sourceFile);
- if (hasWhileKeyword) {
- return nodeEndsWith(n, SyntaxKind.CloseParenToken, sourceFile);
- }
- return isCompletedNode((n).statement, sourceFile);
-
- default:
- return true;
- }
- }
}
}
\ No newline at end of file
diff --git a/src/services/services.ts b/src/services/services.ts
index 1bf5f6336d4..067e4580991 100644
--- a/src/services/services.ts
+++ b/src/services/services.ts
@@ -2597,8 +2597,9 @@ module ts {
isNewIdentifierLocation = isNewIdentifierDefinitionLocation(previousToken);
/// TODO filter meaning based on the current context
+ let scopeNode = getScopeNode(previousToken, position, sourceFile);
let symbolMeanings = SymbolFlags.Type | SymbolFlags.Value | SymbolFlags.Namespace | SymbolFlags.Alias;
- let symbols = typeInfoResolver.getSymbolsInScope(node, symbolMeanings);
+ let symbols = typeInfoResolver.getSymbolsInScope(scopeNode, symbolMeanings);
getCompletionEntriesFromSymbols(symbols, activeCompletionSession);
}
@@ -2613,10 +2614,22 @@ module ts {
return {
isMemberCompletion,
isNewIdentifierLocation,
- isBuilder : isNewIdentifierDefinitionLocation, // temporary property used to match VS implementation
+ isBuilder: isNewIdentifierDefinitionLocation, // temporary property used to match VS implementation
entries: activeCompletionSession.entries
};
+ /**
+ * Finds the first node that "embraces" the position, so that one may
+ * accurately aggregate locals from the closest containing scope.
+ */
+ function getScopeNode(initialToken: Node, position: number, sourceFile: SourceFile) {
+ var scope = initialToken;
+ while (scope && !positionBelongsToNode(scope, position, sourceFile)) {
+ scope = scope.parent;
+ }
+ return scope;
+ }
+
function getCompletionEntriesFromSymbols(symbols: Symbol[], session: CompletionSession): void {
let start = new Date().getTime();
forEach(symbols, symbol => {
diff --git a/src/services/utilities.ts b/src/services/utilities.ts
index 7671ee3f88d..cc9b8c94ab6 100644
--- a/src/services/utilities.ts
+++ b/src/services/utilities.ts
@@ -59,6 +59,157 @@ module ts {
return start < end;
}
+ export function positionBelongsToNode(candidate: Node, position: number, sourceFile: SourceFile): boolean {
+ return candidate.end > position || !isCompletedNode(candidate, sourceFile);
+ }
+
+ export function isCompletedNode(n: Node, sourceFile: SourceFile): boolean {
+ if (nodeIsMissing(n)) {
+ return false;
+ }
+
+ switch (n.kind) {
+ case SyntaxKind.ClassDeclaration:
+ case SyntaxKind.InterfaceDeclaration:
+ case SyntaxKind.EnumDeclaration:
+ case SyntaxKind.ObjectLiteralExpression:
+ case SyntaxKind.ObjectBindingPattern:
+ case SyntaxKind.TypeLiteral:
+ case SyntaxKind.Block:
+ case SyntaxKind.ModuleBlock:
+ case SyntaxKind.CaseBlock:
+ return nodeEndsWith(n, SyntaxKind.CloseBraceToken, sourceFile);
+ case SyntaxKind.CatchClause:
+ return isCompletedNode((n).block, sourceFile);
+ case SyntaxKind.NewExpression:
+ if (!(n).arguments) {
+ return true;
+ }
+ // fall through
+ case SyntaxKind.CallExpression:
+ case SyntaxKind.ParenthesizedExpression:
+ case SyntaxKind.ParenthesizedType:
+ return nodeEndsWith(n, SyntaxKind.CloseParenToken, sourceFile);
+
+ case SyntaxKind.FunctionType:
+ case SyntaxKind.ConstructorType:
+ return isCompletedNode((n).type, sourceFile);
+
+ case SyntaxKind.Constructor:
+ case SyntaxKind.GetAccessor:
+ case SyntaxKind.SetAccessor:
+ case SyntaxKind.FunctionDeclaration:
+ case SyntaxKind.FunctionExpression:
+ case SyntaxKind.MethodDeclaration:
+ case SyntaxKind.MethodSignature:
+ case SyntaxKind.ConstructSignature:
+ case SyntaxKind.CallSignature:
+ case SyntaxKind.ArrowFunction:
+ if ((n).body) {
+ return isCompletedNode((n).body, sourceFile);
+ }
+
+ if ((n).type) {
+ return isCompletedNode((n).type, sourceFile);
+ }
+
+ // Even though type parameters can be unclosed, we can get away with
+ // having at least a closing paren.
+ return hasChildOfKind(n, SyntaxKind.CloseParenToken, sourceFile);
+
+ case SyntaxKind.ModuleDeclaration:
+ return (n).body && isCompletedNode((n).body, sourceFile);
+
+ case SyntaxKind.IfStatement:
+ if ((n).elseStatement) {
+ return isCompletedNode((n).elseStatement, sourceFile);
+ }
+ return isCompletedNode((n).thenStatement, sourceFile);
+
+ case SyntaxKind.ExpressionStatement:
+ return isCompletedNode((n).expression, sourceFile);
+
+ case SyntaxKind.ArrayLiteralExpression:
+ case SyntaxKind.ArrayBindingPattern:
+ case SyntaxKind.ElementAccessExpression:
+ case SyntaxKind.ComputedPropertyName:
+ case SyntaxKind.TupleType:
+ return nodeEndsWith(n, SyntaxKind.CloseBracketToken, sourceFile);
+
+ case SyntaxKind.IndexSignature:
+ if ((n).type) {
+ return isCompletedNode((n).type, sourceFile);
+ }
+
+ return hasChildOfKind(n, SyntaxKind.CloseBracketToken, sourceFile);
+
+ case SyntaxKind.CaseClause:
+ case SyntaxKind.DefaultClause:
+ // there is no such thing as terminator token for CaseClause/DefaultClause so for simplicitly always consider them non-completed
+ return false;
+
+ case SyntaxKind.ForStatement:
+ case SyntaxKind.ForInStatement:
+ case SyntaxKind.ForOfStatement:
+ case SyntaxKind.WhileStatement:
+ return isCompletedNode((n).statement, sourceFile);
+ case SyntaxKind.DoStatement:
+ // rough approximation: if DoStatement has While keyword - then if node is completed is checking the presence of ')';
+ let hasWhileKeyword = findChildOfKind(n, SyntaxKind.WhileKeyword, sourceFile);
+ if (hasWhileKeyword) {
+ return nodeEndsWith(n, SyntaxKind.CloseParenToken, sourceFile);
+ }
+ return isCompletedNode((n).statement, sourceFile);
+
+ case SyntaxKind.TypeQuery:
+ return isCompletedNode((n).exprName, sourceFile);
+
+ case SyntaxKind.TypeOfExpression:
+ case SyntaxKind.DeleteExpression:
+ case SyntaxKind.VoidExpression:
+ case SyntaxKind.YieldExpression:
+ case SyntaxKind.SpreadElementExpression:
+ let unaryWordExpression = (n);
+ return isCompletedNode(unaryWordExpression.expression, sourceFile);
+
+ case SyntaxKind.TaggedTemplateExpression:
+ return isCompletedNode((n).template, sourceFile);
+ case SyntaxKind.TemplateExpression:
+ let lastSpan = lastOrUndefined((n).templateSpans);
+ return isCompletedNode(lastSpan, sourceFile);
+ case SyntaxKind.TemplateSpan:
+ return nodeIsPresent((n).literal);
+
+ case SyntaxKind.PrefixUnaryExpression:
+ return isCompletedNode((n).operand, sourceFile);
+ case SyntaxKind.BinaryExpression:
+ return isCompletedNode((n).right, sourceFile);
+ case SyntaxKind.ConditionalExpression:
+ return isCompletedNode((n).whenFalse, sourceFile);
+
+ default:
+ return true;
+ }
+ }
+
+ /*
+ * Checks if node ends with 'expectedLastToken'.
+ * If child at position 'length - 1' is 'SemicolonToken' it is skipped and 'expectedLastToken' is compared with child at position 'length - 2'.
+ */
+ function nodeEndsWith(n: Node, expectedLastToken: SyntaxKind, sourceFile: SourceFile): boolean {
+ let children = n.getChildren(sourceFile);
+ if (children.length) {
+ let last = children[children.length - 1];
+ if (last.kind === expectedLastToken) {
+ return true;
+ }
+ else if (last.kind === SyntaxKind.SemicolonToken && children.length !== 1) {
+ return children[children.length - 2].kind === expectedLastToken;
+ }
+ }
+ return false;
+ }
+
export function findListItemInfo(node: Node): ListItemInfo {
let list = findContainingList(node);
diff --git a/tests/cases/fourslash/completionListAtBeginningOfFile01.ts b/tests/cases/fourslash/completionListAtBeginningOfFile01.ts
new file mode 100644
index 00000000000..f811fec4c67
--- /dev/null
+++ b/tests/cases/fourslash/completionListAtBeginningOfFile01.ts
@@ -0,0 +1,13 @@
+///
+
+/////*1*/
+////var x = 0, y = 1, z = 2;
+////enum E {
+//// A, B, C
+////}
+
+goTo.marker("1");
+verify.completionListContains("x");
+verify.completionListContains("y");
+verify.completionListContains("z");
+verify.completionListContains("E");
\ No newline at end of file
diff --git a/tests/cases/fourslash/completionListBeforeNewScope01.ts b/tests/cases/fourslash/completionListBeforeNewScope01.ts
new file mode 100644
index 00000000000..79159744b81
--- /dev/null
+++ b/tests/cases/fourslash/completionListBeforeNewScope01.ts
@@ -0,0 +1,11 @@
+///
+
+////p/*1*/
+////
+////function fun(param) {
+//// let party = Math.random() < 0.99;
+////}
+
+goTo.marker("1");
+verify.not.completionListContains("param");
+verify.not.completionListContains("party");
\ No newline at end of file
diff --git a/tests/cases/fourslash/completionListBeforeNewScope02.ts b/tests/cases/fourslash/completionListBeforeNewScope02.ts
new file mode 100644
index 00000000000..9fb1182b56e
--- /dev/null
+++ b/tests/cases/fourslash/completionListBeforeNewScope02.ts
@@ -0,0 +1,10 @@
+///
+
+////a/*1*/
+////
+////{
+//// let aaaaaa = 10;
+////}
+
+goTo.marker("1");
+verify.not.completionListContains("aaaaa");
\ No newline at end of file
diff --git a/tests/cases/fourslash/completionListInArrowFunctionInUnclosedCallSite01.ts b/tests/cases/fourslash/completionListInArrowFunctionInUnclosedCallSite01.ts
new file mode 100644
index 00000000000..633dc00a941
--- /dev/null
+++ b/tests/cases/fourslash/completionListInArrowFunctionInUnclosedCallSite01.ts
@@ -0,0 +1,11 @@
+///
+
+////declare function foo(...params: any[]): any;
+////function getAllFiles(rootFileNames: string[]) {
+//// var processedFiles = rootFileNames.map(fileName => foo(/*1*/
+
+goTo.marker("1");
+verify.completionListContains("fileName");
+verify.completionListContains("rootFileNames");
+verify.completionListContains("getAllFiles");
+verify.completionListContains("foo");
\ No newline at end of file
diff --git a/tests/cases/fourslash/completionListInClosedFunction01.ts b/tests/cases/fourslash/completionListInClosedFunction01.ts
new file mode 100644
index 00000000000..7c9c2a20139
--- /dev/null
+++ b/tests/cases/fourslash/completionListInClosedFunction01.ts
@@ -0,0 +1,12 @@
+///
+
+////function foo(x: string, y: number, z: boolean) {
+//// /*1*/
+////}
+
+goTo.marker("1");
+
+verify.memberListContains("foo");
+verify.memberListContains("x");
+verify.memberListContains("y");
+verify.memberListContains("z");
\ No newline at end of file
diff --git a/tests/cases/fourslash/completionListInClosedFunction02.ts b/tests/cases/fourslash/completionListInClosedFunction02.ts
new file mode 100644
index 00000000000..a2ae8a9da83
--- /dev/null
+++ b/tests/cases/fourslash/completionListInClosedFunction02.ts
@@ -0,0 +1,18 @@
+///
+
+////function foo(x: string, y: number, z: boolean) {
+//// function bar(a: number, b: string, c: typeof /*1*/) {
+//// }
+////}
+
+goTo.marker("1");
+
+verify.memberListContains("foo");
+verify.memberListContains("x");
+verify.memberListContains("y");
+verify.memberListContains("z");
+
+verify.memberListContains("bar");
+verify.memberListContains("a");
+verify.memberListContains("b");
+verify.memberListContains("c"); // questionable
\ No newline at end of file
diff --git a/tests/cases/fourslash/completionListInClosedFunction03.ts b/tests/cases/fourslash/completionListInClosedFunction03.ts
new file mode 100644
index 00000000000..b1a10a4a4b2
--- /dev/null
+++ b/tests/cases/fourslash/completionListInClosedFunction03.ts
@@ -0,0 +1,19 @@
+///
+
+////function foo(x: string, y: number, z: boolean) {
+//// function bar(a: number, b: string, c: typeof x = /*1*/) {
+////
+//// }
+////}
+
+goTo.marker("1");
+
+verify.memberListContains("foo");
+verify.memberListContains("x");
+verify.memberListContains("y");
+verify.memberListContains("z");
+
+verify.memberListContains("bar");
+verify.memberListContains("a");
+verify.memberListContains("b");
+verify.memberListContains("c"); // questionable
\ No newline at end of file
diff --git a/tests/cases/fourslash/completionListInClosedFunction04.ts b/tests/cases/fourslash/completionListInClosedFunction04.ts
new file mode 100644
index 00000000000..fcc7d070eb7
--- /dev/null
+++ b/tests/cases/fourslash/completionListInClosedFunction04.ts
@@ -0,0 +1,19 @@
+///
+
+////function foo(x: string, y: number, z: boolean) {
+//// function bar(a: number, b: string = /*1*/, c: typeof x = "hello") {
+////
+//// }
+////}
+
+goTo.marker("1");
+
+verify.memberListContains("foo");
+verify.memberListContains("x");
+verify.memberListContains("y");
+verify.memberListContains("z");
+
+verify.memberListContains("bar");
+verify.memberListContains("a");
+verify.memberListContains("b");
+verify.memberListContains("c"); // definitely questionable
\ No newline at end of file
diff --git a/tests/cases/fourslash/completionListInClosedFunction05.ts b/tests/cases/fourslash/completionListInClosedFunction05.ts
new file mode 100644
index 00000000000..7ec3985caf0
--- /dev/null
+++ b/tests/cases/fourslash/completionListInClosedFunction05.ts
@@ -0,0 +1,21 @@
+///
+
+////function foo(x: string, y: number, z: boolean) {
+//// function bar(a: number, b: string = "hello", c: typeof x = "hello") {
+//// var v = /*1*/
+//// }
+////}
+
+goTo.marker("1");
+
+verify.memberListContains("foo");
+verify.memberListContains("x");
+verify.memberListContains("y");
+verify.memberListContains("z");
+
+verify.memberListContains("bar");
+verify.memberListContains("a");
+verify.memberListContains("b");
+verify.memberListContains("c");
+
+verify.memberListContains("v"); // questionable
\ No newline at end of file
diff --git a/tests/cases/fourslash/completionListInClosedFunction06.ts b/tests/cases/fourslash/completionListInClosedFunction06.ts
new file mode 100644
index 00000000000..f1aed3ad1a4
--- /dev/null
+++ b/tests/cases/fourslash/completionListInClosedFunction06.ts
@@ -0,0 +1,14 @@
+///
+
+////interface MyType {
+////}
+////
+////function foo(x: string, y: number, z: boolean) {
+//// function bar(a: number, b: string = "hello", c: typeof x = "hello") {
+//// var v = (x: /*1*/);
+//// }
+////}
+
+goTo.marker("1");
+
+verify.memberListContains("MyType");
\ No newline at end of file
diff --git a/tests/cases/fourslash/completionListInClosedFunction07.ts b/tests/cases/fourslash/completionListInClosedFunction07.ts
new file mode 100644
index 00000000000..13b9f5787de
--- /dev/null
+++ b/tests/cases/fourslash/completionListInClosedFunction07.ts
@@ -0,0 +1,25 @@
+///
+
+////interface MyType {
+////}
+////
+////function foo(x: string, y: number, z: boolean) {
+//// function bar(a: number, b: string = "hello", c: typeof x = "hello") {
+//// var v = (p: MyType) => /*1*/;
+//// }
+////}
+
+goTo.marker("1");
+
+verify.memberListContains("foo");
+verify.memberListContains("x");
+verify.memberListContains("y");
+verify.memberListContains("z");
+
+verify.memberListContains("bar");
+verify.memberListContains("a");
+verify.memberListContains("b");
+verify.memberListContains("c");
+
+verify.memberListContains("v");
+verify.memberListContains("p");
\ No newline at end of file
diff --git a/tests/cases/fourslash/completionListInClosedObjectTypeLiteralInSignature01.ts b/tests/cases/fourslash/completionListInClosedObjectTypeLiteralInSignature01.ts
new file mode 100644
index 00000000000..690fb583f67
--- /dev/null
+++ b/tests/cases/fourslash/completionListInClosedObjectTypeLiteralInSignature01.ts
@@ -0,0 +1,18 @@
+///
+
+////interface I {
+//// [s: string]: TString;
+//// [s: number]: TNumber;
+////}
+////
+////declare function foo(obj: I): { str: T/*1*/ }
+
+goTo.marker("1");
+
+verify.memberListContains("I");
+verify.memberListContains("TString");
+verify.memberListContains("TNumber");
+
+// Ideally the following shouldn't show up since they're not types.
+verify.memberListContains("foo");
+verify.memberListContains("obj");
\ No newline at end of file
diff --git a/tests/cases/fourslash/completionListInClosedObjectTypeLiteralInSignature02.ts b/tests/cases/fourslash/completionListInClosedObjectTypeLiteralInSignature02.ts
new file mode 100644
index 00000000000..57af3592d44
--- /dev/null
+++ b/tests/cases/fourslash/completionListInClosedObjectTypeLiteralInSignature02.ts
@@ -0,0 +1,18 @@
+///
+
+////interface I {
+//// [s: string]: TString;
+//// [s: number]: TNumber;
+////}
+////
+////declare function foo(obj: I): { str: TStr/*1*/ }
+
+goTo.marker("1");
+
+verify.memberListContains("I");
+verify.memberListContains("TString");
+verify.memberListContains("TNumber"); // REVIEW: Is this intended behavior?
+
+// Ideally the following shouldn't show up since they're not types.
+verify.memberListContains("foo");
+verify.memberListContains("obj");
\ No newline at end of file
diff --git a/tests/cases/fourslash/completionListInClosedObjectTypeLiteralInSignature03.ts b/tests/cases/fourslash/completionListInClosedObjectTypeLiteralInSignature03.ts
new file mode 100644
index 00000000000..1e5e6256d6e
--- /dev/null
+++ b/tests/cases/fourslash/completionListInClosedObjectTypeLiteralInSignature03.ts
@@ -0,0 +1,18 @@
+///
+
+////interface I {
+//// [s: string]: TString;
+//// [s: number]: TNumber;
+////}
+////
+////declare function foo(obj: I): { str: TString/*1*/ }
+
+goTo.marker("1");
+
+verify.memberListContains("I");
+verify.memberListContains("TString");
+verify.memberListContains("TNumber"); // REVIEW: Is this intended behavior?
+
+// Ideally the following shouldn't show up since they're not types.
+verify.memberListContains("foo");
+verify.memberListContains("obj");
\ No newline at end of file
diff --git a/tests/cases/fourslash/completionListInClosedObjectTypeLiteralInSignature04.ts b/tests/cases/fourslash/completionListInClosedObjectTypeLiteralInSignature04.ts
new file mode 100644
index 00000000000..a45d98ad4df
--- /dev/null
+++ b/tests/cases/fourslash/completionListInClosedObjectTypeLiteralInSignature04.ts
@@ -0,0 +1,16 @@
+///
+
+////interface I {
+//// [s: string]: TString;
+//// [s: number]: TNumber;
+////}
+////
+////declare function foo(obj: I): { /*1*/ }
+
+goTo.marker("1");
+
+verify.not.memberListContains("I");
+verify.not.memberListContains("TString");
+verify.not.memberListContains("TNumber");
+verify.not.memberListContains("foo");
+verify.not.memberListContains("obj");
diff --git a/tests/cases/fourslash/completionListInUnclosedCommaExpression01.ts b/tests/cases/fourslash/completionListInUnclosedCommaExpression01.ts
new file mode 100644
index 00000000000..de0f26eb86e
--- /dev/null
+++ b/tests/cases/fourslash/completionListInUnclosedCommaExpression01.ts
@@ -0,0 +1,8 @@
+///
+
+////// should NOT see a and b
+////foo((a, b) => a,/*1*/
+
+goTo.marker("1");
+verify.not.completionListContains("a");
+verify.not.completionListContains("b");
\ No newline at end of file
diff --git a/tests/cases/fourslash/completionListInUnclosedCommaExpression02.ts b/tests/cases/fourslash/completionListInUnclosedCommaExpression02.ts
new file mode 100644
index 00000000000..e0ea3abbd38
--- /dev/null
+++ b/tests/cases/fourslash/completionListInUnclosedCommaExpression02.ts
@@ -0,0 +1,8 @@
+///
+
+////// should NOT see a and b
+////foo((a, b) => (a,/*1*/
+
+goTo.marker("1");
+verify.completionListContains("a");
+verify.completionListContains("b");
\ No newline at end of file
diff --git a/tests/cases/fourslash/completionListInUnclosedDeleteExpression01.ts b/tests/cases/fourslash/completionListInUnclosedDeleteExpression01.ts
new file mode 100644
index 00000000000..fdb67dfc335
--- /dev/null
+++ b/tests/cases/fourslash/completionListInUnclosedDeleteExpression01.ts
@@ -0,0 +1,7 @@
+///
+
+////var x;
+////var y = delete /*1*/
+
+goTo.marker("1");
+verify.completionListContains("x");
\ No newline at end of file
diff --git a/tests/cases/fourslash/completionListInUnclosedDeleteExpression02.ts b/tests/cases/fourslash/completionListInUnclosedDeleteExpression02.ts
new file mode 100644
index 00000000000..3573c345285
--- /dev/null
+++ b/tests/cases/fourslash/completionListInUnclosedDeleteExpression02.ts
@@ -0,0 +1,8 @@
+///
+
+////var x;
+////var y = (p) => delete /*1*/
+
+goTo.marker("1");
+verify.completionListContains("x");
+verify.completionListContains("p");
\ No newline at end of file
diff --git a/tests/cases/fourslash/completionListInUnclosedElementAccessExpression01.ts b/tests/cases/fourslash/completionListInUnclosedElementAccessExpression01.ts
new file mode 100644
index 00000000000..59c4922671e
--- /dev/null
+++ b/tests/cases/fourslash/completionListInUnclosedElementAccessExpression01.ts
@@ -0,0 +1,7 @@
+///
+
+////var x;
+////var y = x[/*1*/
+
+goTo.marker("1");
+verify.completionListContains("x");
\ No newline at end of file
diff --git a/tests/cases/fourslash/completionListInUnclosedElementAccessExpression02.ts b/tests/cases/fourslash/completionListInUnclosedElementAccessExpression02.ts
new file mode 100644
index 00000000000..1d6403cfa10
--- /dev/null
+++ b/tests/cases/fourslash/completionListInUnclosedElementAccessExpression02.ts
@@ -0,0 +1,8 @@
+///
+
+////var x;
+////var y = (p) => x[/*1*/
+
+goTo.marker("1");
+verify.completionListContains("p");
+verify.completionListContains("x");
\ No newline at end of file
diff --git a/tests/cases/fourslash/completionListInUnclosedForLoop01.ts b/tests/cases/fourslash/completionListInUnclosedForLoop01.ts
new file mode 100644
index 00000000000..35e5efdd304
--- /dev/null
+++ b/tests/cases/fourslash/completionListInUnclosedForLoop01.ts
@@ -0,0 +1,6 @@
+///
+
+////for (let i = 0; /*1*/
+
+goTo.marker("1");
+verify.completionListContains("i");
\ No newline at end of file
diff --git a/tests/cases/fourslash/completionListInUnclosedForLoop02.ts b/tests/cases/fourslash/completionListInUnclosedForLoop02.ts
new file mode 100644
index 00000000000..e79f428b2b0
--- /dev/null
+++ b/tests/cases/fourslash/completionListInUnclosedForLoop02.ts
@@ -0,0 +1,6 @@
+///
+
+////for (let i = 0; i < 10; i++) /*1*/
+
+goTo.marker("1");
+verify.completionListContains("i");
\ No newline at end of file
diff --git a/tests/cases/fourslash/completionListInUnclosedFunction01.ts b/tests/cases/fourslash/completionListInUnclosedFunction01.ts
new file mode 100644
index 00000000000..4d33d1220f7
--- /dev/null
+++ b/tests/cases/fourslash/completionListInUnclosedFunction01.ts
@@ -0,0 +1,12 @@
+///
+
+////function foo(x: string, y: number, z: boolean) {
+//// /*1*/
+////
+
+goTo.marker("1");
+
+verify.memberListContains("foo");
+verify.memberListContains("x");
+verify.memberListContains("y");
+verify.memberListContains("z");
\ No newline at end of file
diff --git a/tests/cases/fourslash/completionListInUnclosedFunction02.ts b/tests/cases/fourslash/completionListInUnclosedFunction02.ts
new file mode 100644
index 00000000000..c0c79e94433
--- /dev/null
+++ b/tests/cases/fourslash/completionListInUnclosedFunction02.ts
@@ -0,0 +1,16 @@
+///
+
+////function foo(x: string, y: number, z: boolean) {
+//// function bar(a: number, b: string, c: typeof /*1*/
+
+goTo.marker("1");
+
+verify.memberListContains("foo");
+verify.memberListContains("x");
+verify.memberListContains("y");
+verify.memberListContains("z");
+
+verify.memberListContains("bar");
+verify.memberListContains("a");
+verify.memberListContains("b");
+verify.memberListContains("c"); // questionable
\ No newline at end of file
diff --git a/tests/cases/fourslash/completionListInUnclosedFunction03.ts b/tests/cases/fourslash/completionListInUnclosedFunction03.ts
new file mode 100644
index 00000000000..d8b3a0a132f
--- /dev/null
+++ b/tests/cases/fourslash/completionListInUnclosedFunction03.ts
@@ -0,0 +1,17 @@
+///
+
+////function foo(x: string, y: number, z: boolean) {
+//// function bar(a: number, b: string, c: typeof /*1*/
+////}
+
+goTo.marker("1");
+
+verify.memberListContains("foo");
+verify.memberListContains("x");
+verify.memberListContains("y");
+verify.memberListContains("z");
+
+verify.memberListContains("bar");
+verify.memberListContains("a");
+verify.memberListContains("b");
+verify.memberListContains("c"); // questionable
\ No newline at end of file
diff --git a/tests/cases/fourslash/completionListInUnclosedFunction04.ts b/tests/cases/fourslash/completionListInUnclosedFunction04.ts
new file mode 100644
index 00000000000..e56978732c2
--- /dev/null
+++ b/tests/cases/fourslash/completionListInUnclosedFunction04.ts
@@ -0,0 +1,16 @@
+///
+
+////function foo(x: string, y: number, z: boolean) {
+//// function bar(a: number, b: string, c: typeof x = /*1*/
+
+goTo.marker("1");
+
+verify.memberListContains("foo");
+verify.memberListContains("x");
+verify.memberListContains("y");
+verify.memberListContains("z");
+
+verify.memberListContains("bar");
+verify.memberListContains("a");
+verify.memberListContains("b");
+verify.memberListContains("c"); // questionable
\ No newline at end of file
diff --git a/tests/cases/fourslash/completionListInUnclosedFunction05.ts b/tests/cases/fourslash/completionListInUnclosedFunction05.ts
new file mode 100644
index 00000000000..748a334f860
--- /dev/null
+++ b/tests/cases/fourslash/completionListInUnclosedFunction05.ts
@@ -0,0 +1,17 @@
+///
+
+////function foo(x: string, y: number, z: boolean) {
+//// function bar(a: number, b: string, c: typeof x = /*1*/
+////}
+
+goTo.marker("1");
+
+verify.memberListContains("foo");
+verify.memberListContains("x");
+verify.memberListContains("y");
+verify.memberListContains("z");
+
+verify.memberListContains("bar");
+verify.memberListContains("a");
+verify.memberListContains("b");
+verify.memberListContains("c"); // questionable
\ No newline at end of file
diff --git a/tests/cases/fourslash/completionListInUnclosedFunction06.ts b/tests/cases/fourslash/completionListInUnclosedFunction06.ts
new file mode 100644
index 00000000000..3ceaff78039
--- /dev/null
+++ b/tests/cases/fourslash/completionListInUnclosedFunction06.ts
@@ -0,0 +1,17 @@
+///
+
+////function foo(x: string, y: number, z: boolean) {
+//// function bar(a: number, b: string = /*1*/, c: typeof x = "hello"
+////
+
+goTo.marker("1");
+
+verify.memberListContains("foo");
+verify.memberListContains("x");
+verify.memberListContains("y");
+verify.memberListContains("z");
+
+verify.memberListContains("bar");
+verify.memberListContains("a");
+verify.memberListContains("b");
+verify.memberListContains("c"); // definitely questionable
\ No newline at end of file
diff --git a/tests/cases/fourslash/completionListInUnclosedFunction07.ts b/tests/cases/fourslash/completionListInUnclosedFunction07.ts
new file mode 100644
index 00000000000..6968a878a77
--- /dev/null
+++ b/tests/cases/fourslash/completionListInUnclosedFunction07.ts
@@ -0,0 +1,17 @@
+///
+
+////function foo(x: string, y: number, z: boolean) {
+//// function bar(a: number, b: string = /*1*/, c: typeof x = "hello"
+////}
+
+goTo.marker("1");
+
+verify.memberListContains("foo");
+verify.memberListContains("x");
+verify.memberListContains("y");
+verify.memberListContains("z");
+
+verify.memberListContains("bar");
+verify.memberListContains("a");
+verify.memberListContains("b");
+verify.memberListContains("c"); // definitely questionable
\ No newline at end of file
diff --git a/tests/cases/fourslash/completionListInUnclosedFunction08.ts b/tests/cases/fourslash/completionListInUnclosedFunction08.ts
new file mode 100644
index 00000000000..5e8b15941c1
--- /dev/null
+++ b/tests/cases/fourslash/completionListInUnclosedFunction08.ts
@@ -0,0 +1,19 @@
+///
+
+////function foo(x: string, y: number, z: boolean) {
+//// function bar(a: number, b: string = "hello", c: typeof x = "hello") {
+//// var v = /*1*/
+
+goTo.marker("1");
+
+verify.memberListContains("foo");
+verify.memberListContains("x");
+verify.memberListContains("y");
+verify.memberListContains("z");
+
+verify.memberListContains("bar");
+verify.memberListContains("a");
+verify.memberListContains("b");
+verify.memberListContains("c");
+
+verify.memberListContains("v"); // questionable
\ No newline at end of file
diff --git a/tests/cases/fourslash/completionListInUnclosedFunction09.ts b/tests/cases/fourslash/completionListInUnclosedFunction09.ts
new file mode 100644
index 00000000000..0171ef96342
--- /dev/null
+++ b/tests/cases/fourslash/completionListInUnclosedFunction09.ts
@@ -0,0 +1,20 @@
+///
+
+////function foo(x: string, y: number, z: boolean) {
+//// function bar(a: number, b: string = "hello", c: typeof x = "hello") {
+//// var v = /*1*/
+////}
+
+goTo.marker("1");
+
+verify.memberListContains("foo");
+verify.memberListContains("x");
+verify.memberListContains("y");
+verify.memberListContains("z");
+
+verify.memberListContains("bar");
+verify.memberListContains("a");
+verify.memberListContains("b");
+verify.memberListContains("c");
+
+verify.memberListContains("v"); // questionable
\ No newline at end of file
diff --git a/tests/cases/fourslash/completionListInUnclosedFunction10.ts b/tests/cases/fourslash/completionListInUnclosedFunction10.ts
new file mode 100644
index 00000000000..1d0162b600b
--- /dev/null
+++ b/tests/cases/fourslash/completionListInUnclosedFunction10.ts
@@ -0,0 +1,12 @@
+///
+
+////interface MyType {
+////}
+////
+////function foo(x: string, y: number, z: boolean) {
+//// function bar(a: number, b: string = "hello", c: typeof x = "hello") {
+//// var v = (p: /*1*/
+
+goTo.marker("1");
+
+verify.memberListContains("MyType");
\ No newline at end of file
diff --git a/tests/cases/fourslash/completionListInUnclosedFunction11.ts b/tests/cases/fourslash/completionListInUnclosedFunction11.ts
new file mode 100644
index 00000000000..1d0162b600b
--- /dev/null
+++ b/tests/cases/fourslash/completionListInUnclosedFunction11.ts
@@ -0,0 +1,12 @@
+///
+
+////interface MyType {
+////}
+////
+////function foo(x: string, y: number, z: boolean) {
+//// function bar(a: number, b: string = "hello", c: typeof x = "hello") {
+//// var v = (p: /*1*/
+
+goTo.marker("1");
+
+verify.memberListContains("MyType");
\ No newline at end of file
diff --git a/tests/cases/fourslash/completionListInUnclosedFunction12.ts b/tests/cases/fourslash/completionListInUnclosedFunction12.ts
new file mode 100644
index 00000000000..b0e36b2fb8a
--- /dev/null
+++ b/tests/cases/fourslash/completionListInUnclosedFunction12.ts
@@ -0,0 +1,13 @@
+///
+
+////interface MyType {
+////}
+////
+////function foo(x: string, y: number, z: boolean) {
+//// function bar(a: number, b: string = "hello", c: typeof x = "hello") {
+//// var v = (p: /*1*/
+////}
+
+goTo.marker("1");
+
+verify.memberListContains("MyType");
\ No newline at end of file
diff --git a/tests/cases/fourslash/completionListInUnclosedFunction13.ts b/tests/cases/fourslash/completionListInUnclosedFunction13.ts
new file mode 100644
index 00000000000..8e1334941ad
--- /dev/null
+++ b/tests/cases/fourslash/completionListInUnclosedFunction13.ts
@@ -0,0 +1,14 @@
+///
+
+////interface MyType {
+////}
+////
+////function foo(x: string, y: number, z: boolean) {
+//// function bar(a: number, b: string = "hello", c: typeof x = "hello") {
+//// var v = (p: /*1*/
+//// }
+////}
+
+goTo.marker("1");
+
+verify.memberListContains("MyType");
\ No newline at end of file
diff --git a/tests/cases/fourslash/completionListInUnclosedFunction14.ts b/tests/cases/fourslash/completionListInUnclosedFunction14.ts
new file mode 100644
index 00000000000..412fcd86670
--- /dev/null
+++ b/tests/cases/fourslash/completionListInUnclosedFunction14.ts
@@ -0,0 +1,25 @@
+///
+
+////interface MyType {
+////}
+////
+////function foo(x: string, y: number, z: boolean) {
+//// function bar(a: number, b: string = "hello", c: typeof x = "hello") {
+//// var v = (p: MyType) => /*1*/
+//// }
+////}
+
+goTo.marker("1");
+
+verify.memberListContains("foo");
+verify.memberListContains("x");
+verify.memberListContains("y");
+verify.memberListContains("z");
+
+verify.memberListContains("bar");
+verify.memberListContains("a");
+verify.memberListContains("b");
+verify.memberListContains("c");
+
+verify.memberListContains("v");
+verify.memberListContains("p");
\ No newline at end of file
diff --git a/tests/cases/fourslash/completionListInUnclosedFunction15.ts b/tests/cases/fourslash/completionListInUnclosedFunction15.ts
new file mode 100644
index 00000000000..73a59795396
--- /dev/null
+++ b/tests/cases/fourslash/completionListInUnclosedFunction15.ts
@@ -0,0 +1,24 @@
+///
+
+////interface MyType {
+////}
+////
+////function foo(x: string, y: number, z: boolean) {
+//// function bar(a: number, b: string = "hello", c: typeof x = "hello") {
+//// var v = (p: MyType) => /*1*/
+////}
+
+goTo.marker("1");
+
+verify.memberListContains("foo");
+verify.memberListContains("x");
+verify.memberListContains("y");
+verify.memberListContains("z");
+
+verify.memberListContains("bar");
+verify.memberListContains("a");
+verify.memberListContains("b");
+verify.memberListContains("c");
+
+verify.memberListContains("v");
+verify.memberListContains("p");
\ No newline at end of file
diff --git a/tests/cases/fourslash/completionListInUnclosedFunction16.ts b/tests/cases/fourslash/completionListInUnclosedFunction16.ts
new file mode 100644
index 00000000000..4ec5f41df53
--- /dev/null
+++ b/tests/cases/fourslash/completionListInUnclosedFunction16.ts
@@ -0,0 +1,23 @@
+///
+
+////interface MyType {
+////}
+////
+////function foo(x: string, y: number, z: boolean) {
+//// function bar(a: number, b: string = "hello", c: typeof x = "hello") {
+//// var v = (p: MyType) => /*1*/
+
+goTo.marker("1");
+
+verify.memberListContains("foo");
+verify.memberListContains("x");
+verify.memberListContains("y");
+verify.memberListContains("z");
+
+verify.memberListContains("bar");
+verify.memberListContains("a");
+verify.memberListContains("b");
+verify.memberListContains("c");
+
+verify.memberListContains("v");
+verify.memberListContains("p");
\ No newline at end of file
diff --git a/tests/cases/fourslash/completionListInUnclosedFunction17.ts b/tests/cases/fourslash/completionListInUnclosedFunction17.ts
new file mode 100644
index 00000000000..8cded845673
--- /dev/null
+++ b/tests/cases/fourslash/completionListInUnclosedFunction17.ts
@@ -0,0 +1,23 @@
+///
+
+////interface MyType {
+////}
+////
+////function foo(x: string, y: number, z: boolean) {
+//// function bar(a: number, b: string = "hello", c: typeof x = "hello") {
+//// var v = (p: MyType) => y + /*1*/
+
+goTo.marker("1");
+
+verify.memberListContains("foo");
+verify.memberListContains("x");
+verify.memberListContains("y");
+verify.memberListContains("z");
+
+verify.memberListContains("bar");
+verify.memberListContains("a");
+verify.memberListContains("b");
+verify.memberListContains("c");
+
+verify.memberListContains("v");
+verify.memberListContains("p");
\ No newline at end of file
diff --git a/tests/cases/fourslash/completionListInUnclosedFunction18.ts b/tests/cases/fourslash/completionListInUnclosedFunction18.ts
new file mode 100644
index 00000000000..182694d73d2
--- /dev/null
+++ b/tests/cases/fourslash/completionListInUnclosedFunction18.ts
@@ -0,0 +1,24 @@
+///
+
+////interface MyType {
+////}
+////
+////function foo(x: string, y: number, z: boolean) {
+//// function bar(a: number, b: string = "hello", c: typeof x = "hello") {
+//// var v = (p: MyType) => y + /*1*/
+////}
+
+goTo.marker("1");
+
+verify.memberListContains("foo");
+verify.memberListContains("x");
+verify.memberListContains("y");
+verify.memberListContains("z");
+
+verify.memberListContains("bar");
+verify.memberListContains("a");
+verify.memberListContains("b");
+verify.memberListContains("c");
+
+verify.memberListContains("v");
+verify.memberListContains("p");
\ No newline at end of file
diff --git a/tests/cases/fourslash/completionListInUnclosedFunction19.ts b/tests/cases/fourslash/completionListInUnclosedFunction19.ts
new file mode 100644
index 00000000000..6f49f270250
--- /dev/null
+++ b/tests/cases/fourslash/completionListInUnclosedFunction19.ts
@@ -0,0 +1,23 @@
+///
+
+////interface MyType {
+////}
+////
+////function foo(x: string, y: number, z: boolean) {
+//// function bar(a: number, b: string = "hello", c: typeof x = "hello") {
+//// var v = (p: MyType) => { return y + /*1*/
+
+goTo.marker("1");
+
+verify.memberListContains("foo");
+verify.memberListContains("x");
+verify.memberListContains("y");
+verify.memberListContains("z");
+
+verify.memberListContains("bar");
+verify.memberListContains("a");
+verify.memberListContains("b");
+verify.memberListContains("c");
+
+verify.memberListContains("v");
+verify.memberListContains("p");
\ No newline at end of file
diff --git a/tests/cases/fourslash/completionListInUnclosedIndexSignature01.ts b/tests/cases/fourslash/completionListInUnclosedIndexSignature01.ts
new file mode 100644
index 00000000000..0667742d4cb
--- /dev/null
+++ b/tests/cases/fourslash/completionListInUnclosedIndexSignature01.ts
@@ -0,0 +1,10 @@
+///
+
+
+////class C {
+//// [foo: string]: typeof /*1*/
+////}
+
+goTo.marker("1");
+verify.completionListContains("foo");
+verify.completionListContains("C");
\ No newline at end of file
diff --git a/tests/cases/fourslash/completionListInUnclosedIndexSignature02.ts b/tests/cases/fourslash/completionListInUnclosedIndexSignature02.ts
new file mode 100644
index 00000000000..318730e41a6
--- /dev/null
+++ b/tests/cases/fourslash/completionListInUnclosedIndexSignature02.ts
@@ -0,0 +1,13 @@
+///
+
+
+////class C {
+//// [foo: /*1*/
+////}
+
+goTo.marker("1");
+verify.completionListContains("C");
+verify.completionListContains("foo"); // ideally this shouldn't show up for a type
+edit.insert("typeof ");
+verify.completionListContains("C");
+verify.completionListContains("foo");
\ No newline at end of file
diff --git a/tests/cases/fourslash/completionListInUnclosedIndexSignature03.ts b/tests/cases/fourslash/completionListInUnclosedIndexSignature03.ts
new file mode 100644
index 00000000000..bb4ef808bff
--- /dev/null
+++ b/tests/cases/fourslash/completionListInUnclosedIndexSignature03.ts
@@ -0,0 +1,10 @@
+///
+
+
+////class C {
+//// [foo: string]: { x: typeof /*1*/
+////}
+
+goTo.marker("1");
+verify.completionListContains("foo");
+verify.completionListContains("C");
\ No newline at end of file
diff --git a/tests/cases/fourslash/completionListInUnclosedObjectTypeLiteralInSignature01.ts b/tests/cases/fourslash/completionListInUnclosedObjectTypeLiteralInSignature01.ts
new file mode 100644
index 00000000000..a931bed6a4b
--- /dev/null
+++ b/tests/cases/fourslash/completionListInUnclosedObjectTypeLiteralInSignature01.ts
@@ -0,0 +1,18 @@
+///
+
+////interface I {
+//// [s: string]: TString;
+//// [s: number]: TNumber;
+////}
+////
+////declare function foo(obj: I): { str: T/*1*/
+
+goTo.marker("1");
+
+verify.memberListContains("I");
+verify.memberListContains("TString");
+verify.memberListContains("TNumber");
+
+// Ideally the following shouldn't show up since they're not types.
+verify.memberListContains("foo");
+verify.memberListContains("obj");
diff --git a/tests/cases/fourslash/completionListInUnclosedObjectTypeLiteralInSignature02.ts b/tests/cases/fourslash/completionListInUnclosedObjectTypeLiteralInSignature02.ts
new file mode 100644
index 00000000000..32a9504ebc3
--- /dev/null
+++ b/tests/cases/fourslash/completionListInUnclosedObjectTypeLiteralInSignature02.ts
@@ -0,0 +1,18 @@
+///
+
+////interface I {
+//// [s: string]: TString;
+//// [s: number]: TNumber;
+////}
+////
+////declare function foo(obj: I): { str: TStr/*1*/
+
+goTo.marker("1");
+
+verify.memberListContains("I");
+verify.memberListContains("TString");
+verify.memberListContains("TNumber"); // REVIEW: Is this intended behavior?
+
+// Ideally the following shouldn't show up since they're not types.
+verify.memberListContains("foo");
+verify.memberListContains("obj");
diff --git a/tests/cases/fourslash/completionListInUnclosedObjectTypeLiteralInSignature03.ts b/tests/cases/fourslash/completionListInUnclosedObjectTypeLiteralInSignature03.ts
new file mode 100644
index 00000000000..455f122888c
--- /dev/null
+++ b/tests/cases/fourslash/completionListInUnclosedObjectTypeLiteralInSignature03.ts
@@ -0,0 +1,18 @@
+///
+
+////interface I {
+//// [s: string]: TString;
+//// [s: number]: TNumber;
+////}
+////
+////declare function foo(obj: I): { str: TString/*1*/
+
+goTo.marker("1");
+
+verify.memberListContains("I");
+verify.memberListContains("TString");
+verify.memberListContains("TNumber"); // REVIEW: Is this intended behavior?
+
+// Ideally the following shouldn't show up since they're not types.
+verify.memberListContains("foo");
+verify.memberListContains("obj");
diff --git a/tests/cases/fourslash/completionListInUnclosedObjectTypeLiteralInSignature04.ts b/tests/cases/fourslash/completionListInUnclosedObjectTypeLiteralInSignature04.ts
new file mode 100644
index 00000000000..c7f53e0e0df
--- /dev/null
+++ b/tests/cases/fourslash/completionListInUnclosedObjectTypeLiteralInSignature04.ts
@@ -0,0 +1,16 @@
+///
+
+////interface I {
+//// [s: string]: TString;
+//// [s: number]: TNumber;
+////}
+////
+////declare function foo(obj: I): { /*1*/
+
+goTo.marker("1");
+
+verify.not.memberListContains("I");
+verify.not.memberListContains("TString");
+verify.not.memberListContains("TNumber");
+verify.not.memberListContains("foo");
+verify.not.memberListContains("obj");
diff --git a/tests/cases/fourslash/completionListInUnclosedSpreadExpression01.ts b/tests/cases/fourslash/completionListInUnclosedSpreadExpression01.ts
new file mode 100644
index 00000000000..b9cc01f0a66
--- /dev/null
+++ b/tests/cases/fourslash/completionListInUnclosedSpreadExpression01.ts
@@ -0,0 +1,7 @@
+///
+
+////var x;
+////var y = [1,2,.../*1*/
+
+goTo.marker("1");
+verify.completionListContains("x");
\ No newline at end of file
diff --git a/tests/cases/fourslash/completionListInUnclosedSpreadExpression02.ts b/tests/cases/fourslash/completionListInUnclosedSpreadExpression02.ts
new file mode 100644
index 00000000000..40d90370232
--- /dev/null
+++ b/tests/cases/fourslash/completionListInUnclosedSpreadExpression02.ts
@@ -0,0 +1,8 @@
+///
+
+////var x;
+////var y = (p) => [1,2,.../*1*/
+
+goTo.marker("1");
+verify.completionListContains("p");
+verify.completionListContains("x");
\ No newline at end of file
diff --git a/tests/cases/fourslash/completionListInUnclosedTaggedTemplate01.ts b/tests/cases/fourslash/completionListInUnclosedTaggedTemplate01.ts
new file mode 100644
index 00000000000..20e2a5d0663
--- /dev/null
+++ b/tests/cases/fourslash/completionListInUnclosedTaggedTemplate01.ts
@@ -0,0 +1,8 @@
+///
+
+////var x;
+////var y = (p) => x `abc ${ /*1*/
+
+goTo.marker("1");
+verify.completionListContains("p");
+verify.completionListContains("x");
\ No newline at end of file
diff --git a/tests/cases/fourslash/completionListInUnclosedTaggedTemplate02.ts b/tests/cases/fourslash/completionListInUnclosedTaggedTemplate02.ts
new file mode 100644
index 00000000000..d4bbd5992c6
--- /dev/null
+++ b/tests/cases/fourslash/completionListInUnclosedTaggedTemplate02.ts
@@ -0,0 +1,8 @@
+///
+
+////var x;
+////var y = (p) => x `abc ${ 123 } ${ /*1*/
+
+goTo.marker("1");
+verify.completionListContains("p");
+verify.completionListContains("x");
\ No newline at end of file
diff --git a/tests/cases/fourslash/completionListInUnclosedTemplate01.ts b/tests/cases/fourslash/completionListInUnclosedTemplate01.ts
new file mode 100644
index 00000000000..c7b8f628170
--- /dev/null
+++ b/tests/cases/fourslash/completionListInUnclosedTemplate01.ts
@@ -0,0 +1,8 @@
+///
+
+////var x;
+////var y = (p) => `abc ${ /*1*/
+
+goTo.marker("1");
+verify.completionListContains("p");
+verify.completionListContains("x");
\ No newline at end of file
diff --git a/tests/cases/fourslash/completionListInUnclosedTemplate02.ts b/tests/cases/fourslash/completionListInUnclosedTemplate02.ts
new file mode 100644
index 00000000000..5fd5c94ee3e
--- /dev/null
+++ b/tests/cases/fourslash/completionListInUnclosedTemplate02.ts
@@ -0,0 +1,8 @@
+///
+
+////var x;
+////var y = (p) => `abc ${ 123 } ${ /*1*/
+
+goTo.marker("1");
+verify.completionListContains("p");
+verify.completionListContains("x");
\ No newline at end of file
diff --git a/tests/cases/fourslash/completionListInUnclosedTypeOfExpression01.ts b/tests/cases/fourslash/completionListInUnclosedTypeOfExpression01.ts
new file mode 100644
index 00000000000..3da8b4fd616
--- /dev/null
+++ b/tests/cases/fourslash/completionListInUnclosedTypeOfExpression01.ts
@@ -0,0 +1,7 @@
+///
+
+////var x;
+////var y = typeof /*1*/
+
+goTo.marker("1");
+verify.completionListContains("x");
\ No newline at end of file
diff --git a/tests/cases/fourslash/completionListInUnclosedTypeOfExpression02.ts b/tests/cases/fourslash/completionListInUnclosedTypeOfExpression02.ts
new file mode 100644
index 00000000000..b1d347211ac
--- /dev/null
+++ b/tests/cases/fourslash/completionListInUnclosedTypeOfExpression02.ts
@@ -0,0 +1,8 @@
+///
+
+////var x;
+////var y = (p) => typeof /*1*/
+
+goTo.marker("1");
+verify.completionListContains("x");
+verify.completionListContains("p");
\ No newline at end of file
diff --git a/tests/cases/fourslash/completionListInUnclosedVoidExpression01.ts b/tests/cases/fourslash/completionListInUnclosedVoidExpression01.ts
new file mode 100644
index 00000000000..d1cfecbffec
--- /dev/null
+++ b/tests/cases/fourslash/completionListInUnclosedVoidExpression01.ts
@@ -0,0 +1,8 @@
+///
+
+////var x;
+////var y = (p) => void /*1*/
+
+goTo.marker("1");
+verify.completionListContains("p");
+verify.completionListContains("x");
\ No newline at end of file
diff --git a/tests/cases/fourslash/completionListInUnclosedYieldExpression01.ts b/tests/cases/fourslash/completionListInUnclosedYieldExpression01.ts
new file mode 100644
index 00000000000..658b0de7dc8
--- /dev/null
+++ b/tests/cases/fourslash/completionListInUnclosedYieldExpression01.ts
@@ -0,0 +1,10 @@
+///
+
+////var x;
+////var y = function* gen(p) { yield /*1*/
+
+goTo.marker("1");
+// These tentatively don't work.
+verify.not.completionListContains("p");
+verify.not.completionListContains("gen");
+verify.not.completionListContains("x");
\ No newline at end of file
diff --git a/tests/cases/fourslash/completionListOutsideOfClosedArrowFunction01.ts b/tests/cases/fourslash/completionListOutsideOfClosedArrowFunction01.ts
new file mode 100644
index 00000000000..d775371796f
--- /dev/null
+++ b/tests/cases/fourslash/completionListOutsideOfClosedArrowFunction01.ts
@@ -0,0 +1,8 @@
+///
+
+////// no a or b
+/////*1*/(a, b) => { }
+
+goTo.marker("1");
+verify.not.completionListContains("a");
+verify.not.completionListContains("b");
\ No newline at end of file
diff --git a/tests/cases/fourslash/completionListOutsideOfClosedArrowFunction02.ts b/tests/cases/fourslash/completionListOutsideOfClosedArrowFunction02.ts
new file mode 100644
index 00000000000..d9195ce5b97
--- /dev/null
+++ b/tests/cases/fourslash/completionListOutsideOfClosedArrowFunction02.ts
@@ -0,0 +1,8 @@
+///
+
+////// no a or b
+////(a, b) => { }/*1*/
+
+goTo.marker("1");
+verify.not.completionListContains("a");
+verify.not.completionListContains("b");
\ No newline at end of file
diff --git a/tests/cases/fourslash/completionListOutsideOfClosedFunctionDeclaration01.ts b/tests/cases/fourslash/completionListOutsideOfClosedFunctionDeclaration01.ts
new file mode 100644
index 00000000000..8b6077e0f8b
--- /dev/null
+++ b/tests/cases/fourslash/completionListOutsideOfClosedFunctionDeclaration01.ts
@@ -0,0 +1,8 @@
+///
+
+////// no a or b
+/////*1*/function f (a, b) {}
+
+goTo.marker("1");
+verify.not.completionListContains("a");
+verify.not.completionListContains("b");
\ No newline at end of file
diff --git a/tests/cases/fourslash/completionListOutsideOfForLoop01.ts b/tests/cases/fourslash/completionListOutsideOfForLoop01.ts
new file mode 100644
index 00000000000..473a39a453d
--- /dev/null
+++ b/tests/cases/fourslash/completionListOutsideOfForLoop01.ts
@@ -0,0 +1,6 @@
+///
+
+////for (let i = 0; i < 10; i++) i;/*1*/
+
+goTo.marker("1");
+verify.not.completionListContains("i");
\ No newline at end of file
diff --git a/tests/cases/fourslash/completionListOutsideOfForLoop02.ts b/tests/cases/fourslash/completionListOutsideOfForLoop02.ts
new file mode 100644
index 00000000000..b1186ac7cce
--- /dev/null
+++ b/tests/cases/fourslash/completionListOutsideOfForLoop02.ts
@@ -0,0 +1,6 @@
+///
+
+////for (let i = 0; i < 10; i++);/*1*/
+
+goTo.marker("1");
+verify.not.completionListContains("i");
\ No newline at end of file