• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

rokucommunity / bslint / #1041

03 Oct 2024 07:42PM UTC coverage: 91.278% (-0.5%) from 91.746%
#1041

Pull #96

TwitchBronBron
1.0.0-alpha.39
Pull Request #96: v1

927 of 1061 branches covered (87.37%)

Branch coverage included in aggregate %.

231 of 240 new or added lines in 12 files covered. (96.25%)

11 existing lines in 3 files now uncovered.

1009 of 1060 relevant lines covered (95.19%)

68.85 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

91.49
/src/util.ts
1
import { parse } from 'jsonc-parser';
1✔
2
import * as minimatch from 'minimatch';
1✔
3
import { BsLintConfig, BsLintRules, RuleSeverity, BsLintSeverity } from './index';
4
import { readFileSync, existsSync } from 'fs';
1✔
5
import * as path from 'path';
1✔
6
import { Program, BscFile, DiagnosticSeverity } from 'brighterscript';
1✔
7
import { applyFixes, ChangeEntry, TextEdit } from './textEdit';
1✔
8
import { addJob } from './Linter';
1✔
9

10
export function getDefaultRules(): BsLintConfig['rules'] {
1✔
11
    return {
181✔
12
        'assign-all-paths': 'error',
13
        'unsafe-path-loop': 'error',
14
        'unsafe-iterators': 'error',
15
        'unreachable-code': 'info',
16
        'case-sensitivity': 'warn',
17
        'unused-variable': 'warn',
18
        // 'no-stop': 'off',
19
        'consistent-return': 'error',
20
        // 'only-function': 'off',
21
        // 'only-sub': 'off',
22
        'inline-if-style': 'then',
23
        'block-if-style': 'no-then',
24
        'condition-style': 'no-group',
25
        'named-function-style': 'auto',
26
        'anon-function-style': 'auto',
27
        'aa-comma-style': 'no-dangling',
28
        'type-annotations': 'off',
29
        'no-print': 'off',
30
        'no-assocarray-component-field-type': 'off',
31
        'no-array-component-field-type': 'off',
32
        'name-shadowing': 'off'
33
    };
34
}
35

36
export function getDefaultSeverity() {
1✔
UNCOV
37
    return rulesToSeverity(getDefaultRules());
×
38
}
39

40
export function normalizeConfig(options: BsLintConfig) {
1✔
41
    const baseConfig = {
180✔
42
        rules: getDefaultRules()
43
    };
44
    const projectConfig = mergeConfigs(loadConfig(options), { rules: options.rules });
180✔
45
    return mergeConfigs(baseConfig, projectConfig);
180✔
46
}
47

48
export function mergeConfigs(a: BsLintConfig, b: BsLintConfig): BsLintConfig {
1✔
49
    return {
361✔
50
        ...a,
51
        ...b,
52
        rules: {
53
            ...(a.rules || {}),
388✔
54
            ...(b.rules || {})
392✔
55
        }
56
    };
57
}
58

59
function loadConfig(options: BsLintConfig) {
60
    if (options.lintConfig) {
180✔
61
        const bsconfig = tryLoadConfig(options.lintConfig);
2✔
62
        if (bsconfig) {
2!
63
            return { ...options, ...bsconfig };
2✔
64
        } else {
UNCOV
65
            throw new Error(`Configuration file '${options.lintConfig}' not found`);
×
66
        }
67
    }
68
    if (options.project) {
178✔
69
        const bsconfig = tryLoadConfig(path.join(path.dirname(options.project), 'bslint.json'));
1✔
70
        if (bsconfig) {
1!
71
            return { ...options, ...bsconfig };
1✔
72
        }
73
    }
74
    if (options.rootDir) {
177✔
75
        const bsconfig = tryLoadConfig(path.join(options.rootDir, 'bslint.json'));
175✔
76
        if (bsconfig) {
175✔
77
            return { ...options, ...bsconfig };
71✔
78
        }
79
    }
80
    const bsconfig = tryLoadConfig('./bslint.json');
106✔
81
    if (bsconfig) {
106!
UNCOV
82
        return { ...options, ...bsconfig };
×
83
    }
84
    return options;
106✔
85
}
86

87
function tryLoadConfig(filename: string): BsLintConfig | undefined {
88
    if (!existsSync(filename)) {
284✔
89
        return undefined;
210✔
90
    }
91

92
    const bserrors = [];
74✔
93
    const bsconfig = parse(readFileSync(filename).toString(), bserrors);
74✔
94
    if (bserrors.length) {
74!
UNCOV
95
        throw new Error(`Invalid bslint configuration file '${filename}': ${bserrors}`);
×
96
    }
97
    return bsconfig;
74✔
98
}
99

