<commit_before>// tslint:disable-next-line:no-implicit-dependencies
import { FileEntry, SchematicContext, Tree, FileVisitor } from '@angular-devkit/schematics';

import * as fs from 'fs';
import * as path from 'path';
import { ClassChanges, BindingChanges, SelectorChange, SelectorChanges } from './schema';
import { getIdentifierPositions } from './tsUtils';
import { getProjectPaths, getWorkspace } from './util';

// tslint:disable:arrow-parens
export class UpdateChanges {
    protected sourcePaths: string[];
    protected classChanges: ClassChanges;
    protected outputChanges: BindingChanges;
    protected inputChanges: BindingChanges;
    protected selectorChanges: SelectorChanges;
    protected conditionFunctions: Map<string, Function>;

    private _templateFiles: string[] = [];
    public get templateFiles(): string[] {
        if (!this._templateFiles.length) {
            // https://github.com/angular/devkit/blob/master/packages/angular_devkit/schematics/src/tree/filesystem.ts
            this.sourceDirsVisitor((fulPath, entry) => {
                if (fulPath.endsWith('component.html')) {
                    this._templateFiles.push(entry.path);
                }
            });
        }
        return this._templateFiles;
    }

    private _tsFiles: string[] = [];
    public get tsFiles(): string[] {
        if (!this._tsFiles.length) {
            this.sourceDirsVisitor((fulPath, entry) => {
                if (fulPath.endsWith('.ts')) {
                    this._tsFiles.push(entry.path);
                }
            });
        }
        return this._tsFiles;
    }

    /**
     * Create a new base schematic to apply changes
     * @param rootPath Root folder for the schematic to read configs, pass __dirname
     */
    constructor(private rootPath: string, private host: Tree, private context?: SchematicContext) {
        this.sourcePaths = getProjectPaths(getWorkspace(host));

        const selectorJson = path.join(this.rootPath, 'changes', 'selectors.json');
        if (fs.existsSync(selectorJson)) {
            this.selectorChanges = JSON.parse(fs.readFileSync(selectorJson, 'utf-8'));
        }
        const classJson = path.join(this.rootPath, 'changes', 'classes.json');
        if (fs.existsSync(classJson)) {
            this.classChanges = JSON.parse(fs.readFileSync(classJson, 'utf-8'));
        }
        const outputsJson = path.join(this.rootPath, 'changes', 'outputs.json');
        if (fs.existsSync(outputsJson)) {
            this.outputChanges = JSON.parse(fs.readFileSync(outputsJson, 'utf-8'));
        }
        const inputsJson = path.join(this.rootPath, 'changes', 'inputs.json');
        if (fs.existsSync(inputsJson)) {
            this.inputChanges = JSON.parse(fs.readFileSync(inputsJson, 'utf-8'));
        }
    }

    /** Apply configured changes to the Host Tree */
    public applyChanges() {
        if (this.selectorChanges && this.selectorChanges.changes.length) {
            for (const entryPath of this.templateFiles) {
                this.updateSelectors(entryPath);
            }
        }
        if (this.outputChanges && this.outputChanges.changes.length) {
            for (const entryPath of this.templateFiles) {
                this.updateBindings(entryPath, this.outputChanges);
            }
        }

        if (this.inputChanges && this.inputChanges.changes.length) {
            for (const entryPath of this.templateFiles) {
                this.updateBindings(entryPath, this.inputChanges, BindingType.input);
            }
        }

        /** TS files */
        if (this.classChanges && this.classChanges.changes.length) {
            for (const entryPath of this.tsFiles) {
                this.updateClasses(entryPath);
            }
        }
    }

    /** Add condition funtion. */
    public addCondition(conditionName: string, callback: Function) {
        if (!this.conditionFunctions) {
            this.conditionFunctions = new Map<string, Function>();
        }

        this.conditionFunctions.set(conditionName, callback);
    }

