首页 > 解决方案 > In the TypeScript compiler source, is `parsingContext` a blob or an instance of an enum?

问题描述

In the TypeScript compiler source, is parsingContext meant to be always equal to one of the values in the ParsingContext enum? Or is ParsingContext a set of flags and parsingContext is a blob to be manipulated through bitwise operators?

Support for parsingContext being equal to one of the values of the enum (0 -> 22):

Support for parsingContext being a blob intended to be manipulated with bitwise operators:

I'm asking here instead of on GitHub because the TypeScript Issues page says to ask questions here instead of on GH and because it's possible I'm just not understanding a common thing people do with bitwise operators.

标签: typescriptbitwise-operators

解决方案


In the TypeScript compiler source, is parsingContext meant to be always equal to one of the values in the ParsingContext enum? Or is ParsingContext a set of flags and parsingContext is a blob to be manipulated through bitwise operators?

There are different entities called parsingContext.

This one

    let parsingContext: ParsingContext;

holds arbitrary combination of bit flags (is a 'blob' as you say), is always manipulated via bitwise operators and is never compared directly with values of ParsingContext enum, although for some unclear reason it's declared to have ParsingContext type.

The other parsingContexts are declared as parameters to several functions, and are really meant to be just ParsingContext enum values. In fact, values for these parsingContexts always come from some function above in the call stack where they are called kind, not parsingContext. Here is one instance of kind in parseList becoming parseContext in parseListElement:

    // Parses a list of elements
    function parseList<T extends Node>(kind: ParsingContext, parseElement: () => T): NodeArray<T> {
        const saveParsingContext = parsingContext;
        parsingContext |= 1 << kind;
        const list = [];
        const listPos = getNodePos();

        while (!isListTerminator(kind)) {
            if (isListElement(kind, /*inErrorRecovery*/ false)) {
                const element = parseListElement(kind, parseElement);
                                                 ^^^^

    function parseListElement<T extends Node>(parsingContext: ParsingContext, parseElement: () => T): T {
        const node = currentNode(parsingContext);

All checks for parsingContext being equal to some value of ParsingContext enum are done in these functions where parsingContext does not refer to the parsingContext bit flags variable, but is coming as a parameter that was initially named kind and was given as a single value of ParsingContext enum.

Yes it's confusing, hope that my answer does not add to the confusion :)


推荐阅读