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

rokucommunity / roku-debug / #2026

02 Nov 2022 02:41PM UTC coverage: 56.194% (+7.0%) from 49.18%
#2026

push

TwitchBronBron
0.17.0

997 of 1898 branches covered (52.53%)

Branch coverage included in aggregate %.

2074 of 3567 relevant lines covered (58.14%)

15.56 hits per line

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

91.04
/src/PrintedObjectParser.ts
1
export class PrintedObjectParser {
1✔
2
    constructor(private line: string) {
11✔
3
        this.parse();
11✔
4
    }
5
    private currentIndex: number;
6

7
    private key: string;
8
    private value: string;
9

10
    public get result() {
11
        return this.key && this.value ? {
11✔
12
            key: this.key,
13
            value: this.value
14
        } : undefined;
15
    }
16

17
    private take() {
18
        //iterate from right-to-left, since the rhs strings have quotes around them (but the lhs ones do not)
19
        return this.line[this.currentIndex--];
113✔
20
    }
21

22
    private peek() {
23
        return this.line[this.currentIndex];
272✔
24
    }
25

26
    /**
27
     * Indicates whether the index is at or past the end of the line
28
     */
29
    private isAtEnd() {
30
        return this.currentIndex >= this.line.length;
94✔
31
    }
32

33
    /**
34
     * get a string with all of the characters up to
35
     * @param stopChar
36
     */
37
    private takeUntil(stopChar: string, includeStopChar = true) {
15✔
38
        let result = '';
22✔
39
        while (this.peek() && this.peek() !== stopChar) {
22✔
40
            if (this.isAtEnd()) {
94!
41
                return undefined;
×
42
            }
43
            result += this.take();
94✔
44
        }
45
        if (includeStopChar) {
22✔
46
            result += this.take();
15✔
47
        }
48
        return result;
22✔
49
    }
50

51
    /**
52
     * Take all whitespace chars until a non-whitespace char is found
53
     */
54
    private takeWhitespace() {
55
        let result = '';
11✔
56
        while (this.peek() === ' ' || this.peek() === '\t') {
11✔
57
            result += this.take();
×
58
        }
59
        return result;
11✔
60
    }
61

62
    private hasValue() {
63
        return !!this.value;
44✔
64
    }
65

66
    private parse() {
67
        //throw out the beginning 4 characters of the line that roku always includes for object properties
68
        this.line = this.line.substring(4);
11✔
69

70
        this.currentIndex = this.line.length - 1;
11✔
71

72
        //trim right whitespace
73
        this.takeWhitespace();
11✔
74

75
        //try to get the value. All of these methods will immediately exit if value was already found
76
        this.tryTakeStringValue();
11✔
77
        this.tryTakeComponentValue();
11✔
78
        this.tryTakeBasicValue();
11✔
79

80
        //if we found a value, then the remaining characters are the key
81
        if (this.hasValue()) {
11!
82
            //we process backwards, so reverse the value
83
            this.value = this.value.split('').reverse().join('').trim();
11✔
84
            this.takeKey();
11✔
85
        }
86
    }
87

88
    private tryTakeStringValue() {
89
        if (this.hasValue()) {
11!
90
            return;
×
91
        }
92

93
        //TODO support complex strings like `"cat says "bark" like a dog"`
94

95
        //if ends with quote
96
        if (this.peek() === '"') {
11✔
97
            //very primative take (does not support quotes embedded inside quotes).
98
            //roku does not escape the quotes inside of quotes for this type of print, unfortunately
99

100
            //take the opening quote, and all chars up to (and including) the closing quote
101
            this.value = this.take() + this.takeUntil('"');
2✔
102
        }
103
    }
104

105
    private tryTakeComponentValue() {
106
        if (this.hasValue()) {
11✔
107
            return;
2✔
108
        }
109
        //if ends with greaterThan, this is a component reference
110
        if (this.peek() === '>') {
9✔
111
            //take until lessThan
112
            this.value = this.take() + this.takeUntil('<');
2✔
113
        }
114
    }
115

116
    /**
117
     * Look for basic values like int, boolean, and other non-string and non-object values.
118
     * These are going to be non-semicolon characters found to the right of a semicolon (i.e. `age: 123` or `isAlive: true`)
119
     */
120
    private tryTakeBasicValue() {
121
        if (this.hasValue()) {
11✔
122
            return;
4✔
123
        }
124
        this.value = this.takeUntil(':', false);
7✔
125
    }
126

127
    /**
128
     * Clean up the remaining characters, and use them as the key
129
     */
130
    private takeKey() {
131
        //throw out characters until we reach a colon
132
        this.takeUntil(':');
11✔
133
        this.key = this.line.substring(0, this.currentIndex + 1);
11✔
134
    }
135
}
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