Repository: eslint/eslint
File: lib/rules/utils/ast-utils.js (JavaScript)

Code before:
        return false;
    }
    const parent = node.parent;

    return parent.type === "Program" || (parent.type === "BlockStatement" && isFunction(parent.parent));

}

/**
 * Check whether the given node is a string literal not surrounded by parentheses.
 * @param {ASTNode} node The node to check.
 * @param {SourceCode} sourceCode The source code object to get tokens.
 * @returns {boolean} `true` if the node is a string literal not surrounded by parentheses.
 */
function isUnparenthesizedStringLiteral(node, sourceCode) {
    return node.type === "Literal" && typeof node.value === "string" && !isParenthesised(sourceCode, node);
}

/**
 * Check whether the given node is a part of a directive prologue or not.
 * @param {ASTNode} node The node to check.
 * @param {SourceCode} sourceCode The source code object to get tokens.
 * @returns {boolean} `true` if the node is a part of directive prologue.
 */
function isDirective(node, sourceCode) {
    if (node.type === "ExpressionStatement" && "directive" in node) {
        return true;
    }

    // Fallback for parsers that don't set a `directive` property.
    if (isTopLevelExpressionStatement(node) && isUnparenthesizedStringLiteral(node.expression, sourceCode)) {
        for (const sibling of node.parent.body) {
            if (sibling === node) {
                break;
            }
            if (sibling.type !== "ExpressionStatement" || !isUnparenthesizedStringLiteral(sibling.expression, sourceCode)) {
                return false;
            }
        }
        return true;
    }
    return false;
}

//------------------------------------------------------------------------------
// Public Interface
//------------------------------------------------------------------------------

module.exports = {
    COMMENTS_IGNORE_PATTERN,
    LINEBREAKS,

Review comment (suggestion):
```suggestion
    if (node.type === "ExpressionStatement" && typeof node.directive === "string") {
```

It might be better to check this way. There's at least one parser based on ESTree that generates `directive: null` on non-directive expression statements, flow-parser:

https://astexplorer.net/#/gist/d47d64e44da5ff23bb7881df3b77859b/328a3a0d86f4a985da36a0f1d95e16a8a4fc8744

Code after:
        return false;
    }
    const parent = node.parent;

    return parent.type === "Program" || (parent.type === "BlockStatement" && isFunction(parent.parent));

}

/**
 * Check whether the given node is a part of a directive prologue or not.
 * @param {ASTNode} node The node to check.
 * @returns {boolean} `true` if the node is a part of directive prologue.
 */
function isDirective(node) {
    return node.type === "ExpressionStatement" && typeof node.directive === "string";
}

//------------------------------------------------------------------------------
// Public Interface
//------------------------------------------------------------------------------

module.exports = {
    COMMENTS_IGNORE_PATTERN,
    LINEBREAKS,
    LINEBREAK_MATCHER: lineBreakPattern,
    SHEBANG_MATCHER: shebangPattern,
    STATEMENT_LIST_PARENTS,

    /**
     * Determines whether two adjacent tokens are on the same line.
     * @param {Object} left The left token object.
     * @param {Object} right The right token object.
     * @returns {boolean} Whether or not the tokens are on the same line.
     * @public
     */
    isTokenOnSameLine(left, right) {
        return left.loc.end.line === right.loc.start.line;
    },

    isNullOrUndefined,
    isCallee,
    isES5Constructor,
    getUpperFunction,
    isFunction,
    isLoop,
    isInLoop,
    isArrayFromMethod,
    isParenthesised,
    createGlobalLinebreakMatcher,
    equalTokens,