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

rokucommunity / brighterscript / #12861

25 Jul 2024 06:50PM UTC coverage: 85.655%. Remained the same
#12861

push

web-flow
Merge f2fa50529 into 87123a285

10870 of 13570 branches covered (80.1%)

Branch coverage included in aggregate %.

66 of 72 new or added lines in 7 files covered. (91.67%)

147 existing lines in 5 files now uncovered.

12309 of 13491 relevant lines covered (91.24%)

26640.65 hits per line

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

92.5
/src/bscPlugin/codeActions/CodeActionsProcessor.ts
1
import type { Diagnostic } from 'vscode-languageserver';
2
import { CodeActionKind } from 'vscode-languageserver';
1✔
3
import { codeActionUtil } from '../../CodeActionUtil';
1✔
4
import type { DiagnosticMessageType } from '../../DiagnosticMessages';
5
import { DiagnosticCodeMap } from '../../DiagnosticMessages';
1✔
6
import type { BrsFile } from '../../files/BrsFile';
7
import type { BscFile } from '../../files/BscFile';
8
import type { XmlFile } from '../../files/XmlFile';
9
import type { OnGetCodeActionsEvent } from '../../interfaces';
10
import { ParseMode } from '../../parser/Parser';
1✔
11
import { util } from '../../util';
1✔
12
import { isBrsFile } from '../../astUtils/reflection';
1✔
13

14
export class CodeActionsProcessor {
1✔
15
    public constructor(
16
        public event: OnGetCodeActionsEvent
10✔
17
    ) {
18

19
    }
20

21
    public process() {
22
        for (const diagnostic of this.event.diagnostics) {
10✔
23
            if (diagnostic.code === DiagnosticCodeMap.cannotFindName || diagnostic.code === DiagnosticCodeMap.cannotFindFunction) {
12✔
24
                this.suggestCannotFindName(diagnostic as any);
8✔
25
            } else if (diagnostic.code === DiagnosticCodeMap.xmlComponentMissingExtendsAttribute) {
4✔
26
                this.addMissingExtends(diagnostic as any);
2✔
27
            }
28
        }
29
    }
30

31
    private suggestedImports = new Set<string>();
10✔
32

33
    /**
34
     * Generic import suggestion function. Shouldn't be called directly from the main loop, but instead called by more specific diagnostic handlers
35
     */
36
    private suggestImports(diagnostic: Diagnostic, key: string, files: BscFile[]) {
37
        //skip if we already have this suggestion
38
        if (this.suggestedImports.has(key) || !isBrsFile(this.event.file)) {
7!
UNCOV
39
            return;
×
40
        }
41

42
        this.suggestedImports.add(key);
7✔
43
        // eslint-disable-next-line @typescript-eslint/dot-notation
44
        const importStatements = this.event.file['_cachedLookups'].importStatements;
7✔
45
        //find the position of the first import statement, or the top of the file if there is none
46
        const insertPosition = importStatements[importStatements.length - 1]?.tokens.import?.location?.range?.start ?? util.createPosition(0, 0);
7✔
47

48
        //find all files that reference this function
49
        for (const file of files) {
7✔
50
            const destPath = util.sanitizePkgPath(file.destPath);
9✔
51
            this.event.codeActions.push(
9✔
52
                codeActionUtil.createCodeAction({
53
                    title: `import "${destPath}"`,
54
                    diagnostics: [diagnostic],
55
                    isPreferred: false,
56
                    kind: CodeActionKind.QuickFix,
57
                    changes: [{
58
                        type: 'insert',
59
                        filePath: this.event.file.srcPath,
60
                        position: insertPosition,
61
                        newText: `import "${destPath}"\n`
62
                    }]
63
                })
64
            );
65
        }
66
    }
67

68
    private suggestCannotFindName(diagnostic: DiagnosticMessageType<'cannotFindName'>) {
69
        //skip if not a BrighterScript file
70
        if ((diagnostic.file as BrsFile).parseMode !== ParseMode.BrighterScript) {
8✔
71
            return;
1✔
72
        }
73
        const lowerName = (diagnostic.data.fullName ?? diagnostic.data.name).toLowerCase();
7!
74

75
        this.suggestImports(
7✔
76
            diagnostic,
77
            lowerName,
78
            [
79
                ...this.event.program.findFilesForFunction(lowerName),
80
                ...this.event.program.findFilesForClass(lowerName),
81
                ...this.event.program.findFilesForNamespace(lowerName),
82
                ...this.event.program.findFilesForEnum(lowerName)
83
            ]
84
        );
85
    }
86

87
    private addMissingExtends(diagnostic: DiagnosticMessageType<'xmlComponentMissingExtendsAttribute'>) {
88
        const srcPath = this.event.file.srcPath;
2✔
89
        const { componentElement } = (this.event.file as XmlFile).parser.ast;
2✔
90
        //inject new attribute after the final attribute, or after the `<component` if there are no attributes
91
        const pos = (componentElement.attributes[componentElement.attributes.length - 1] ?? componentElement.tokens.startTagName)?.location?.range.end;
2!
92
        this.event.codeActions.push(
2✔
93
            codeActionUtil.createCodeAction({
94
                title: `Extend "Group"`,
95
                diagnostics: [diagnostic],
96
                isPreferred: true,
97
                kind: CodeActionKind.QuickFix,
98
                changes: [{
99
                    type: 'insert',
100
                    filePath: srcPath,
101
                    position: pos,
102
                    newText: ' extends="Group"'
103
                }]
104
            })
105
        );
106
        this.event.codeActions.push(
2✔
107
            codeActionUtil.createCodeAction({
108
                title: `Extend "Task"`,
109
                diagnostics: [diagnostic],
110
                kind: CodeActionKind.QuickFix,
111
                changes: [{
112
                    type: 'insert',
113
                    filePath: srcPath,
114
                    position: pos,
115
                    newText: ' extends="Task"'
116
                }]
117
            })
118
        );
119
        this.event.codeActions.push(
2✔
120
            codeActionUtil.createCodeAction({
121
                title: `Extend "ContentNode"`,
122
                diagnostics: [diagnostic],
123
                kind: CodeActionKind.QuickFix,
124
                changes: [{
125
                    type: 'insert',
126
                    filePath: srcPath,
127
                    position: pos,
128
                    newText: ' extends="ContentNode"'
129
                }]
130
            })
131
        );
132
    }
133
}
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