Skip to content

Commit 91b96a2

Browse files
Merge branch 'v1' into issue-1397-align-event-names
2 parents d779db4 + 2ea4d21 commit 91b96a2

33 files changed

+1110
-69
lines changed

CHANGELOG.md

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,24 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
66

77

88

9+
## [1.0.0-alpha.49](https://github.com/rokucommunity/brighterscript/compare/1.0.0-alpha.48...v1.0.0-alpha.49) - 2025-12-10
10+
### Added
11+
- Adds `TypeStatement` for declaring new types ([#1597](https://github.com/rokucommunity/brighterscript/pull/1597))
12+
- Adds Inline interfaces ([#1591](https://github.com/rokucommunity/brighterscript/pull/1591))
13+
### Changed
14+
- Make Invalid compatible with typed arrays ([#1596](https://github.com/rokucommunity/brighterscript/pull/1596))
15+
- Limit scope Validation ([#1586](https://github.com/rokucommunity/brighterscript/pull/1586))
16+
- Interface extending node includes callfuncs ([#1585](https://github.com/rokucommunity/brighterscript/pull/1585))
17+
- Remove zip and sideload ([#1562](https://github.com/rokucommunity/brighterscript/pull/1562))
18+
- upgrade to [[email protected]](https://github.com/rokucommunity/roku-deploy/blob/master/CHANGELOG.md#3144---2025-10-30)
19+
### Fixed
20+
- Fix validation exception when calling `roFunction` ([#1588](https://github.com/rokucommunity/brighterscript/pull/1588))
21+
- Fix `MaskGroup.maskUri` type ([#1559](https://github.com/rokucommunity/brighterscript/pull/1559))
22+
### Removed
23+
- Remove unused util functions ([#1565](https://github.com/rokucommunity/brighterscript/pull/1565))
24+
25+
26+
927
## [1.0.0-alpha.48](https://github.com/rokucommunity/brighterscript/compare/1.0.0-alpha.47...v1.0.0-alpha.48) - 2025-07-16
1028
### Changed
1129
- Union Return type consistency ([#1508](https://github.com/rokucommunity/brighterscript/pull/1508))

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ A superset of Roku's BrightScript language. Compiles to standard BrightScript.
1111

1212
## Overview
1313

14-
**WARNING: this is the v0.66.0 branch with experimental features**
14+
**WARNING: this is the `v1` branch with experimental features**
1515

1616
The BrighterScript language provides new features and syntax enhancements to Roku's BrightScript language. Because the language is a superset of BrightScript, the parser and associated tools (VSCode integration, cli, etc...) work with standard BrightScript (.brs) files. This means you will get benefits (as described in the following section) from using the BrighterScript compiler, whether your project contains BrighterScript (.bs) files or not. The BrighterScript language transpiles to standard BrightScript, so your code is fully compatible with all roku devices.
1717

docs/readme.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,15 @@ function getY(translation as float[]) as float
134134
end function
135135
```
136136

137+
## [Type Statements](type-statements.md)
138+
```brighterscript
139+
type number = integer or float or double
140+
141+
function sum(x as number, y as number) as number
142+
return x + y
143+
end function
144+
```
145+
137146
## [Union Types](union-types.md)
138147
```brighterscript
139148
sub logData(data as string or number)

docs/type-statements.md

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
## Type Statements
2+
3+
BrighterScript supports declaring custom named types using the `type` keyword. In this way, new types can be created as wrappers, or aliases for other types. This is useful to create custom names for advanced types like unions, so they can be more easily used throughout the code.
4+
5+
## Syntax
6+
7+
To create a new custom named types, use the syntax `type <customName> = <existingType>` at either the top level of a file, or within a namespace.
8+
9+
For example, if you wanted to create a shorthand for the union type `integer or float or double`, you could do the following:
10+
11+
```BrighterScript
12+
type number = integer or float or double
13+
14+
function sum(x as number, y as number) as number
15+
return x + y
16+
end function
17+
18+
function product(x as number, y as number) as number
19+
return x * y
20+
end function
21+
```
22+
23+
<details>
24+
<summary>View the transpiled BrightScript code</summary>
25+
26+
```BrightScript
27+
function sum(x as dynamic, y as dynamic) as dynamic
28+
return x + y
29+
end function
30+
31+
function product(x as dynamic, y as dynamic) as dynamic
32+
return x * y
33+
end function
34+
```
35+
36+
</details>
37+
38+
## Importing
39+
40+
Types created with the `type` keyword are available through importing the file they are declared in.
41+
42+
For example:
43+
44+
**src/components/Widget.bs**
45+
46+
```BrighterScript
47+
namespace Widgets
48+
49+
type widget = Button or Checkbox
50+
51+
interface Button
52+
text as string
53+
action as function
54+
end interface
55+
56+
interface Checkbox
57+
text as string
58+
checked as boolean
59+
end interface
60+
end namespace
61+
```
62+
63+
**src/components/UI.bs**
64+
65+
```BrighterScript
66+
import "pkg:/components/Widget.bs" ' provides the "Widgets.widget" type
67+
68+
function getName(w as Widgets.widget) as string
69+
return w.text
70+
end function
71+
```

package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "brighterscript",
3-
"version": "1.0.0-alpha.48",
3+
"version": "1.0.0-alpha.49",
44
"description": "A superset of Roku's BrightScript language.",
55
"scripts": {
66
"preversion": "npm run build && npm run lint && npm run test",

src/AstValidationSegmenter.ts

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import type { DottedGetExpression, TypeExpression, VariableExpression } from './parser/Expression';
2-
import { isAliasStatement, isArrayType, isBinaryExpression, isBlock, isBody, isClassStatement, isConditionalCompileStatement, isDottedGetExpression, isInterfaceStatement, isNamespaceStatement, isTypecastStatement, isTypeExpression, isVariableExpression } from './astUtils/reflection';
2+
import { isAliasStatement, isArrayType, isBinaryExpression, isBlock, isBody, isClassStatement, isConditionalCompileStatement, isDottedGetExpression, isInterfaceStatement, isNamespaceStatement, isTypecastStatement, isTypeExpression, isTypeStatement, isVariableExpression } from './astUtils/reflection';
33
import { ChildrenSkipper, WalkMode, createVisitor } from './astUtils/visitors';
44
import type { ExtraSymbolData, GetTypeOptions, TypeChainEntry } from './interfaces';
55
import type { AstNode, Expression } from './parser/AstNode';
@@ -81,7 +81,7 @@ export class AstValidationSegmenter {
8181
if (isArrayType(typeInTypeExpression)) {
8282
typeInTypeExpression = typeInTypeExpression.defaultType;
8383
}
84-
if (typeInTypeExpression.isResolvable()) {
84+
if (typeInTypeExpression?.isResolvable()) {
8585
return this.handleTypeCastTypeExpression(segment, expression);
8686
}
8787
}
@@ -115,6 +115,13 @@ export class AstValidationSegmenter {
115115
extraData.definingNode.value.getType({ ...options, flags: SymbolTypeFlag.runtime | SymbolTypeFlag.typetime, typeChain: aliasTypeChain });
116116
typeChain = [...aliasTypeChain, ...typeChain.slice(1)];
117117
}
118+
if (extraData.isFromTypeStatement && isTypeStatement(extraData.definingNode)) {
119+
//set the unwrapped version of this symbol as required.
120+
const wrappedTypeChain = [];
121+
// eslint-disable-next-line no-bitwise
122+
extraData.definingNode.getType({ ...options, flags: SymbolTypeFlag.typetime, typeChain: wrappedTypeChain });
123+
typeChain = [...wrappedTypeChain, ...typeChain.slice(1)];
124+
}
118125
const possibleNamespace = this.currentNamespaceStatement?.getNameParts()?.map(t => t.text)?.join('.').toLowerCase() ?? '';
119126
const fullChainName = util.processTypeChain(typeChain).fullChainName?.toLowerCase();
120127
const possibleNamesLower = [] as string[];
@@ -180,7 +187,6 @@ export class AstValidationSegmenter {
180187
return;
181188
}
182189

183-
184190
this.segmentsForValidation.push(segment);
185191
this.validatedSegments.set(segment, false);
186192
let foundUnresolvedInSegment = false;
@@ -199,6 +205,12 @@ export class AstValidationSegmenter {
199205
unresolvedTypeCastTypeExpression = this.unresolvedTypeCastTypeExpressions[this.unresolvedTypeCastTypeExpressions.length - 1];
200206
}
201207

208+
if (isTypeStatement(segment)) {
209+
// this is a straight assignment,
210+
assignedSymbols.add({ token: segment.tokens.name, node: segment });
211+
assignedSymbolsNames.add(segment.tokens.name.text.toLowerCase());
212+
}
213+
202214
segment.walk(createVisitor({
203215
AssignmentStatement: (stmt) => {
204216
if (stmt.tokens.equals.kind === TokenKind.Equal) {

src/CrossScopeValidator.spec.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1635,5 +1635,24 @@ describe('CrossScopeValidator', () => {
16351635
DiagnosticMessages.nameCollision('Interface', 'Const', 'alpha.beta.Test')
16361636
]);
16371637
});
1638+
1639+
it('finds duplicates when using type statements', () => {
1640+
program.setFile('source/utils.bs', `
1641+
namespace alpha
1642+
type myInt = integer
1643+
1644+
1645+
interface myInt
1646+
value as string
1647+
end interface
1648+
end namespace
1649+
`);
1650+
1651+
program.validate();
1652+
expectDiagnostics(program, [
1653+
DiagnosticMessages.nameCollision('Type', 'Interface', 'alpha.myInt'),
1654+
DiagnosticMessages.nameCollision('Interface', 'Type', 'alpha.myInt')
1655+
]);
1656+
});
16381657
});
16391658
});

0 commit comments

Comments
 (0)