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

rokucommunity / bslint / #1354

25 Nov 2025 01:33AM UTC coverage: 91.556% (-0.4%) from 91.927%
#1354

push

GitHub
Merge 8eeb3f88a into 7eec9b785

879 of 997 branches covered (88.16%)

Branch coverage included in aggregate %.

986 of 1040 relevant lines covered (94.81%)

69.87 hits per line

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

89.13
/src/plugins/codeStyle/styleFixes.ts
1
import { BscFile, BsDiagnostic, FunctionExpression, GroupingExpression, IfStatement, isIfStatement, Position, Range, TokenKind, WhileStatement } from 'brighterscript';
1✔
2
import { ChangeEntry, comparePos, insertText, replaceText } from '../../textEdit';
1✔
3
import { CodeStyleError } from './diagnosticMessages';
1✔
4
import { platform } from 'process';
1✔
5

6
export function extractFixes(
1✔
7
    addFixes: (file: BscFile, changes: ChangeEntry) => void,
8
    diagnostics: BsDiagnostic[],
9
    fixAll?: boolean
10
): BsDiagnostic[] {
11
    return diagnostics.filter(diagnostic => {
12✔
12
        if (diagnostic.data?.isExperimental && !fixAll) {
41!
13
            return true;
×
14
        }
15
        const fix = getFixes(diagnostic);
41✔
16
        if (fix) {
41!
17
            addFixes(diagnostic.file, fix);
41✔
18
            return false;
41✔
19
        }
20
        return true;
×
21
    });
22
}
23

24
export function getFixes(diagnostic: BsDiagnostic): ChangeEntry {
1✔
25
    switch (diagnostic.code) {
41✔
26
        case CodeStyleError.FunctionKeywordExpected:
45!
27
            return replaceFunctionTokens(diagnostic, 'function');
3✔
28
        case CodeStyleError.SubKeywordExpected:
29
            return replaceFunctionTokens(diagnostic, 'sub');
3✔
30
        case CodeStyleError.InlineIfThenFound:
31
        case CodeStyleError.BlockIfThenFound:
32
            return removeThenToken(diagnostic);
4✔
33
        case CodeStyleError.InlineIfThenMissing:
34
        case CodeStyleError.BlockIfThenMissing:
35
            return addThenToken(diagnostic);
3✔
36
        case CodeStyleError.ConditionGroupFound:
37
            return removeConditionGroup(diagnostic);
5✔
38
        case CodeStyleError.ConditionGroupMissing:
39
            return addConditionGroup(diagnostic);
5✔
40
        case CodeStyleError.AACommaFound:
41
            return removeAAComma(diagnostic);
9✔
42
        case CodeStyleError.AACommaMissing:
43
            return addAAComma(diagnostic);
6✔
44
        case CodeStyleError.EolLastMissing:
45
            return addEolLast(diagnostic);
2✔
46
        case CodeStyleError.EolLastFound:
47
            return removeEolLast(diagnostic);
1✔
48
        default:
49
            return null;
×
50
    }
51
}
52

53
function addAAComma(diagnostic: BsDiagnostic) {
54
    const { range } = diagnostic;
6✔
55
    return {
6✔
56
        diagnostic,
57
        changes: [
58
            insertText(range.end, ',')
59
        ]
60
    };
61
}
62

63
function removeAAComma(diagnostic: BsDiagnostic) {
64
    const { range } = diagnostic;
9✔
65
    return {
9✔
66
        diagnostic,
67
        changes: [
68
            replaceText(range, '')
69
        ]
70
    };
71
}
72

73
function addConditionGroup(diagnostic: BsDiagnostic) {
74
    const stat: IfStatement | WhileStatement = diagnostic.data;
5✔
75
    const { start, end } = stat.condition.range;
5✔
76
    return {
5✔
77
        diagnostic,
78
        changes: [
79
            insertText(Position.create(start.line, start.character), '('),
80
            insertText(Position.create(end.line, end.character), ')')
81
        ]
82
    };
83
}
84

