Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Task/support bs const in bsconfig #887

Merged
merged 5 commits into from
Sep 6, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions bsconfig.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,21 @@
"description": "The root directory of your Roku project. Defaults to the current working directory (or cwd property)",
"type": "string"
},
"manifest": {
"description": "A entry to modify manifest values",
"type": "object",
"properties": {
"bs_const": {
"description": "A dictionary of bs_consts to change or add to the manifest. Each entry ",
"type": "object",
"patternProperties": {
"^.+$": {
"type": ["boolean", "null"]
}
}
}
}
},
"files": {
"description": "The list of files that should be used in this project. Supports globs. Optionally, you can specify an object with `src` and `dest` properties to move files from one location into a different destination location",
"default": [
Expand Down
4 changes: 4 additions & 0 deletions src/BsConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ export interface BsConfig {
*/
project?: string;

manifest?: {
bs_const?: Record<string, boolean | null>;
};

/**
* Relative or absolute path to another bsconfig.json file that this file should import and then override.
* Prefix with a question mark (?) to prevent throwing an exception if the file does not exist.
Expand Down
88 changes: 88 additions & 0 deletions src/Program.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2966,4 +2966,92 @@ describe('Program', () => {
]);
});
});

describe('getManifest', () => {
beforeEach(() => {
fsExtra.emptyDirSync(tempDir);
fsExtra.writeFileSync(`${tempDir}/manifest`, trim`
# Channel Details
title=sample manifest
major_version=2
minor_version=0
build_version=0
supports_input_launch=1
bs_const=DEBUG=false
`);
program.options = {
rootDir: tempDir
};
});

afterEach(() => {
fsExtra.emptyDirSync(tempDir);
program.dispose();
});

it('loads the manifest', () => {
let manifest = program.getManifest();
testCommonManifestValues(manifest);
expect(manifest.get('bs_const')).to.equal('DEBUG=false');
});

it('adds a const to the manifest', () => {
program.options.manifest = {
// eslint-disable-next-line camelcase
bs_const: {
NEW_VALUE: false
}
};
let manifest = program.getManifest();
testCommonManifestValues(manifest);
expect(manifest.get('bs_const')).to.equal('DEBUG=false;NEW_VALUE=false');
});

it('changes a const in the manifest', () => {
program.options.manifest = {
// eslint-disable-next-line camelcase
bs_const: {
DEBUG: true
}
};
let manifest = program.getManifest();
testCommonManifestValues(manifest);
expect(manifest.get('bs_const')).to.equal('DEBUG=true');
});

it('removes a const in the manifest', () => {
program.options.manifest = {
// eslint-disable-next-line camelcase
bs_const: {
DEBUG: null
}
};
let manifest = program.getManifest();
testCommonManifestValues(manifest);
expect(manifest.get('bs_const')).to.equal('');
});

it('handles no consts in the manifest', () => {
fsExtra.emptyDirSync(tempDir);
fsExtra.writeFileSync(`${tempDir}/manifest`, trim`
# Channel Details
title=sample manifest
major_version=2
minor_version=0
build_version=0
supports_input_launch=1
`);
let manifest = program.getManifest();
testCommonManifestValues(manifest);
expect(manifest.get('bs_const')).to.equal('');
});

function testCommonManifestValues(manifest: Map<string, string>) {
expect(manifest.get('title')).to.equal('sample manifest');
expect(manifest.get('major_version')).to.equal('2');
expect(manifest.get('minor_version')).to.equal('0');
expect(manifest.get('build_version')).to.equal('0');
expect(manifest.get('supports_input_launch')).to.equal('1');
}
});
});
28 changes: 26 additions & 2 deletions src/Program.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import { DependencyGraph } from './DependencyGraph';
import { Logger, LogLevel } from './Logger';
import chalk from 'chalk';
import { globalFile } from './globalCallables';
import { parseManifest } from './preprocessor/Manifest';
import { parseManifest, getBsConst } from './preprocessor/Manifest';
import { URI } from 'vscode-uri';
import PluginInterface from './PluginInterface';
import { isBrsFile, isXmlFile, isXmlScope, isNamespaceStatement } from './astUtils/reflection';
Expand Down Expand Up @@ -1362,7 +1362,31 @@ export class Program {
try {
//we only load this manifest once, so do it sync to improve speed downstream
contents = fsExtra.readFileSync(manifestPath, 'utf-8');
this._manifest = parseManifest(contents);
let parsedManifest = parseManifest(contents);

// Lift the bs_consts defined in the manifest
let bsConsts = getBsConst(parsedManifest, false);

// Override or delete any bs_consts defined in the bs config
for (const key in this.options?.manifest?.bs_const) {
const value = this.options.manifest.bs_const[key];
if (value === null) {
bsConsts.delete(key);
} else {
bsConsts.set(key, value);
}
}

// convert the new list of bs consts back into a string for the rest of the down stream systems to use
let constString = '';
for (const [key, value] of bsConsts) {
constString += `${constString !== '' ? ';' : ''}${key}=${value.toString()}`;
}

// Set the updated bs_const value
parsedManifest.set('bs_const', constString);

this._manifest = parsedManifest;
} catch (err) {
this._manifest = new Map();
}
Expand Down
4 changes: 2 additions & 2 deletions src/preprocessor/Manifest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ export function parseManifest(contents: string) {
* @returns a map of key to boolean value representing the `bs_const` attribute, or an empty map if
* no `bs_const` attribute is found.
*/
export function getBsConst(manifest: Manifest): Map<string, boolean> {
export function getBsConst(manifest: Manifest, toLowerKeys = true): Map<string, boolean> {
if (!manifest.has('bs_const')) {
return new Map();
}
Expand Down Expand Up @@ -89,7 +89,7 @@ export function getBsConst(manifest: Manifest): Map<string, boolean> {
return [keyValuePair.slice(0, equals), keyValuePair.slice(equals + 1)];
})
// remove leading/trailing whitespace from keys and values, and force everything to lower case
.map(([key, value]) => [key.trim().toLowerCase(), value.trim().toLowerCase()])
.map(([key, value]) => [toLowerKeys ? key.trim().toLowerCase() : key.trim(), value.trim().toLowerCase()])
// convert value to boolean or throw
.map(([key, value]): [string, boolean] => {
if (value.toLowerCase() === 'true') {
Expand Down