<commit_before>import * as ts from 'typescript';
import * as Lint from 'tslint';

import { AstUtils } from './utils/AstUtils';
import { ExtendedMetadata } from './utils/ExtendedMetadata';

export class Rule extends Lint.Rules.AbstractRule {
    public static metadata: ExtendedMetadata = {
        ruleName: 'no-document-write',
        type: 'maintainability',
        description: 'Do not use document.write',
        options: null, // tslint:disable-line:no-null-keyword
        optionsDescription: '',
        typescriptOnly: true,
        issueClass: 'SDL',
        issueType: 'Error',
        severity: 'Critical',
        level: 'Mandatory',
        group: 'Security',
        commonWeaknessEnumeration: '79, 85'
    };

    public static WRITE_FAILURE: string = 'Forbidden call to document.write';
    public static WRITELN_FAILURE: string = 'Forbidden call to document.writeln';

    public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] {
        return this.applyWithWalker(new NoDocumentWriteWalker(sourceFile, this.getOptions()));
    }
}

class NoDocumentWriteWalker extends Lint.RuleWalker {
    protected visitCallExpression(node: ts.CallExpression) {
        const functionTarget = AstUtils.getFunctionTarget(node);
        if (functionTarget === 'document' || functionTarget === 'window.document') {
            if (node.arguments.length === 1) {
                const functionName: string = AstUtils.getFunctionName(node);
                if (functionName === 'write') {
                    this.addFailureAt(node.getStart(), node.getWidth(), Rule.WRITE_FAILURE);
                } else if (functionName === 'writeln') {
                    this.addFailureAt(node.getStart(), node.getWidth(), Rule.WRITELN_FAILURE);
                }
            }
        }

        super.visitCallExpression(node);
    }
}<commit_msg>convert no-document-write rule to use a walk function (#746)<commit_after>import * as ts from 'typescript';
import * as Lint from 'tslint';
import * as tsutils from 'tsutils';

import { AstUtils } from './utils/AstUtils';
import { ExtendedMetadata } from './utils/ExtendedMetadata';

export class Rule extends Lint.Rules.AbstractRule {
    public static metadata: ExtendedMetadata = {
        ruleName: 'no-document-write',
        type: 'maintainability',
        description: 'Do not use document.write',
        options: null, // tslint:disable-line:no-null-keyword
        optionsDescription: '',
        typescriptOnly: true,
        issueClass: 'SDL',
        issueType: 'Error',
        severity: 'Critical',
        level: 'Mandatory',
        group: 'Security',
        commonWeaknessEnumeration: '79, 85'
    };

    public static WRITE_FAILURE: string = 'Forbidden call to document.write';
    public static WRITELN_FAILURE: string = 'Forbidden call to document.writeln';

    public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] {
        return this.applyWithFunction(sourceFile, walk);
    }
}

function walk(ctx: Lint.WalkContext<void>) {
    function cb(node: ts.Node): void {
        if (tsutils.isCallExpression(node)) {
            const functionTarget = AstUtils.getFunctionTarget(node);
            if (functionTarget === 'document' || functionTarget === 'window.document') {
                if (node.arguments.length === 1) {
                    const functionName: string = AstUtils.getFunctionName(node);
                    if (functionName === 'write') {
                        ctx.addFailureAt(node.getStart(), node.getWidth(), Rule.WRITE_FAILURE);
                    } else if (functionName === 'writeln') {
                        ctx.addFailureAt(node.getStart(), node.getWidth(), Rule.WRITELN_FAILURE);
                    }
                }
            }
        }

        return ts.forEachChild(node, cb);
    }

    return ts.forEachChild(ctx.sourceFile, cb);
}
{'fraction_non_alphanumeric': 0.11844155844155844, 'fraction_numerical': 0.0033766233766233766, 'mean_word_length': 2.585661080074488, 'pattern_counts': {'":': 0, '<': 4, '<?xml version=': 0, '>': 4, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '634291', 'n_tokens_mistral': 1079, 'n_tokens_neox': 1035, 'n_words': 249}