85
function removeConditionGroup(diagnostic: BsDiagnostic) {
86
    const stat: (IfStatement | WhileStatement) & { condition: GroupingExpression } = diagnostic.data;
5✔
87
    const { left, right } = stat.condition.tokens;
5✔
88
    const spaceBefore = left.leadingWhitespace?.length > 0 ? '' : ' ';
5!
89
    let spaceAfter = '';
5✔
90
    if (isIfStatement(stat)) {
5✔
91
        spaceAfter = stat.isInline ? ' ' : '';
3✔
92
        if (stat.tokens.then) {
3✔
93
            spaceAfter = stat.tokens.then.leadingWhitespace?.length > 0 ? '' : ' ';
2!
94
        }
95
    }
96
    return {
5✔
97
        diagnostic,
98
        changes: [
99
            replaceText(left.range, spaceBefore),
100
            replaceText(right.range, spaceAfter)
101
        ]
102
    };
103
}
104

105
function addThenToken(diagnostic: BsDiagnostic) {
106
    const stat: IfStatement = diagnostic.data;
3✔
107
    const { end } = stat.condition.range;
3✔
108
    // const { start } = stat.thenBranch.range; // TODO: use when Block range bug is fixed
109
    const start = stat.thenBranch.statements[0]?.range.start;
3!
110
    const space = stat.isInline && comparePos(end, start) === 0 ? ' ' : '';
3✔
111
    return {
3✔
112
        diagnostic,
113
        changes: [
114
            insertText(end, ` then${space}`)
115
        ]
116
    };
117
}
118

119
function removeThenToken(diagnostic: BsDiagnostic) {
120
    const stat: IfStatement = diagnostic.data;
4✔
121
    const { then } = stat.tokens;
4✔
122
    const { line, character } = then.range.start;
4✔
123
    const range = Range.create(
4✔
124
        line, character - (then.leadingWhitespace?.length || 0), line, character + then.text.length
17!
125
    );
126
    return {
4✔
127
        diagnostic,
128
        changes: [
129
            replaceText(range, '')
130
        ]
131
    };
132
}
133

134
function replaceFunctionTokens(diagnostic: BsDiagnostic, token: string) {
135
    const fun: FunctionExpression = diagnostic.data;
6✔
136
    const space = fun.end?.text.indexOf(' ') > 0 ? ' ' : '';
6!
137
    // sub/function keyword
138
    const keywordChanges = [
6✔
139
        replaceText(fun.functionType.range, token),
140
        replaceText(fun.end?.range, `end${space}${token}`)
18!
141
    ];
142
    // remove `as void` in case of `sub`
143
    const returnChanges = token === 'sub' && fun.returnTypeToken?.kind === TokenKind.Void ? [
6✔
144
        replaceText(Range.create(fun.rightParen.range.end, fun.returnTypeToken.range.end), '')
145
    ] : [];
146
    return {
6✔
147
        diagnostic,
148
        changes: [
149
            ...keywordChanges,
150
            ...returnChanges
151
        ]
152
    };
153
}
154

155
function addEolLast(diagnostic: BsDiagnostic): ChangeEntry {
156
    return {
2✔
157
        diagnostic,
158
        changes: [
159
            insertText(
160
                diagnostic.range.end,
161
                // In single line files, the `preferredEol` cannot be determined
162
                // e.g: `sub foo() end sub\EOF`
163
                diagnostic.data.preferredEol ?? (platform.toString() === 'win32' ? '\r\n' : '\n')
7!
164
            )
165
        ]
166
    };
167
}
168

169
function removeEolLast(diagnostic: BsDiagnostic): ChangeEntry {
170
    return {
1✔
171
        diagnostic,
172
        changes: [
173
            replaceText(diagnostic.range, '')
174
        ]
175
    };
176
}
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

© 2026 Coveralls, Inc