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

rokucommunity / brighterscript / #13286

21 Nov 2024 03:03PM UTC coverage: 88.232% (-0.9%) from 89.088%
#13286

push

TwitchBronBron
0.68.0

6754 of 8102 branches covered (83.36%)

Branch coverage included in aggregate %.

8983 of 9734 relevant lines covered (92.28%)

1868.45 hits per line

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

88.52
/src/PluginInterface.ts
1
import type { CompilerPlugin } from './interfaces';
2
import { LogLevel, createLogger, type Logger } from './logging';
1✔
3
/*
4
 * we use `Required` everywhere here because we expect that the methods on plugin objects will
5
 * be optional, and we don't want to deal with `undefined`.
6
 * `extends (...args: any[]) => any` determines whether the thing we're dealing with is a function.
7
 * Returning `never` in the `as` clause of the `[key in object]` step deletes that key from the
8
 * resultant object.
9
 * on the right-hand side of the mapped type we are forced to use a conditional type a second time,
10
 * in order to be able to use the `Parameters` utility type on `Required<T>[K]`. This will always
11
 * be true because of the filtering done by the `[key in object]` clause, but TS requires the duplication.
12
 *
13
 * so put together: we iterate over all of the fields in T, deleting ones which are not (potentially
14
 * optional) functions. For the ones that are, we replace them with their parameters.
15
 *
16
 * this returns the type of an object whose keys are the names of the methods of T and whose values
17
 * are tuples containing the arguments that each method accepts.
18
 */
19
export type PluginEventArgs<T> = {
20
    [K in keyof Required<T> as Required<T>[K] extends (...args: any[]) => any ? K : never]:
21
    Required<T>[K] extends (...args: any[]) => any ? Parameters<Required<T>[K]> : never
22
};
23

24
export default class PluginInterface<T extends CompilerPlugin = CompilerPlugin> {
1✔
25

26
    constructor();
27
    /**
28
     * @deprecated use the `options` parameter pattern instead
29
     */
30
    constructor(
31
        plugins?: CompilerPlugin[],
32
        logger?: Logger
33
    );
34
    constructor(
35
        plugins?: CompilerPlugin[],
36
        options?: {
37
            logger?: Logger;
38
            suppressErrors?: boolean;
39
        }
40
    );
41
    constructor(
42
        private plugins?: CompilerPlugin[],
1,293✔
43
        options?: {
44
            logger?: Logger;
45
            suppressErrors?: boolean;
46
        } | Logger
47
    ) {
48
        this.plugins ??= [];
1,293✔
49
        if (options?.constructor.name === 'Logger') {
1,293!
50
            this.logger = options as unknown as Logger;
×
51
        } else {
52
            this.logger = (options as any)?.logger;
1,293✔
53
            this.suppressErrors = (options as any)?.suppressErrors === false ? false : true;
1,293✔
54
        }
55
        if (!this.logger) {
1,293✔
56
            this.logger = createLogger();
1✔
57
        }
58
    }
59

60
    private logger: Logger;
61

62
    /**
63
     * Should plugin errors cause the program to fail, or should they be caught and simply logged
64
     */
65
    private suppressErrors: boolean | undefined;
66

67
    /**
68
     * Call `event` on plugins
69
     */
70
    public emit<K extends keyof PluginEventArgs<T> & string>(event: K, ...args: PluginEventArgs<T>[K]) {
71
        for (let plugin of this.plugins) {
16,139✔
72
            if ((plugin as any)[event]) {
16,785✔
73
                try {
4,100✔
74
                    this.logger.time(LogLevel.debug, [plugin.name, event], () => {
4,100✔
75
                        (plugin as any)[event](...args);
4,100✔
76
                    });
77
                } catch (err) {
78
                    this.logger.error(`Error when calling plugin ${plugin.name}.${event}:`, err);
2✔
79
                    if (!this.suppressErrors) {
2!
80
                        throw err;
×
81
                    }
82
                }
83
            }
84
        }
85
    }
86

87
    /**
88
     * Add a plugin to the beginning of the list of plugins
89
     */
90
    public addFirst<T extends CompilerPlugin = CompilerPlugin>(plugin: T) {
91
        if (!this.has(plugin)) {
1,271!
92
            this.plugins.unshift(plugin);
1,271✔
93
        }
94
        return plugin;
1,271✔
95
    }
96

97
    /**
98
     * Add a plugin to the end of the list of plugins
99
     */
100
    public add<T extends CompilerPlugin = CompilerPlugin>(plugin: T) {
101
        if (!this.has(plugin)) {
63✔
102
            this.plugins.push(plugin);
62✔
103
        }
104
        return plugin;
63✔
105
    }
106

107
    public has(plugin: CompilerPlugin) {
108
        return this.plugins.includes(plugin);
1,339✔
109
    }
110

111
    public remove<T extends CompilerPlugin = CompilerPlugin>(plugin: T) {
112
        if (this.has(plugin)) {
2!
113
            this.plugins.splice(this.plugins.indexOf(plugin));
2✔
114
        }
115
        return plugin;
2✔
116
    }
117

118
    /**
119
     * Remove all plugins
120
     */
121
    public clear() {
122
        this.plugins = [];
×
123
    }
124
}
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