<commit_before>let fs = require('fs');

let start = Date.now();
const propRegExp = new RegExp('@Prop\\(([\\s\\S]*?)\\)\\s*public\\s*(\\w*):\\s*(\\w*);', 'g');
const mixinsRegExp = new RegExp('mixins:\\s*\\[([\\s\\S]*?)\\]', 'g');
const mixinNameRegExp = new RegExp('[\\w\\d]+', 'g');

readFolders('./src/components', (folder, done) => {
    let errors = [];
    read(`./src/components/${folder}/${folder}.ts`, source => {
        read(`./src/components/${folder}/${folder}.meta.json`, rawMeta => {
            let meta = JSON.parse(rawMeta);

            validateMeta(meta, source, errors);
            validateMixins(meta, source, errors);

            done(errors);
        }, err => {
            errors.push(err.message);
            done(errors);
        })
    }, err => {
        errors.push(err.message);
        done(errors);
    });
});

function validateMeta(meta, source, errors) {
    let prop = undefined;
    do {
        prop = propRegExp.exec(source);
        if (prop) {
            if (meta.attributes && meta.attributes[prop[2]] !== undefined) {
                delete meta.attributes[prop[2]];
            } else {
                errors.push(`Property ${prop[2]} not found in meta`);<commit_msg>Add typing and default value validations<commit_after>let fs = require('fs');

let start = Date.now();
const propRegExp = new RegExp(`@Prop\\(([\\s\\S]*?)\\)\\s*(?:@Model\\(\\'?[\\w\\d]+\\'?\\)\\s*)?public\\s*(\\w*):\\s*(\\w\\s|.*);`, 'g');
const mixinsRegExp = new RegExp('mixins:\\s*\\[([\\s\\S]*?)\\]', 'g');
const mixinNameRegExp = new RegExp('[\\w\\d]+', 'g');
const defaultValueRegExp = new RegExp('default:\\s*(.*?)[\\s,}]');

readFolders('./src/components', (folder, done) => {
    let errors = [];
    read(`./src/components/${folder}/${folder}.ts`, source => {
        read(`./src/components/${folder}/${folder}.meta.json`, rawMeta => {
            let meta = JSON.parse(rawMeta);

            validateProps(meta, source, errors);
            validateMixins(meta, source, errors);

            done(errors);
        }, err => {
            errors.push(err.message);
            done(errors);
        })
    }, err => {
        errors.push(err.message);
        done(errors);
    });
});

function validateProps(meta, source, errors) {
    let prop = undefined;
    do {
        prop = propRegExp.exec(source);
        if (prop) {
            if (meta.attributes && meta.attributes[prop[2]] !== undefined) {
                let attributeMeta = meta.attributes[prop[2]];
                if (attributeMeta.type !== prop[3]) {
                    errors.push(`Property ${prop[2]} should be of type ${prop[3]}, not ${attributeMeta.type}`);
                }
                if (prop[1]) {
                    let defaultValueMatch = defaultValueRegExp.exec(prop[1]);
                    let defaultValue = defaultValueMatch ? defaultValueMatch[1] : undefined;
                    if (defaultValue && defaultValue[0] === '\'' && defaultValue[defaultValue.length - 1] === '\'') {
                        defaultValue = defaultValue.slice(1, -1);
                    }
                    if (defaultValue !== 'function()' && String(attributeMeta.default) !== String(defaultValue)) {
                        errors.push(`Property ${prop[2]} default value should be ${defaultValue}, not ${attributeMeta.default}`);
                    }
                }
                delete meta.attributes[prop[2]];
            } else {
                errors.push(`Property ${prop[2]} not found in meta`);
{'fraction_non_alphanumeric': 0.20301822323462415, 'fraction_numerical': 0.005125284738041002, 'mean_word_length': 2.0897097625329817, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 13, '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': '1260061', 'n_tokens_mistral': 1053, 'n_tokens_neox': 1033, 'n_words': 197}