Skip to content

Commit

Permalink
Merge branch 'master' into feat/ternary-support
Browse files Browse the repository at this point in the history
  • Loading branch information
TwitchBronBron committed Jan 25, 2021
2 parents a98fa0a + ce803df commit 3f8801e
Show file tree
Hide file tree
Showing 12 changed files with 112 additions and 82 deletions.
12 changes: 11 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0



## [0.28.2] -2021-01-22
### Changed
- config loading functions from `util.ts` are now run synchronously
### Fixed
- missing variable from `for each` statement in completions for language server
- bug when running the CLI that wouldn't properly read the `sourceMap` property from bsconfig.json



## [0.28.1] - 2021-01-19
### Changed
- (For plugin authors) refactored many async methods into sync methods to simplify file creation/management. ([#278](https://github.com/rokucommunity/brighterscript/pull/278))
Expand Down Expand Up @@ -845,4 +854,5 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
[0.26.0]: https://github.com/rokucommunity/brighterscript/compare/v0.25.0...v0.26.0
[0.27.0]: https://github.com/rokucommunity/brighterscript/compare/v0.26.0...v0.27.0
[0.28.0]: https://github.com/rokucommunity/brighterscript/compare/v0.27.0...v0.28.0
[0.28.1]: https://github.com/rokucommunity/brighterscript/compare/v0.28.0...v0.28.1
[0.28.1]: https://github.com/rokucommunity/brighterscript/compare/v0.28.0...v0.28.1
[0.28.2]: https://github.com/rokucommunity/brighterscript/compare/v0.28.1...v0.28.2
2 changes: 1 addition & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "brighterscript",
"version": "0.28.1",
"version": "0.28.2",
"description": "A superset of Roku's BrightScript language.",
"scripts": {
"preversion": "npm run build && npm run lint && npm run test",
Expand Down
2 changes: 1 addition & 1 deletion src/LanguageServer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -449,7 +449,7 @@ export class LanguageServer {
let configFilePath = await util.findClosestConfigFile(filePathAbsolute);
let project: BsConfig = {};
if (configFilePath) {
project = await util.normalizeAndResolveConfig({ project: configFilePath });
project = util.normalizeAndResolveConfig({ project: configFilePath });
}
//override the rootDir and files array
project.rootDir = cwd;
Expand Down
28 changes: 28 additions & 0 deletions src/Program.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -685,6 +685,34 @@ describe('Program', () => {
});

describe('getCompletions', () => {
it('includes `for each` variable', () => {
program.addOrReplaceFile('source/main.brs', `
sub main()
items = [1, 2, 3]
for each thing in items
t =
end for
end for
end sub
`);
program.validate();
let completions = program.getCompletions(`${rootDir}/source/main.brs`, Position.create(4, 28)).map(x => x.label);
expect(completions).to.include('thing');
});

it('includes `for` variable', () => {
program.addOrReplaceFile('source/main.brs', `
sub main()
for i = 0 to 10
t =
end for
end sub
`);
program.validate();
let completions = program.getCompletions(`${rootDir}/source/main.brs`, Position.create(3, 28)).map(x => x.label);
expect(completions).to.include('i');
});

it('should include first-level namespace names for brighterscript files', () => {
program.addOrReplaceFile('source/main.bs', `
namespace NameA.NameB.NameC
Expand Down
2 changes: 0 additions & 2 deletions src/Program.ts
Original file line number Diff line number Diff line change
Expand Up @@ -669,8 +669,6 @@ export class Program {
//if there are no scopes, include the global scope so we at least get the built-in functions
scopes = scopes.length > 0 ? scopes : [this.globalScope];

//get the completions for this file for every scope

//get the completions from all scopes for this file
let allCompletions = util.flatMap(
scopes.map(ctx => file.getCompletions(position, ctx)),
Expand Down
4 changes: 2 additions & 2 deletions src/ProgramBuilder.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,9 @@ describe('ProgramBuilder', () => {
});

let builder: ProgramBuilder;
beforeEach(async () => {
beforeEach(() => {
builder = new ProgramBuilder();
builder.options = await util.normalizeAndResolveConfig({
builder.options = util.normalizeAndResolveConfig({
rootDir: rootDir
});
builder.program = new Program(builder.options);
Expand Down
2 changes: 1 addition & 1 deletion src/ProgramBuilder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ export class ProgramBuilder {
}
this.isRunning = true;
try {
this.options = await util.normalizeAndResolveConfig(options);
this.options = util.normalizeAndResolveConfig(options);
this.loadPlugins();
} catch (e) {
if (e?.file && e.message && e.code) {
Expand Down
2 changes: 1 addition & 1 deletion src/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ let options = yargs
.usage('$0', 'BrighterScript, a superset of Roku\'s BrightScript language')
.help('help', 'View help information about this tool.')
.option('create-package', { type: 'boolean', defaultDescription: 'true', description: 'Creates a zip package. This setting is ignored when deploy is enabled.' })
.option('source-map', { type: 'boolean', default: false, defaultDescription: 'false', description: 'Enables generating sourcemap files, which allow debugging tools to show the original source code while running the emitted files.' })
.option('source-map', { type: 'boolean', defaultDescription: 'false', description: 'Enables generating sourcemap files, which allow debugging tools to show the original source code while running the emitted files.' })
.option('cwd', { type: 'string', description: 'Override the current working directory.' })
.option('copy-to-staging', { type: 'boolean', defaultDescription: 'true', description: 'Copy project files into the staging folder, ready to be packaged.' })
.option('diagnostic-level', { type: 'string', defaultDescription: '"warn"', description: 'Specify what diagnostic types should be printed to the console. Value can be "error", "warn", "hint", "info".' })
Expand Down
14 changes: 14 additions & 0 deletions src/files/BrsFile.ts
Original file line number Diff line number Diff line change
Expand Up @@ -501,6 +501,20 @@ export class BrsFile {
});
}

//add all of ForEachStatement loop varibales
func.body.walk(createVisitor({
ForEachStatement: (stmt) => {
scope.variableDeclarations.push({
nameRange: stmt.item.range,
lineIndex: stmt.item.range.start.line,
name: stmt.item.text,
type: new DynamicType()
});
}
}), {
walkMode: WalkMode.visitStatements
});

this.scopesByFunc.set(func, scope);

//find every statement in the scope
Expand Down
106 changes: 43 additions & 63 deletions src/util.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,21 +44,21 @@ describe('util', () => {
});

describe('loadConfigFile', () => {
it('returns undefined when no path is provided', async () => {
expect(await util.loadConfigFile(undefined)).to.be.undefined;
it('returns undefined when no path is provided', () => {
expect(util.loadConfigFile(undefined)).to.be.undefined;
});

it('returns undefined when the path does not exist', async () => {
expect(await util.loadConfigFile(`?${rootDir}/donotexist.json`)).to.be.undefined;
it('returns undefined when the path does not exist', () => {
expect(util.loadConfigFile(`?${rootDir}/donotexist.json`)).to.be.undefined;
});

it('returns proper list of ancestor project paths', async () => {
it('returns proper list of ancestor project paths', () => {
fsExtra.outputFileSync(s`${rootDir}/child.json`, `{"extends": "parent.json"}`);
fsExtra.outputFileSync(s`${rootDir}/parent.json`, `{"extends": "grandparent.json"}`);
fsExtra.outputFileSync(s`${rootDir}/grandparent.json`, `{"extends": "greatgrandparent.json"}`);
fsExtra.outputFileSync(s`${rootDir}/greatgrandparent.json`, `{}`);
expect(
(await util.loadConfigFile(s`${rootDir}/child.json`))._ancestors.map(x => s(x))
util.loadConfigFile(s`${rootDir}/child.json`)._ancestors.map(x => s(x))
).to.eql([
s`${rootDir}/child.json`,
s`${rootDir}/parent.json`,
Expand All @@ -67,9 +67,9 @@ describe('util', () => {
]);
});

it('returns empty ancestors list for non-extends files', async () => {
it('returns empty ancestors list for non-extends files', () => {
fsExtra.outputFileSync(s`${rootDir}/child.json`, `{}`);
let config = await util.loadConfigFile(s`${rootDir}/child.json`);
let config = util.loadConfigFile(s`${rootDir}/child.json`);
expect(
config._ancestors.map(x => s(x))
).to.eql([
Expand Down Expand Up @@ -114,34 +114,34 @@ describe('util', () => {
});

describe('getConfigFilePath', () => {
it('returns undefined when it does not find the file', async () => {
let configFilePath = await util.getConfigFilePath(s`${process.cwd()}/testProject/project1`);
it('returns undefined when it does not find the file', () => {
let configFilePath = util.getConfigFilePath(s`${process.cwd()}/testProject/project1`);
expect(configFilePath).not.to.exist;
});

it('returns path to file when found', async () => {
it('returns path to file when found', () => {
fsExtra.outputFileSync(s`${tempDir}/rootDir/bsconfig.json`, '');
expect(
await util.getConfigFilePath(s`${tempDir}/rootDir`)
util.getConfigFilePath(s`${tempDir}/rootDir`)
).to.equal(
s`${tempDir}/rootDir/bsconfig.json`
);
});

it('finds config file in parent directory', async () => {
it('finds config file in parent directory', () => {
const bsconfigPath = s`${tempDir}/rootDir/bsconfig.json`;
fsExtra.outputFileSync(bsconfigPath, '');
fsExtra.ensureDirSync(`${tempDir}/rootDir/source`);
expect(
await util.getConfigFilePath(s`${tempDir}/rootDir/source`)
util.getConfigFilePath(s`${tempDir}/rootDir/source`)
).to.equal(
s`${tempDir}/rootDir/bsconfig.json`
);
});

it('uses cwd when not provided', async () => {
it('uses cwd when not provided', () => {
//sanity check
expect(await util.getConfigFilePath()).not.to.exist;
expect(util.getConfigFilePath()).not.to.exist;

const rootDir = s`${tempDir}/rootDir`;

Expand All @@ -151,7 +151,7 @@ describe('util', () => {
process.chdir(rootDir);
try {
expect(
await util.getConfigFilePath()
util.getConfigFilePath()
).to.equal(
s`${rootDir}/bsconfig.json`
);
Expand Down Expand Up @@ -205,39 +205,39 @@ describe('util', () => {
});

describe('normalizeAndResolveConfig', () => {
it('throws for missing project file', async () => {
await expectThrowAsync(async () => {
await util.normalizeAndResolveConfig({ project: 'path/does/not/exist/bsconfig.json' });
});
it('throws for missing project file', () => {
expect(() => {
util.normalizeAndResolveConfig({ project: 'path/does/not/exist/bsconfig.json' });
}).to.throw;
});

it('does not throw for optional missing', async () => {
await expectNotThrowAsync(async () => {
await util.normalizeAndResolveConfig({ project: '?path/does/not/exist/bsconfig.json' });
it('does not throw for optional missing', () => {
expect(() => {
util.normalizeAndResolveConfig({ project: '?path/does/not/exist/bsconfig.json' });

});
}).not.to.throw;
});

it('throws for missing extends file', async () => {
it('throws for missing extends file', () => {
try {
fsExtra.outputFileSync(s`${rootDir}/bsconfig.json`, `{ "extends": "path/does/not/exist/bsconfig.json" }`);
await expectThrowAsync(async () => {
await util.normalizeAndResolveConfig({
expect(() => {
util.normalizeAndResolveConfig({
project: s`${rootDir}/bsconfig.json`
});
});
}).to.throw;
} finally {
process.chdir(cwd);
}
});

it('throws for missing extends file', async () => {
it('throws for missing extends file', () => {
fsExtra.outputFileSync(s`${rootDir}/bsconfig.json`, `{ "extends": "?path/does/not/exist/bsconfig.json" }`);
await expectNotThrowAsync(async () => {
await util.normalizeAndResolveConfig({
expect(() => {
util.normalizeAndResolveConfig({
project: s`${rootDir}/bsconfig.json`
});
});
}).not.to.throw;
});
});

Expand All @@ -250,9 +250,9 @@ describe('util', () => {
expect(util.normalizeConfig(<any>{ emitDefinitions: 'true' }).emitDefinitions).to.be.false;
});

it('loads project from disc', async () => {
it('loads project from disc', () => {
fsExtra.outputFileSync(s`${tempDir}/rootDir/bsconfig.json`, `{ "outFile": "customOutDir/pkg.zip" }`);
let config = await util.normalizeAndResolveConfig({
let config = util.normalizeAndResolveConfig({
project: s`${tempDir}/rootDir/bsconfig.json`
});
expect(
Expand All @@ -262,7 +262,7 @@ describe('util', () => {
);
});

it('loads project from disc and extends it', async () => {
it('loads project from disc and extends it', () => {
//the extends file
fsExtra.outputFileSync(s`${tempDir}/rootDir/bsconfig.base.json`, `{
"outFile": "customOutDir/pkg1.zip",
Expand All @@ -275,14 +275,14 @@ describe('util', () => {
"watch": true
}`);

let config = await util.normalizeAndResolveConfig({ project: s`${tempDir}/rootDir/bsconfig.json` });
let config = util.normalizeAndResolveConfig({ project: s`${tempDir}/rootDir/bsconfig.json` });

expect(config.outFile).to.equal(s`${tempDir}/rootDir/customOutDir/pkg1.zip`);
expect(config.rootDir).to.equal(s`${tempDir}/rootDir/core`);
expect(config.watch).to.equal(true);
});

it('overrides parent files array with child files array', async () => {
it('overrides parent files array with child files array', () => {
//the parent file
fsExtra.outputFileSync(s`${tempDir}/rootDir/bsconfig.parent.json`, `{
"files": ["base.brs"]
Expand All @@ -294,12 +294,12 @@ describe('util', () => {
"files": ["child.brs"]
}`);

let config = await util.normalizeAndResolveConfig({ project: s`${tempDir}/rootDir/bsconfig.json` });
let config = util.normalizeAndResolveConfig({ project: s`${tempDir}/rootDir/bsconfig.json` });

expect(config.files).to.eql(['child.brs']);
});

it('catches circular dependencies', async () => {
it('catches circular dependencies', () => {
fsExtra.outputFileSync(s`${rootDir}/bsconfig.json`, `{
"extends": "bsconfig2.json"
}`);
Expand All @@ -309,7 +309,7 @@ describe('util', () => {

let threw = false;
try {
await util.normalizeAndResolveConfig({ project: s`${rootDir}/bsconfig.json` });
util.normalizeAndResolveConfig({ project: s`${rootDir}/bsconfig.json` });
} catch (e) {
threw = true;
}
Expand All @@ -318,8 +318,8 @@ describe('util', () => {
//the test passed
});

it('properly handles default for watch', async () => {
let config = await util.normalizeAndResolveConfig({ watch: true });
it('properly handles default for watch', () => {
let config = util.normalizeAndResolveConfig({ watch: true });
expect(config.watch).to.be.true;
});
});
Expand Down Expand Up @@ -631,23 +631,3 @@ describe('util', () => {
});
});
});

async function expectThrowAsync(callback) {
let ex;
try {
await Promise.resolve(callback());
} catch (e) {
ex = e;
}
expect(ex, 'Expected to throw error').to.exist;
}

async function expectNotThrowAsync(callback) {
let ex;
try {
await Promise.resolve(callback());
} catch (e) {
ex = e;
}
expect(ex, 'Expected not to throw error').not.to.exist;
}
Loading

0 comments on commit 3f8801e

Please sign in to comment.