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

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

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

    public static FAILURE_STRING: string = 'Forbidden call to document.cookie';

    public applyWithProgram(sourceFile: ts.SourceFile, program: ts.Program): Lint.RuleFailure[] {
        return this.applyWithWalker(new NoCookiesWalker(sourceFile, this.getOptions(), program));
    }
}

class NoCookiesWalker extends Lint.RuleWalker {
    private readonly typeChecker: ts.TypeChecker;

    constructor(sourceFile: ts.SourceFile, options: Lint.IOptions, program: ts.Program) {
        super(sourceFile, options);
        this.typeChecker = program.getTypeChecker();
    }

    protected visitPropertyAccessExpression(node: ts.PropertyAccessExpression): void {
        const propertyName = node.name.text;
        if (propertyName === 'cookie') {
            const leftSide: ts.Expression = node.expression;
            try {
                const leftSideType: ts.Type = this.typeChecker.getTypeAtLocation(leftSide);
                const typeAsString: string = this.typeChecker.typeToString(leftSideType);
                if (leftSideType.flags === ts.TypeFlags.Any || typeAsString === 'Document') {
                    this.addFailureAt(leftSide.getStart(), leftSide.getWidth(), Rule.FAILURE_STRING);
                }
            } catch (e) {
                // the error thrown seems like a tslint error
                if (leftSide.getFullText().trim() === 'document') {
                    this.addFailureAt(leftSide.getStart(), leftSide.getWidth(), Rule.FAILURE_STRING);
                }
            }
        }

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

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

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

    public static FAILURE_STRING: string = 'Forbidden call to document.cookie';

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

function walk(ctx: Lint.WalkContext<void>, program: ts.Program) {
    const typeChecker: ts.TypeChecker = program.getTypeChecker();

    function cb(node: ts.Node): void {
        if (tsutils.isPropertyAccessExpression(node)) {
            const propertyName = node.name.text;
            if (propertyName === 'cookie') {
                const leftSide: ts.Expression = node.expression;
                try {
                    const leftSideType: ts.Type = typeChecker.getTypeAtLocation(leftSide);
                    const typeAsString: string = typeChecker.typeToString(leftSideType);
                    if (leftSideType.flags === ts.TypeFlags.Any || typeAsString === 'Document') {
                        ctx.addFailureAt(leftSide.getStart(), leftSide.getWidth(), Rule.FAILURE_STRING);
                    }
                } catch (e) {
                    // the error thrown seems like a tslint error
                    if (leftSide.getFullText().trim() === 'document') {
                        ctx.addFailureAt(leftSide.getStart(), leftSide.getWidth(), Rule.FAILURE_STRING);
                    }
                }
            }
        }

        return ts.forEachChild(node, cb);
    }

    return ts.forEachChild(ctx.sourceFile, cb);
}

{'fraction_non_alphanumeric': 0.11118435508679411, 'fraction_numerical': 0.005932762030323006, 'mean_word_length': 2.4251316779533485, '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': '7279912', 'n_tokens_mistral': 1271, 'n_tokens_neox': 1211, 'n_words': 287}