Repository: microsoft/TypeScript
File: src/services/stringCompletions.ts (TypeScript)

Code before:
            }
            return fromContextualType() || fromContextualType(ContextFlags.None);

        case SyntaxKind.ElementAccessExpression: {
            const { expression, argumentExpression } = parent as ElementAccessExpression;
            if (node === skipParentheses(argumentExpression)) {
                // Get all names of properties on the expression
                // i.e. interface A {
                //      'prop1': string
                // }
                // let a: A;
                // a['/*completion position*/']
                return stringLiteralCompletionsFromProperties(typeChecker.getTypeAtLocation(expression));
            }
            return undefined;
        }

        case SyntaxKind.CallExpression:
        case SyntaxKind.NewExpression:
        case SyntaxKind.JsxAttribute:
            if (!isRequireCallArgument(node) && !isImportCall(parent)) {
                const argumentInfo = SignatureHelp.getArgumentInfoForCompletions(parent.kind === SyntaxKind.JsxAttribute ? parent.parent : node, position, sourceFile);
                // Get string literal completions from specialized signatures of the target
                // i.e. declare function f(a: 'A');
                // f("/*completion position*/")
                return argumentInfo && getStringLiteralCompletionsFromSignature(argumentInfo.invocation, node, argumentInfo, typeChecker) || fromContextualType();
            }
            // falls through (is `require("")` or `require(""` or `import("")`)

        case SyntaxKind.ImportDeclaration:
        case SyntaxKind.ExportDeclaration:
        case SyntaxKind.ExternalModuleReference:
            // Get all known external module names or complete a path to a module
            // i.e. import * as ns from "/*completion position*/";
            //      var y = import("/*completion position*/");
            //      import x = require("/*completion position*/");
            //      var y = require("/*completion position*/");
            //      export * from "/*completion position*/";
            return { kind: StringLiteralCompletionKind.Paths, paths: getStringLiteralCompletionsFromModuleNames(sourceFile, node, compilerOptions, host, typeChecker, preferences) };
        case SyntaxKind.CaseClause:
            const tracker = newCaseClauseTracker(typeChecker, (parent as CaseClause).parent.clauses);
            const contextualTypes = fromContextualType();
            if (!contextualTypes) {
                return;
            }
            const literals = contextualTypes.types.filter(literal => !tracker.hasValue(literal.value));
            return { kind: StringLiteralCompletionKind.Types, types: literals, isNewIdentifier: false };
        default:
            return fromContextualType() || fromContextualType(ContextFlags.None);
    }


Review comment (suggestion):
`getStringLiteralCompletionsFromSignature` is already using the "inference blocking strategy" so it doesn't make sense (at least usually) for the fallback request~ to use it as well

Code after:
            }
            return fromContextualType() || fromContextualType(ContextFlags.None);

        case SyntaxKind.ElementAccessExpression: {
            const { expression, argumentExpression } = parent as ElementAccessExpression;
            if (node === skipParentheses(argumentExpression)) {
                // Get all names of properties on the expression
                // i.e. interface A {
                //      'prop1': string
                // }
                // let a: A;
                // a['/*completion position*/']
                return stringLiteralCompletionsFromProperties(typeChecker.getTypeAtLocation(expression));
            }
            return undefined;
        }

        case SyntaxKind.CallExpression:
        case SyntaxKind.NewExpression:
        case SyntaxKind.JsxAttribute:
            if (!isRequireCallArgument(node) && !isImportCall(parent)) {
                const argumentInfo = SignatureHelp.getArgumentInfoForCompletions(parent.kind === SyntaxKind.JsxAttribute ? parent.parent : node, position, sourceFile);
                // Get string literal completions from specialized signatures of the target
                // i.e. declare function f(a: 'A');
                // f("/*completion position*/")
                return argumentInfo && getStringLiteralCompletionsFromSignature(argumentInfo.invocation, node, argumentInfo, typeChecker) || fromContextualType(ContextFlags.None);
            }
            // falls through (is `require("")` or `require(""` or `import("")`)

        case SyntaxKind.ImportDeclaration:
        case SyntaxKind.ExportDeclaration:
        case SyntaxKind.ExternalModuleReference:
            // Get all known external module names or complete a path to a module
            // i.e. import * as ns from "/*completion position*/";
            //      var y = import("/*completion position*/");
            //      import x = require("/*completion position*/");
            //      var y = require("/*completion position*/");
            //      export * from "/*completion position*/";
            return { kind: StringLiteralCompletionKind.Paths, paths: getStringLiteralCompletionsFromModuleNames(sourceFile, node, compilerOptions, host, typeChecker, preferences) };
        case SyntaxKind.CaseClause:
            const tracker = newCaseClauseTracker(typeChecker, (parent as CaseClause).parent.clauses);
            const contextualTypes = fromContextualType();
            if (!contextualTypes) {
                return;
            }
            const literals = contextualTypes.types.filter(literal => !tracker.hasValue(literal.value));
            return { kind: StringLiteralCompletionKind.Types, types: literals, isNewIdentifier: false };
        default:
            return fromContextualType() || fromContextualType(ContextFlags.None);
    }