Repository: microsoft/TypeScript
File: src/compiler/utilities.ts (TypeScript)

Code before:
            return true;
        default:
            assertType<never>(node);
            return false;
    }
}

/** @internal */
export function isEqualityOperatorKind(kind: SyntaxKind): kind is EqualityOperator {
    switch (kind) {
        case SyntaxKind.EqualsEqualsEqualsToken:
        case SyntaxKind.EqualsEqualsToken:
        case SyntaxKind.ExclamationEqualsEqualsToken:
        case SyntaxKind.ExclamationEqualsToken:
            return true;
        default:
            return false;
    }
}

/** @internal */
export function getContextualTypeFromParent(node: Expression, checker: TypeChecker, contextFlags?: ContextFlags): Type | undefined {
    const parent = walkUpParenthesizedExpressions(node.parent);
    switch (parent.kind) {
        case SyntaxKind.NewExpression:
            return checker.getContextualType(parent as NewExpression, contextFlags);
        case SyntaxKind.BinaryExpression: {
            const { left, operatorToken, right } = parent as BinaryExpression;
            return isEqualityOperatorKind(operatorToken.kind)
                ? checker.getTypeAtLocation(node === right ? left : right)
                : checker.getContextualType(node, contextFlags);
        }
        case SyntaxKind.CaseClause:
            return checker.getTypeAtLocation((parent as CaseClause).parent.parent.expression);
        default:
            return checker.getContextualType(node, contextFlags);
    }
}


Review comment (refactor):
using the checker like this implies that this utility should be in services. Does it also rely on some compiler internals? I looked and I don't see it.

Code after:
                                originalLocation,
                                Diagnostics.Cannot_access_0_from_another_file_without_qualification_when_1_is_enabled_Use_2_instead,
                                unescapeLeadingUnderscores(name),
                                isolatedModulesLikeFlagName,
                                `${unescapeLeadingUnderscores(getSymbolOfDeclaration(location as EnumDeclaration).escapedName)}.${unescapeLeadingUnderscores(name)}`,
                            );
                        }
                        break loop;
                    }
                    break;
                case SyntaxKind.PropertyDeclaration:
                    // TypeScript 1.0 spec (April 2014): 8.4.1
                    // Initializer expressions for instance member variables are evaluated in the scope
                    // of the class constructor body but are not permitted to reference parameters or
                    // local variables of the constructor. This effectively means that entities from outer scopes
                    // by the same name as a constructor parameter or local variable are inaccessible
                    // in initializer expressions for instance member variables.
                    if (!isStatic(location)) {
                        const ctor = findConstructorDeclaration(location.parent as ClassLikeDeclaration);
                        if (ctor && ctor.locals) {
                            if (lookup(ctor.locals, name, meaning & SymbolFlags.Value)) {
                                // Remember the property node, it will be used later to report appropriate error
                                Debug.assertNode(location, isPropertyDeclaration);
                                propertyWithInvalidInitializer = location;
                            }
                        }
                    }
                    break;
                case SyntaxKind.ClassDeclaration:
                case SyntaxKind.ClassExpression:
                case SyntaxKind.InterfaceDeclaration:
                    // The below is used to lookup type parameters within a class or interface, as they are added to the class/interface locals
                    // These can never be latebound, so the symbol's raw members are sufficient. `getMembersOfNode` cannot be used, as it would
                    // trigger resolving late-bound names, which we may already be in the process of doing while we're here!
                    if (result = lookup(getSymbolOfDeclaration(location as ClassLikeDeclaration | InterfaceDeclaration).members || emptySymbols, name, meaning & SymbolFlags.Type)) {
                        if (!isTypeParameterSymbolDeclaredInContainer(result, location)) {
                            // ignore type parameters not declared in this container
                            result = undefined;
                            break;
                        }
                        if (lastLocation && isStatic(lastLocation)) {
                            // TypeScript 1.0 spec (April 2014): 3.4.1
                            // The scope of a type parameter extends over the entire declaration with which the type
                            // parameter list is associated, with the exception of static member declarations in classes.
                            if (nameNotFoundMessage) {
                                error(originalLocation, Diagnostics.Static_members_cannot_reference_class_type_parameters);
                            }
                            return undefined;
                        }
                        break loop;
                    }