function getCompletionData(fileName, position) {
            var typeChecker = program.getTypeChecker();
            var syntacticStart = new Date().getTime();
            var sourceFile = getValidSourceFile(fileName);
            var isJavaScriptFile = ts.isSourceFileJavaScript(sourceFile);
            var isJsDocTagName = false;
            var start = new Date().getTime();
            var currentToken = ts.getTokenAtPosition(sourceFile, position);
            log("getCompletionData: Get current token: " + (new Date().getTime() - start));
            start = new Date().getTime();
            // Completion not allowed inside comments, bail out if this is the case
            var insideComment = isInsideComment(sourceFile, currentToken, position);
            log("getCompletionData: Is inside comment: " + (new Date().getTime() - start));
            if (insideComment) {
                // The current position is next to the '@' sign, when no tag name being provided yet. 
                // Provide a full list of tag names
                if (ts.hasDocComment(sourceFile, position) && sourceFile.text.charCodeAt(position - 1) === 64 /* at */) {
                    isJsDocTagName = true;
                }
                // Completion should work inside certain JsDoc tags. For example:
                //     /** @type {number | string} */
                // Completion should work in the brackets
                var insideJsDocTagExpression = false;
                var tag = ts.getJsDocTagAtPosition(sourceFile, position);
                if (tag) {
                    if (tag.tagName.pos <= position && position <= tag.tagName.end) {
                        isJsDocTagName = true;
                    }
                    switch (tag.kind) {
                        case 269 /* JSDocTypeTag */:
                        case 267 /* JSDocParameterTag */:
                        case 268 /* JSDocReturnTag */:
                            var tagWithExpression = tag;
                            if (tagWithExpression.typeExpression) {
                                insideJsDocTagExpression = tagWithExpression.typeExpression.pos < position && position < tagWithExpression.typeExpression.end;
                            }
                            break;
                    }
                }
                if (isJsDocTagName) {
                    return { symbols: undefined, isMemberCompletion: false, isNewIdentifierLocation: false, location: undefined, isRightOfDot: false, isJsDocTagName: isJsDocTagName };
                }
                if (!insideJsDocTagExpression) {
                    // 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.");
                    return undefined;
                }
            }
            start = new Date().getTime();
            var previousToken = ts.findPrecedingToken(position, sourceFile);
            log("getCompletionData: Get previous token 1: " + (new Date().getTime() - start));
            // The decision to provide completion depends on the contextToken, which is determined through the previousToken.
            // Note: 'previousToken' (and thus 'contextToken') can be undefined if we are the beginning of the file
            var contextToken = previousToken;
            // Check if the caret is at the end of an identifier; this is a partial identifier that we want to complete: e.g. a.toS|
            // Skip this partial identifier and adjust the contextToken to the token that precedes it.
            if (contextToken && position <= contextToken.end && ts.isWord(contextToken.kind)) {
                var start_3 = new Date().getTime();
                contextToken = ts.findPrecedingToken(contextToken.getFullStart(), sourceFile);
                log("getCompletionData: Get previous token 2: " + (new Date().getTime() - start_3));
            }
            // Find the node where completion is requested on.
            // Also determine whether we are trying to complete with members of that node
            // or attributes of a JSX tag.
            var node = currentToken;
            var isRightOfDot = false;
            var isRightOfOpenTag = false;
            var isStartingCloseTag = false;
            var location = ts.getTouchingPropertyName(sourceFile, position);
            if (contextToken) {
                // Bail out if this is a known invalid completion location
                if (isCompletionListBlocker(contextToken)) {
                    log("Returning an empty list because completion was requested in an invalid position.");
                    return undefined;
                }
                var parent_9 = contextToken.parent, kind = contextToken.kind;
                if (kind === 21 /* DotToken */) {
                    if (parent_9.kind === 166 /* PropertyAccessExpression */) {
                        node = contextToken.parent.expression;
                        isRightOfDot = true;
                    }
                    else if (parent_9.kind === 135 /* QualifiedName */) {
                        node = contextToken.parent.left;
                        isRightOfDot = true;
                    }
                    else {
                        // There is nothing that precedes the dot, so this likely just a stray character
                        // or leading into a '...' token. Just bail out instead.
                        return undefined;
                    }
                }
                else if (sourceFile.languageVariant === 1 /* JSX */) {
                    if (kind === 25 /* LessThanToken */) {
                        isRightOfOpenTag = true;
                        location = contextToken;
                    }
                    else if (kind === 39 /* SlashToken */ && contextToken.parent.kind === 237 /* JsxClosingElement */) {
                        isStartingCloseTag = true;
                    }
                }
            }
            var semanticStart = new Date().getTime();
            var isMemberCompletion;
            var isNewIdentifierLocation;
            var symbols = [];
            if (isRightOfDot) {
                getTypeScriptMemberSymbols();
            }
            else if (isRightOfOpenTag) {
                var tagSymbols = typeChecker.getJsxIntrinsicTagNames();
                if (tryGetGlobalSymbols()) {
                    symbols = tagSymbols.concat(symbols.filter(function (s) { return !!(s.flags & 107455 /* Value */); }));
                }
                else {
                    symbols = tagSymbols;
                }
                isMemberCompletion = true;
                isNewIdentifierLocation = false;
            }
            else if (isStartingCloseTag) {
                var tagName = contextToken.parent.parent.openingElement.tagName;
                symbols = [typeChecker.getSymbolAtLocation(tagName)];
                isMemberCompletion = true;
                isNewIdentifierLocation = false;
            }
            else {
                // For JavaScript or TypeScript, if we're not after a dot, then just try to get the
                // global symbols in scope.  These results should be valid for either language as
                // the set of symbols that can be referenced from this location.
                if (!tryGetGlobalSymbols()) {
                    return undefined;
                }
            }
            log("getCompletionData: Semantic work: " + (new Date().getTime() - semanticStart));
            return { symbols: symbols, isMemberCompletion: isMemberCompletion, isNewIdentifierLocation: isNewIdentifierLocation, location: location, isRightOfDot: (isRightOfDot || isRightOfOpenTag), isJsDocTagName: isJsDocTagName };
            function getTypeScriptMemberSymbols() {
                // Right of dot member completion list
                isMemberCompletion = true;
                isNewIdentifierLocation = false;
                if (node.kind === 69 /* Identifier */ || node.kind === 135 /* QualifiedName */ || node.kind === 166 /* PropertyAccessExpression */) {
                    var symbol = typeChecker.getSymbolAtLocation(node);
                    // This is an alias, follow what it aliases
                    if (symbol && symbol.flags & 8388608 /* Alias */) {
                        symbol = typeChecker.getAliasedSymbol(symbol);
                    }
                    if (symbol && symbol.flags & 1952 /* HasExports */) {
                        // Extract module or enum members
                        var exportedSymbols = typeChecker.getExportsOfModule(symbol);
                        ts.forEach(exportedSymbols, function (symbol) {
                            if (typeChecker.isValidPropertyAccess((node.parent), symbol.name)) {
                                symbols.push(symbol);
                            }
                        });
                    }
                }
                var type = typeChecker.getTypeAtLocation(node);
                addTypeProperties(type);
            }
            function addTypeProperties(type) {
                if (type) {
                    // Filter private properties
                    for (var _i = 0, _a = type.getApparentProperties(); _i < _a.length; _i++) {
                        var symbol = _a[_i];
                        if (typeChecker.isValidPropertyAccess((node.parent), symbol.name)) {
                            symbols.push(symbol);
                        }
                    }
                    if (isJavaScriptFile && type.flags & 16384 /* Union */) {
                        // In javascript files, for union types, we don't just get the members that
                        // the individual types have in common, we also include all the members that
                        // each individual type has.  This is because we're going to add all identifiers
                        // anyways.  So we might as well elevate the members that were at least part
                        // of the individual types to a higher status since we know what they are.
                        var unionType = type;
                        for (var _b = 0, _c = unionType.types; _b < _c.length; _b++) {
                            var elementType = _c[_b];
                            addTypeProperties(elementType);
                        }
                    }
                }
            }
            function tryGetGlobalSymbols() {
                var objectLikeContainer;
                var namedImportsOrExports;
                var jsxContainer;
                if (objectLikeContainer = tryGetObjectLikeCompletionContainer(contextToken)) {
                    return tryGetObjectLikeCompletionSymbols(objectLikeContainer);
                }
                if (namedImportsOrExports = tryGetNamedImportsOrExportsForCompletion(contextToken)) {
                    // cursor is in an import clause
                    // try to show exported member for imported module
                    return tryGetImportOrExportClauseCompletionSymbols(namedImportsOrExports);
                }
                if (jsxContainer = tryGetContainingJsxElement(contextToken)) {
                    var attrsType;
                    if ((jsxContainer.kind === 234 /* JsxSelfClosingElement */) || (jsxContainer.kind === 235 /* JsxOpeningElement */)) {
                        // Cursor is inside a JSX self-closing element or opening element
                        attrsType = typeChecker.getJsxElementAttributesType(jsxContainer);
                        if (attrsType) {
                            symbols = filterJsxAttributes(typeChecker.getPropertiesOfType(attrsType), jsxContainer.attributes);
                            isMemberCompletion = true;
                            isNewIdentifierLocation = false;
                            return true;
                        }
                    }
                }
                // Get all entities in the current scope.
                isMemberCompletion = false;
                isNewIdentifierLocation = isNewIdentifierDefinitionLocation(contextToken);
                if (previousToken !== contextToken) {
                    ts.Debug.assert(!!previousToken, "Expected 'contextToken' to be defined when different from 'previousToken'.");
                }
                // We need to find the node that will give us an appropriate scope to begin
                // aggregating completion candidates. This is achieved in 'getScopeNode'
                // by finding the first node that encompasses a position, accounting for whether a node
                // is "complete" to decide whether a position belongs to the node.
                //
                // However, at the end of an identifier, we are interested in the scope of the identifier
                // itself, but fall outside of the identifier. For instance:
                //
                //      xyz => x$
                //
                // the cursor is outside of both the 'x' and the arrow function 'xyz => x',
                // so 'xyz' is not returned in our results.
                //
                // We define 'adjustedPosition' so that we may appropriately account for
                // being at the end of an identifier. The intention is that if requesting completion
                // at the end of an identifier, it should be effectively equivalent to requesting completion
                // anywhere inside/at the beginning of the identifier. So in the previous case, the
                // 'adjustedPosition' will work as if requesting completion in the following:
                //
                //      xyz => $x
                //
                // If previousToken !== contextToken, then
                //   - 'contextToken' was adjusted to the token prior to 'previousToken'
                //      because we were at the end of an identifier.
                //   - 'previousToken' is defined.
                var adjustedPosition = previousToken !== contextToken ?
                    previousToken.getStart() :
                    position;
                var scopeNode = getScopeNode(contextToken, adjustedPosition, sourceFile) || sourceFile;
                /// TODO filter meaning based on the current context
                var symbolMeanings = 793056 /* Type */ | 107455 /* Value */ | 1536 /* Namespace */ | 8388608 /* Alias */;
                symbols = typeChecker.getSymbolsInScope(scopeNode, symbolMeanings);
                return true;
            }
            /**
             * Finds the first node that "embraces" the position, so that one may
             * accurately aggregate locals from the closest containing scope.
             */
            function getScopeNode(initialToken, position, sourceFile) {
                var scope = initialToken;
                while (scope && !ts.positionBelongsToNode(scope, position, sourceFile)) {
                    scope = scope.parent;
                }
                return scope;
            }
            function isCompletionListBlocker(contextToken) {
                var start = new Date().getTime();
                var result = isInStringOrRegularExpressionOrTemplateLiteral(contextToken) ||
                    isSolelyIdentifierDefinitionLocation(contextToken) ||
                    isDotOfNumericLiteral(contextToken) ||
                    isInJsxText(contextToken);
                log("getCompletionsAtPosition: isCompletionListBlocker: " + (new Date().getTime() - start));
                return result;
            }
            function isInJsxText(contextToken) {
                if (contextToken.kind === 236 /* JsxText */) {
                    return true;
                }
                if (contextToken.kind === 27 /* GreaterThanToken */ && contextToken.parent) {
                    if (contextToken.parent.kind === 235 /* JsxOpeningElement */) {
                        return true;
                    }
                    if (contextToken.parent.kind === 237 /* JsxClosingElement */ || contextToken.parent.kind === 234 /* JsxSelfClosingElement */) {
                        return contextToken.parent.parent && contextToken.parent.parent.kind === 233 /* JsxElement */;
                    }
                }
                return false;
            }
            function isNewIdentifierDefinitionLocation(previousToken) {
                if (previousToken) {
                    var containingNodeKind = previousToken.parent.kind;
                    switch (previousToken.kind) {
                        case 24 /* CommaToken */:
                            return containingNodeKind === 168 /* CallExpression */ // func( a, |
                                || containingNodeKind === 144 /* Constructor */ // constructor( a, |   /* public, protected, private keywords are allowed here, so show completion */
                                || containingNodeKind === 169 /* NewExpression */ // new C(a, |
                                || containingNodeKind === 164 /* ArrayLiteralExpression */ // [a, |
                                || containingNodeKind === 181 /* BinaryExpression */ // let x = (a, |
                                || containingNodeKind === 152 /* FunctionType */; // var x: (s: string, list|
                        case 17 /* OpenParenToken */:
                            return containingNodeKind === 168 /* CallExpression */ // func( |
                                || containingNodeKind === 144 /* Constructor */ // constructor( |
                                || containingNodeKind === 169 /* NewExpression */ // new C(a|
                                || containingNodeKind === 172 /* ParenthesizedExpression */ // let x = (a|
                                || containingNodeKind === 160 /* ParenthesizedType */; // function F(pred: (a| /* this can become an arrow function, where 'a' is the argument */
                        case 19 /* OpenBracketToken */:
                            return containingNodeKind === 164 /* ArrayLiteralExpression */ // [ |
                                || containingNodeKind === 149 /* IndexSignature */ // [ | : string ]
                                || containingNodeKind === 136 /* ComputedPropertyName */; // [ |    /* this can become an index signature */
                        case 125 /* ModuleKeyword */: // module |
                        case 126 /* NamespaceKeyword */:
                            return true;
                        case 21 /* DotToken */:
                            return containingNodeKind === 218 /* ModuleDeclaration */; // module A.|
                        case 15 /* OpenBraceToken */:
                            return containingNodeKind === 214 /* ClassDeclaration */; // class A{ |
                        case 56 /* EqualsToken */:
                            return containingNodeKind === 211 /* VariableDeclaration */ // let x = a|
                                || containingNodeKind === 181 /* BinaryExpression */; // x = a|
                        case 12 /* TemplateHead */:
                            return containingNodeKind === 183 /* TemplateExpression */; // `aa ${|
                        case 13 /* TemplateMiddle */:
                            return containingNodeKind === 190 /* TemplateSpan */; // `aa ${10} dd ${|
                        case 112 /* PublicKeyword */:
                        case 110 /* PrivateKeyword */:
                        case 111 /* ProtectedKeyword */:
                            return containingNodeKind === 141 /* PropertyDeclaration */; // class A{ public |
                    }
                    // Previous token may have been a keyword that was converted to an identifier.
                    switch (previousToken.getText()) {
                        case "public":
                        case "protected":
                        case "private":
                            return true;
                    }
                }
                return false;
            }
            function isInStringOrRegularExpressionOrTemplateLiteral(contextToken) {
                if (contextToken.kind === 9 /* StringLiteral */
                    || contextToken.kind === 10 /* RegularExpressionLiteral */
                    || ts.isTemplateLiteralKind(contextToken.kind)) {
                    var start_4 = contextToken.getStart();
                    var end = contextToken.getEnd();
                    // To be "in" one of these literals, the position has to be:
                    //   1. entirely within the token text.
                    //   2. at the end position of an unterminated token.
                    //   3. at the end of a regular expression (due to trailing flags like '/foo/g').
                    if (start_4 < position && position < end) {
                        return true;
                    }
                    if (position === end) {
                        return !!contextToken.isUnterminated
                            || contextToken.kind === 10 /* RegularExpressionLiteral */;
                    }
                }
                return false;
            }
            /**
             * Aggregates relevant symbols for completion in object literals and object binding patterns.
             * Relevant symbols are stored in the captured 'symbols' variable.
             *
             * @returns true if 'symbols' was successfully populated; false otherwise.
             */
            function tryGetObjectLikeCompletionSymbols(objectLikeContainer) {
                // We're looking up possible property names from contextual/inferred/declared type.
                isMemberCompletion = true;
                var typeForObject;
                var existingMembers;
                if (objectLikeContainer.kind === 165 /* ObjectLiteralExpression */) {
                    // We are completing on contextual types, but may also include properties
                    // other than those within the declared type.
                    isNewIdentifierLocation = true;
                    typeForObject = typeChecker.getContextualType(objectLikeContainer);
                    existingMembers = objectLikeContainer.properties;
                }
                else if (objectLikeContainer.kind === 161 /* ObjectBindingPattern */) {
                    // We are *only* completing on properties from the type being destructured.
                    isNewIdentifierLocation = false;
                    var rootDeclaration = ts.getRootDeclaration(objectLikeContainer.parent);
                    if (ts.isVariableLike(rootDeclaration)) {
                        // We don't want to complete using the type acquired by the shape
                        // of the binding pattern; we are only interested in types acquired
                        // through type declaration or inference.
                        if (rootDeclaration.initializer || rootDeclaration.type) {
                            typeForObject = typeChecker.getTypeAtLocation(objectLikeContainer);
                            existingMembers = objectLikeContainer.elements;
                        }
                    }
                    else {
                        ts.Debug.fail("Root declaration is not variable-like.");
                    }
                }
                else {
                    ts.Debug.fail("Expected object literal or binding pattern, got " + objectLikeContainer.kind);
                }
                if (!typeForObject) {
                    return false;
                }
                var typeMembers = typeChecker.getPropertiesOfType(typeForObject);
                if (typeMembers && typeMembers.length > 0) {
                    // Add filtered items to the completion list
                    symbols = filterObjectMembersList(typeMembers, existingMembers);
                }
                return true;
            }
            /**
             * Aggregates relevant symbols for completion in import clauses and export clauses
             * whose declarations have a module specifier; for instance, symbols will be aggregated for
             *
             *      import { | } from "moduleName";
             *      export { a as foo, | } from "moduleName";
             *
             * but not for
             *
             *      export { | };
             *
             * Relevant symbols are stored in the captured 'symbols' variable.
             *
             * @returns true if 'symbols' was successfully populated; false otherwise.
             */
            function tryGetImportOrExportClauseCompletionSymbols(namedImportsOrExports) {
                var declarationKind = namedImportsOrExports.kind === 225 /* NamedImports */ ?
                    222 /* ImportDeclaration */ :
                    228 /* ExportDeclaration */;
                var importOrExportDeclaration = ts.getAncestor(namedImportsOrExports, declarationKind);
                var moduleSpecifier = importOrExportDeclaration.moduleSpecifier;
                if (!moduleSpecifier) {
                    return false;
                }
                isMemberCompletion = true;
                isNewIdentifierLocation = false;
                var exports;
                var moduleSpecifierSymbol = typeChecker.getSymbolAtLocation(importOrExportDeclaration.moduleSpecifier);
                if (moduleSpecifierSymbol) {
                    exports = typeChecker.getExportsOfModule(moduleSpecifierSymbol);
                }
                symbols = exports ? filterNamedImportOrExportCompletionItems(exports, namedImportsOrExports.elements) : emptyArray;
                return true;
            }
            /**
             * Returns the immediate owning object literal or binding pattern of a context token,
             * on the condition that one exists and that the context implies completion should be given.
             */
            function tryGetObjectLikeCompletionContainer(contextToken) {
                if (contextToken) {
                    switch (contextToken.kind) {
                        case 15 /* OpenBraceToken */: // let x = { |
                        case 24 /* CommaToken */:
                            var parent_10 = contextToken.parent;
                            if (parent_10 && (parent_10.kind === 165 /* ObjectLiteralExpression */ || parent_10.kind === 161 /* ObjectBindingPattern */)) {
                                return parent_10;
                            }
                            break;
                    }
                }
                return undefined;
            }
            /**
             * Returns the containing list of named imports or exports of a context token,
             * on the condition that one exists and that the context implies completion should be given.
             */
            function tryGetNamedImportsOrExportsForCompletion(contextToken) {
                if (contextToken) {
                    switch (contextToken.kind) {
                        case 15 /* OpenBraceToken */: // import { |
                        case 24 /* CommaToken */:
                            switch (contextToken.parent.kind) {
                                case 225 /* NamedImports */:
                                case 229 /* NamedExports */:
                                    return contextToken.parent;
                            }
                    }
                }
                return undefined;
            }
            function tryGetContainingJsxElement(contextToken) {
                if (contextToken) {
                    var parent_11 = contextToken.parent;
                    switch (contextToken.kind) {
                        case 26 /* LessThanSlashToken */:
                        case 39 /* SlashToken */:
                        case 69 /* Identifier */:
                        case 238 /* JsxAttribute */:
                        case 239 /* JsxSpreadAttribute */:
                            if (parent_11 && (parent_11.kind === 234 /* JsxSelfClosingElement */ || parent_11.kind === 235 /* JsxOpeningElement */)) {
                                return parent_11;
                            }
                            else if (parent_11.kind === 238 /* JsxAttribute */) {
                                return parent_11.parent;
                            }
                            break;
                        // The context token is the closing } or " of an attribute, which means
                        // its parent is a JsxExpression, whose parent is a JsxAttribute,
                        // whose parent is a JsxOpeningLikeElement
                        case 9 /* StringLiteral */:
                            if (parent_11 && ((parent_11.kind === 238 /* JsxAttribute */) || (parent_11.kind === 239 /* JsxSpreadAttribute */))) {
                                return parent_11.parent;
                            }
                            break;
                        case 16 /* CloseBraceToken */:
                            if (parent_11 &&
                                parent_11.kind === 240 /* JsxExpression */ &&
                                parent_11.parent &&
                                (parent_11.parent.kind === 238 /* JsxAttribute */)) {
                                return parent_11.parent.parent;
                            }
                            if (parent_11 && parent_11.kind === 239 /* JsxSpreadAttribute */) {
                                return parent_11.parent;
                            }
                            break;
                    }
                }
                return undefined;
            }
            function isFunction(kind) {
                switch (kind) {
                    case 173 /* FunctionExpression */:
                    case 174 /* ArrowFunction */:
                    case 213 /* FunctionDeclaration */:
                    case 143 /* MethodDeclaration */:
                    case 142 /* MethodSignature */:
                    case 145 /* GetAccessor */:
                    case 146 /* SetAccessor */:
                    case 147 /* CallSignature */:
                    case 148 /* ConstructSignature */:
                    case 149 /* IndexSignature */:
                        return true;
                }
                return false;
            }
            /**
             * @returns true if we are certain that the currently edited location must define a new location; false otherwise.
             */
            function isSolelyIdentifierDefinitionLocation(contextToken) {
                var containingNodeKind = contextToken.parent.kind;
                switch (contextToken.kind) {
                    case 24 /* CommaToken */:
                        return containingNodeKind === 211 /* VariableDeclaration */ ||
                            containingNodeKind === 212 /* VariableDeclarationList */ ||
                            containingNodeKind === 193 /* VariableStatement */ ||
                            containingNodeKind === 217 /* EnumDeclaration */ ||
                            isFunction(containingNodeKind) ||
                            containingNodeKind === 214 /* ClassDeclaration */ ||
                            containingNodeKind === 186 /* ClassExpression */ ||
                            containingNodeKind === 215 /* InterfaceDeclaration */ ||
                            containingNodeKind === 162 /* ArrayBindingPattern */ ||
                            containingNodeKind === 216 /* TypeAliasDeclaration */; // type Map, K, |
                    case 21 /* DotToken */:
                        return containingNodeKind === 162 /* ArrayBindingPattern */; // var [.|
                    case 54 /* ColonToken */:
                        return containingNodeKind === 163 /* BindingElement */; // var {x :html|
                    case 19 /* OpenBracketToken */:
                        return containingNodeKind === 162 /* ArrayBindingPattern */; // var [x|
                    case 17 /* OpenParenToken */:
                        return containingNodeKind === 244 /* CatchClause */ ||
                            isFunction(containingNodeKind);
                    case 15 /* OpenBraceToken */:
                        return containingNodeKind === 217 /* EnumDeclaration */ ||
                            containingNodeKind === 215 /* InterfaceDeclaration */ ||
                            containingNodeKind === 155 /* TypeLiteral */; // let x : { |
                    case 23 /* SemicolonToken */:
                        return containingNodeKind === 140 /* PropertySignature */ &&
                            contextToken.parent && contextToken.parent.parent &&
                            (contextToken.parent.parent.kind === 215 /* InterfaceDeclaration */ ||
                                contextToken.parent.parent.kind === 155 /* TypeLiteral */); // let x : { a; |
                    case 25 /* LessThanToken */:
                        return containingNodeKind === 214 /* ClassDeclaration */ ||
                            containingNodeKind === 186 /* ClassExpression */ ||
                            containingNodeKind === 215 /* InterfaceDeclaration */ ||
                            containingNodeKind === 216 /* TypeAliasDeclaration */ ||
                            isFunction(containingNodeKind);
                    case 113 /* StaticKeyword */:
                        return containingNodeKind === 141 /* PropertyDeclaration */;
                    case 22 /* DotDotDotToken */:
                        return containingNodeKind === 138 /* Parameter */ ||
                            (contextToken.parent && contextToken.parent.parent &&
                                contextToken.parent.parent.kind === 162 /* ArrayBindingPattern */); // var [...z|
                    case 112 /* PublicKeyword */:
                    case 110 /* PrivateKeyword */:
                    case 111 /* ProtectedKeyword */:
                        return containingNodeKind === 138 /* Parameter */;
                    case 116 /* AsKeyword */:
                        return containingNodeKind === 226 /* ImportSpecifier */ ||
                            containingNodeKind === 230 /* ExportSpecifier */ ||
                            containingNodeKind === 224 /* NamespaceImport */;
                    case 73 /* ClassKeyword */:
                    case 81 /* EnumKeyword */:
                    case 107 /* InterfaceKeyword */:
                    case 87 /* FunctionKeyword */:
                    case 102 /* VarKeyword */:
                    case 123 /* GetKeyword */:
                    case 129 /* SetKeyword */:
                    case 89 /* ImportKeyword */:
                    case 108 /* LetKeyword */:
                    case 74 /* ConstKeyword */:
                    case 114 /* YieldKeyword */:
                    case 132 /* TypeKeyword */:
                        return true;
                }
                // Previous token may have been a keyword that was converted to an identifier.
                switch (contextToken.getText()) {
                    case "abstract":
                    case "async":
                    case "class":
                    case "const":
                    case "declare":
                    case "enum":
                    case "function":
                    case "interface":
                    case "let":
                    case "private":
                    case "protected":
                    case "public":
                    case "static":
                    case "var":
                    case "yield":
                        return true;
                }
                return false;
            }
            function isDotOfNumericLiteral(contextToken) {
                if (contextToken.kind === 8 /* NumericLiteral */) {
                    var text = contextToken.getFullText();
                    return text.charAt(text.length - 1) === ".";
                }
                return false;
            }
            /**
             * Filters out completion suggestions for named imports or exports.
             *
             * @param exportsOfModule          The list of symbols which a module exposes.
             * @param namedImportsOrExports    The list of existing import/export specifiers in the import/export clause.
             *
             * @returns Symbols to be suggested at an import/export clause, barring those whose named imports/exports
             *          do not occur at the current position and have not otherwise been typed.
             */
            function filterNamedImportOrExportCompletionItems(exportsOfModule, namedImportsOrExports) {
                var exisingImportsOrExports = {};
                for (var _i = 0, namedImportsOrExports_1 = namedImportsOrExports; _i < namedImportsOrExports_1.length; _i++) {
                    var element = namedImportsOrExports_1[_i];
                    // If this is the current item we are editing right now, do not filter it out
                    if (element.getStart() <= position && position <= element.getEnd()) {
                        continue;
                    }
                    var name_35 = element.propertyName || element.name;
                    exisingImportsOrExports[name_35.text] = true;
                }
                if (ts.isEmpty(exisingImportsOrExports)) {
                    return exportsOfModule;
                }
                return ts.filter(exportsOfModule, function (e) { return !ts.lookUp(exisingImportsOrExports, e.name); });
            }
            /**
             * Filters out completion suggestions for named imports or exports.
             *
             * @returns Symbols to be suggested in an object binding pattern or object literal expression, barring those whose declarations
             *          do not occur at the current position and have not otherwise been typed.
             */
            function filterObjectMembersList(contextualMemberSymbols, existingMembers) {
                if (!existingMembers || existingMembers.length === 0) {
                    return contextualMemberSymbols;
                }
                var existingMemberNames = {};
                for (var _i = 0, existingMembers_1 = existingMembers; _i < existingMembers_1.length; _i++) {
                    var m = existingMembers_1[_i];
                    // Ignore omitted expressions for missing members
                    if (m.kind !== 245 /* PropertyAssignment */ &&
                        m.kind !== 246 /* ShorthandPropertyAssignment */ &&
                        m.kind !== 163 /* BindingElement */) {
                        continue;
                    }
                    // If this is the current item we are editing right now, do not filter it out
                    if (m.getStart() <= position && position <= m.getEnd()) {
                        continue;
                    }
                    var existingName = void 0;
                    if (m.kind === 163 /* BindingElement */ && m.propertyName) {
                        // include only identifiers in completion list
                        if (m.propertyName.kind === 69 /* Identifier */) {
                            existingName = m.propertyName.text;
                        }
                    }
                    else {
                        // TODO(jfreeman): Account for computed property name
                        // NOTE: if one only performs this step when m.name is an identifier,
                        // things like '__proto__' are not filtered out.
                        existingName = m.name.text;
                    }
                    existingMemberNames[existingName] = true;
                }
                return ts.filter(contextualMemberSymbols, function (m) { return !ts.lookUp(existingMemberNames, m.name); });
            }
            /**
             * Filters out completion suggestions from 'symbols' according to existing JSX attributes.
             *
             * @returns Symbols to be suggested in a JSX element, barring those whose attributes
             *          do not occur at the current position and have not otherwise been typed.
             */
            function filterJsxAttributes(symbols, attributes) {
                var seenNames = {};
                for (var _i = 0, attributes_1 = attributes; _i < attributes_1.length; _i++) {
                    var attr = attributes_1[_i];
                    // If this is the current item we are editing right now, do not filter it out
                    if (attr.getStart() <= position && position <= attr.getEnd()) {
                        continue;
                    }
                    if (attr.kind === 238 /* JsxAttribute */) {
                        seenNames[attr.name.text] = true;
                    }
                }
                return ts.filter(symbols, function (a) { return !ts.lookUp(seenNames, a.name); });
            }
        }
Get a displayName from a given for completion list, performing any necessary quotes stripping
and checking whether the name is valid identifier name.