Skip to content

Commit 5f55915

Browse files
committed
Adds the template children and field attributes to the component
1 parent 75f2595 commit 5f55915

1 file changed

Lines changed: 43 additions & 5 deletions

File tree

src/bscPlugin/fileProviders/ComponentStatementProvider.ts

Lines changed: 43 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import { Cache } from '../../Cache';
77
import * as path from 'path';
88
import { util } from '../../util';
99
import type { ProvideFileEvent } from '../../interfaces';
10-
import { isDottedGetExpression, isFieldStatement, isMethodStatement, isVariableExpression } from '../../astUtils/reflection';
10+
import { isDottedGetExpression, isFieldStatement, isMethodStatement, isVariableExpression, isLiteralExpression, isTemplateStringExpression } from '../../astUtils/reflection';
1111
import { createFunctionStatement, createFunctionExpression, createDottedSetStatement, createVariableExpression } from '../../astUtils/creators';
1212
import type { Statement } from '../../parser/AstNode';
1313
import { TokenKind } from '../../lexer/TokenKind';
@@ -27,7 +27,7 @@ export class ComponentStatementProvider {
2727
const cache = new Cache<string, string>();
2828
file.ast.walk(createVisitor({
2929
ComponentStatement: (node) => {
30-
//force the desetPath for this component to be within the `pkg:/components` folder
30+
//force the destPath for this component to be within the `pkg:/components` folder
3131
const destDir = cache.getOrAdd(file.srcPath, () => {
3232
return path.dirname(file.destPath).replace(/^(.+?)(?=[\/\\]|$)/, (match: string, firstDirName: string) => {
3333
return 'components';
@@ -56,26 +56,64 @@ export class ComponentStatementProvider {
5656

5757
//declare interface field
5858
} else if (isFieldStatement(member) && member.accessModifier?.text.toLowerCase() === 'public') {
59-
return `<field id="${member.name.text}" type="${member.typeExpression.getName()}" />`;
59+
return `<field
60+
id="${member.name.text}"
61+
type="${member.typeExpression.getName()}"
62+
alias="${this.getAnnotationValue(member.annotations?.filter(x => x.name.toLowerCase() === 'alias'))}"
63+
onChange="${this.getAnnotationValue(member.annotations?.filter(x => x.name.toLowerCase() === 'onchange'))}"
64+
alwaysNotify="${this.getAnnotationValue(member.annotations?.filter(x => x.name.toLowerCase() === 'alwaysnotify')) === 'true'}"
65+
/>`;
6066
} else {
6167
return '';
6268
}
6369
}).filter(x => !!x);
6470

71+
let componentChildren = '';
72+
const template = statement.annotations?.find(x => x.name.toLowerCase() === 'template');
73+
if (template) {
74+
componentChildren = `<children>${this.getAnnotationValue([template])}</children>`;
75+
}
76+
6577
xmlFile.parse(undent`
6678
<component name="${name}" extends="${statement.getParentName(ParseMode.BrightScript) ?? 'Group'}">
6779
<script uri="${util.sanitizePkgPath(file.destPath)}" />
6880
<script uri="${util.sanitizePkgPath(codebehindFile.destPath)}" />
6981
${interfaceMembers.length > 0 ? '<interface>' : ''}
7082
${interfaceMembers.join('\n ')}
7183
${interfaceMembers.length > 0 ? '</interface>' : ''}
84+
${componentChildren}
7285
</component>
7386
`);
7487

75-
7688
this.event.files.push(xmlFile);
7789
}
7890

91+
private getAnnotationValue(annotations: any) {
92+
let response = [];
93+
annotations.forEach(a => {
94+
let args = a?.call?.args[0];
95+
if (isVariableExpression(args) || isDottedGetExpression(args)) {
96+
response.push(args.name.text);
97+
} else if (isLiteralExpression(args)) {
98+
let values = args?.token?.text.replaceAll('\"', '').replaceAll(' ', '').split(',');
99+
response = response.concat(values);
100+
} else if (isTemplateStringExpression(args)) {
101+
let textOutput = '';
102+
args.quasis[0]?.expressions?.forEach((a: { token: { text: string } }) => {
103+
if (!a.token.text.includes('component>') && !a.token.text.includes('children>')) {
104+
textOutput += a.token.text;
105+
}
106+
});
107+
response.push(textOutput);
108+
}
109+
});
110+
111+
response = response.filter((item, index) => {
112+
return response.indexOf(item) === index;
113+
});
114+
return response.join(', ');
115+
}
116+
79117
private registerCodebehind(name: string, statement: ComponentStatement, destDir: string) {
80118
//create the codebehind file
81119
const file = this.event.fileFactory.BrsFile({
@@ -120,7 +158,7 @@ export class ComponentStatementProvider {
120158
initFunc.func.body.statements.unshift(...initStatements);
121159
}
122160

123-
//TODO these are hacks that we need until scope has been refactored to leverate the AST directly
161+
//TODO these are hacks that we need until scope has been refactored to leverage the AST directly
124162
file.parser.invalidateReferences();
125163
// eslint-disable-next-line @typescript-eslint/dot-notation
126164
file['findCallables']();

0 commit comments

Comments
 (0)