    protected updateSelectors(entryPath: string) {
        let fileContent = this.host.read(entryPath).toString();
        let overwrite = false;
        for (const change of this.selectorChanges.changes) {
            let searchPttrn = change.type === 'component' ? '<' : '';
            searchPttrn += change.selector;
            if (fileContent.indexOf(searchPttrn) !== -1) {
                fileContent = this.applySelectorChange(fileContent, change);
                overwrite = true;
            }
        }<commit_msg>chore(migration): Small refactoring for review comments (#2613)<commit_after>// tslint:disable-next-line:no-implicit-dependencies
import { FileEntry, SchematicContext, Tree, FileVisitor } from '@angular-devkit/schematics';

import * as fs from 'fs';
import * as path from 'path';
import { ClassChanges, BindingChanges, SelectorChange, SelectorChanges } from './schema';
import { getIdentifierPositions } from './tsUtils';
import { getProjectPaths, getWorkspace } from './util';

// tslint:disable:arrow-parens
export class UpdateChanges {
    protected sourcePaths: string[];
    protected classChanges: ClassChanges;
    protected outputChanges: BindingChanges;
    protected inputChanges: BindingChanges;
    protected selectorChanges: SelectorChanges;
    protected conditionFunctions: Map<string, Function> = new Map<string, Function>();

    private _templateFiles: string[] = [];
    public get templateFiles(): string[] {
        if (!this._templateFiles.length) {
            // https://github.com/angular/devkit/blob/master/packages/angular_devkit/schematics/src/tree/filesystem.ts
            this.sourceDirsVisitor((fulPath, entry) => {
                if (fulPath.endsWith('component.html')) {
                    this._templateFiles.push(entry.path);
                }
            });
        }
        return this._templateFiles;
    }

    private _tsFiles: string[] = [];
    public get tsFiles(): string[] {
        if (!this._tsFiles.length) {
            this.sourceDirsVisitor((fulPath, entry) => {
                if (fulPath.endsWith('.ts')) {
                    this._tsFiles.push(entry.path);
                }
            });
        }
        return this._tsFiles;
    }

    /**
     * Create a new base schematic to apply changes
     * @param rootPath Root folder for the schematic to read configs, pass __dirname
     */
    constructor(private rootPath: string, private host: Tree, private context?: SchematicContext) {
        this.sourcePaths = getProjectPaths(getWorkspace(host));

        const selectorJson = path.join(this.rootPath, 'changes', 'selectors.json');
        if (fs.existsSync(selectorJson)) {
            this.selectorChanges = JSON.parse(fs.readFileSync(selectorJson, 'utf-8'));
        }
        const classJson = path.join(this.rootPath, 'changes', 'classes.json');
        if (fs.existsSync(classJson)) {
            this.classChanges = JSON.parse(fs.readFileSync(classJson, 'utf-8'));
        }
        const outputsJson = path.join(this.rootPath, 'changes', 'outputs.json');
        if (fs.existsSync(outputsJson)) {
            this.outputChanges = JSON.parse(fs.readFileSync(outputsJson, 'utf-8'));
        }
        const inputsJson = path.join(this.rootPath, 'changes', 'inputs.json');
        if (fs.existsSync(inputsJson)) {
            this.inputChanges = JSON.parse(fs.readFileSync(inputsJson, 'utf-8'));
        }
    }

    /** Apply configured changes to the Host Tree */
    public applyChanges() {
        if (this.selectorChanges && this.selectorChanges.changes.length) {
            for (const entryPath of this.templateFiles) {
                this.updateSelectors(entryPath);
            }
        }
        if (this.outputChanges && this.outputChanges.changes.length) {
            for (const entryPath of this.templateFiles) {
                this.updateBindings(entryPath, this.outputChanges);
            }
        }

        if (this.inputChanges && this.inputChanges.changes.length) {
            for (const entryPath of this.templateFiles) {
                this.updateBindings(entryPath, this.inputChanges, BindingType.input);
            }
        }

        /** TS files */
        if (this.classChanges && this.classChanges.changes.length) {
            for (const entryPath of this.tsFiles) {
                this.updateClasses(entryPath);
            }
        }
    }

    /** Add condition funtion. */
    public addCondition(conditionName: string, callback: (ownerMatch: string) => boolean) {
        this.conditionFunctions.set(conditionName, callback);
    }

    protected updateSelectors(entryPath: string) {
        let fileContent = this.host.read(entryPath).toString();
        let overwrite = false;
        for (const change of this.selectorChanges.changes) {
            let searchPttrn = change.type === 'component' ? '<' : '';
            searchPttrn += change.selector;
            if (fileContent.indexOf(searchPttrn) !== -1) {
                fileContent = this.applySelectorChange(fileContent, change);
                overwrite = true;
            }
        }
{'fraction_non_alphanumeric': 0.11861812616158303, 'fraction_numerical': 0.0015305564666010713, 'mean_word_length': 2.4058078927773643, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 12, 'https://': 2, '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': '6539285', 'n_tokens_mistral': 2471, 'n_tokens_neox': 2400, 'n_words': 517}