100
export interface PluginContext {
101
    program: Readonly<Program>;
102
    severity: Readonly<BsLintRules>;
103
    todoPattern: Readonly<RegExp>;
104
    globals: string[];
105
    ignores: (file: BscFile) => boolean;
106
    fix: Readonly<boolean>;
107
    checkUsage: Readonly<boolean>;
108
    addFixes: (file: BscFile, entry: ChangeEntry) => void;
109
}
110

111
export interface PluginWrapperContext extends PluginContext {
112
    pendingFixes: Map<string, TextEdit[]>;
113
    applyFixes: () => Promise<void>;
114
}
115

116
export function createContext(program: Program): PluginWrapperContext {
1✔
117
    const { rules, fix, checkUsage, globals, ignores } = normalizeConfig(program.options);
174✔
118
    const ignorePatterns = (ignores || []).map(pattern => {
174✔
119
        return pattern.startsWith('**/') ? pattern : '**/' + pattern;
3✔
120
    });
121
    const pendingFixes = new Map<string, TextEdit[]>();
174✔
122
    return {
174✔
123
        program: program,
124
        severity: rulesToSeverity(rules),
125
        todoPattern: rules['todo-pattern'] ? new RegExp(rules['todo-pattern']) : /TODO|todo|FIXME/,
174✔
126
        globals,
127
        ignores: (file: BscFile) => {
128
            return !file || ignorePatterns.some(pattern => minimatch(file.srcPath, pattern));
178✔
129
        },
130
        fix,
131
        checkUsage,
132
        addFixes: (file: BscFile, entry: ChangeEntry) => {
133
            if (!pendingFixes.has(file.srcPath)) {
47✔
134
                pendingFixes.set(file.srcPath, entry.changes);
13✔
135
            } else {
136
                pendingFixes.get(file.srcPath).push(...entry.changes);
34✔
137
            }
138
        },
139
        applyFixes: () => addJob(applyFixes(fix, pendingFixes)),
31✔
140
        pendingFixes
141
    };
142
}
143

144
function rulesToSeverity(rules: BsLintConfig['rules']) {
145
    return {
174✔
146
        assignAllPath: ruleToSeverity(rules['assign-all-paths']),
147
        unreachableCode: ruleToSeverity(rules['unreachable-code']),
148
        unsafePathLoop: ruleToSeverity(rules['unsafe-path-loop']),
149
        unsafeIterators: ruleToSeverity(rules['unsafe-iterators']),
150
        caseSensitivity: ruleToSeverity(rules['case-sensitivity']),
151
        unusedVariable: ruleToSeverity(rules['unused-variable']),
152
        consistentReturn: ruleToSeverity(rules['consistent-return']),
153
        inlineIfStyle: rules['inline-if-style'],
154
        blockIfStyle: rules['block-if-style'],
155
        conditionStyle: rules['condition-style'],
156
        namedFunctionStyle: rules['named-function-style'],
157
        anonFunctionStyle: rules['anon-function-style'],
158
        aaCommaStyle: rules['aa-comma-style'],
159
        typeAnnotations: rules['type-annotations'],
160
        noPrint: ruleToSeverity(rules['no-print']),
161
        noTodo: ruleToSeverity(rules['no-todo']),
162
        noStop: ruleToSeverity(rules['no-stop']),
163
        eolLast: rules['eol-last'],
164
        colorFormat: rules['color-format'],
165
        colorCase: rules['color-case'],
166
        colorAlpha: rules['color-alpha'],
167
        colorAlphaDefaults: rules['color-alpha-defaults'],
168
        colorCertCompliant: rules['color-cert'],
169
        noAssocarrayComponentFieldType: ruleToSeverity(rules['no-assocarray-component-field-type']),
170
        noArrayComponentFieldType: ruleToSeverity(rules['no-array-component-field-type']),
171
        nameShadowing: ruleToSeverity(rules['name-shadowing'])
172
    };
173
}
174

175
function ruleToSeverity(rule: RuleSeverity): BsLintSeverity {
176
    switch (rule) {
2,262✔
177
        case 'error':
178
            return DiagnosticSeverity.Error;
398✔
179
        case 'warn':
180
            return DiagnosticSeverity.Warning;
170✔
181
        case 'info':
182
            return DiagnosticSeverity.Information;
97✔
183
        default:
184
            return DiagnosticSeverity.Hint;
1,597✔
185
    }
186
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc