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

rokucommunity / brighterscript-formatter / #616

pending completion
#616

push

web-flow
<a href="https://github.com/rokucommunity/brighterscript-formatter/commit/<a class=hub.com/rokucommunity/brighterscript-formatter/commit/75af489be7475f5f1a6ed2b7bfc5b74f498dfe75">75af489be<a href="https://github.com/rokucommunity/brighterscript-formatter/commit/75af489be7475f5f1a6ed2b7bfc5b74f498dfe75">">Merge </a><a class="double-link" href="https://github.com/rokucommunity/brighterscript-formatter/commit/<a class="double-link" href="https://github.com/rokucommunity/brighterscript-formatter/commit/391518e42dfc9da4f773db7cb31ceebf2d7323ce">391518e42</a>">391518e42</a><a href="https://github.com/rokucommunity/brighterscript-formatter/commit/75af489be7475f5f1a6ed2b7bfc5b74f498dfe75"> into 503d247e2">503d247e2</a>

470 of 470 branches covered (100.0%)

Branch coverage included in aggregate %.

539 of 539 relevant lines covered (100.0%)

975.44 hits per line

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

100.0
/src/formatters/KeywordCaseFormatter.ts
1
import type { Token } from 'brighterscript';
2
import { CompositeKeywords, CompositeKeywordStartingWords, Keywords } from '../constants';
1✔
3
import type { FormattingOptions } from '../FormattingOptions';
4
import { util } from '../util';
1✔
5

6
export class KeywordCaseFormatter {
1✔
7
    /**
8
     * Handle indentation for an array of tokens
9
     */
10
    public format(tokens: Token[], options: FormattingOptions) {
11
        for (let token of tokens) {
239✔
12

13
            //if this token is a keyword
14
            if (Keywords.includes(token.kind)) {
4,833✔
15

16
                let keywordCase: FormattingOptions['keywordCase'];
17
                let lowerKind = token.kind.toLowerCase();
706✔
18

19
                //a token is a type if it's preceeded by an `as` token
20
                if (this.isType(tokens, token)) {
706✔
21
                    //options.typeCase is always set to options.keywordCase when not provided
22
                    keywordCase = options.typeCase;
29✔
23
                    //if this is an overridden type keyword, use that override instead
24
                    if (options.typeCaseOverride && options.typeCaseOverride[lowerKind] !== undefined) {
29✔
25
                        keywordCase = options.typeCaseOverride[lowerKind];
1✔
26
                    }
27
                } else {
28
                    keywordCase = options.keywordCase;
677✔
29
                    //if this is an overridable keyword, use that override instead
30
                    if (options.keywordCaseOverride && options.keywordCaseOverride[lowerKind] !== undefined) {
677✔
31
                        keywordCase = options.keywordCaseOverride[lowerKind];
8✔
32
                    }
33
                }
34
                switch (keywordCase) {
706✔
35
                    case 'lower':
36
                        token.text = token.text.toLowerCase();
642✔
37
                        break;
642✔
38
                    case 'upper':
39
                        token.text = token.text.toUpperCase();
18✔
40
                        break;
18✔
41
                    case 'title':
42
                        let lowerValue = token.text.toLowerCase();
23✔
43

44
                        //format the first letter (conditional compile composite-keywords start with hash)
45
                        let charIndex = token.text.startsWith('#') ? 1 : 0;
23✔
46
                        token.text = this.upperCaseLetter(token.text, charIndex);
23✔
47

48
                        //if this is a composite keyword, format the first letter of the second word
49
                        if (CompositeKeywords.includes(token.kind)) {
23✔
50
                            let spaceCharCount = (/\s+/.exec(lowerValue) ?? []).length;
5✔
51

52
                            let firstWordLength = CompositeKeywordStartingWords.find(x => lowerValue.startsWith(x))!.length;
12✔
53

54
                            let nextWordFirstCharIndex = firstWordLength + spaceCharCount;
5✔
55
                            token.text = this.upperCaseLetter(token.text, nextWordFirstCharIndex);
5✔
56
                        }
57
                        break;
23✔
58
                    case 'original':
59
                    default:
60
                        //do nothing
61
                        break;
23✔
62

63
                }
64
            }
65
        }
66
        return tokens;
239✔
67
    }
68

69
    /**
70
     * Convert the character at the specified index to upper case
71
     */
72
    private upperCaseLetter(text: string, index: number) {
73
        //out of bounds index should be a noop
74
        if (index < 0 || index > text.length) {
33✔
75
            return text;
1✔
76
        }
77
        text =
32✔
78
            //add the beginning text
79
            text.substring(0, index) +
80
            //uppercase the letter
81
            text.substring(index, index + 1).toUpperCase() +
82
            //rest of word
83
            text.substring(index + 1).toLowerCase();
84
        return text;
32✔
85
    }
86

87
    /**
88
     * Determine if the token is a type keyword (meaing preceeded by `as` token)
89
     * @param token
90
     */
91
    public isType(tokens: Token[], token: Token) {
92
        let previousToken = util.getPreviousNonWhitespaceToken(tokens, tokens.indexOf(token));
706✔
93
        if (previousToken && previousToken.text.toLowerCase() === 'as') {
706✔
94
            return true;
29✔
95
        } else {
96
            return false;
677✔
97
        }
98
    }
99
}
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