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

Source root #134

Merged
merged 7 commits into from
Jul 6, 2020
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
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,8 @@ These are the options available in the `bsconfig.json` file.
```
- **autoImportComponentScript**: `bool` - BrighterScript only: will automatically import a script at transpile-time for a component with the same name if it exists.

- **sourceRoot*: `string` - Override the root directory path where debugger should locate the source files. The location will be embedded in the source map to help debuggers locate the original source files. This only applies to files found within rootDir. This is useful when you want to preprocess files before passing them to BrighterScript, and want a debugger to open the original files.


## Ignore errors and warnings on a per-line basis
In addition to disabling an entire class of errors in `bsconfig.json` by using `ignoreErrorCodes`, you may also disable errors for a subset of the complier rules within a file with the following comment flags:
Expand Down
4 changes: 4 additions & 0 deletions bsconfig.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,10 @@
"debug",
"trace"
]
},
"sourceRoot": {
"description": "Override the root directory path where debugger should locate the source files. The location will be embedded in the source map to help debuggers locate the original source files. This only applies to files found within rootDir. This is useful when you want to preprocess files before passing them to BrighterScript, and want a debugger to open the original files.",
"type": "string"
}
}
}
7 changes: 7 additions & 0 deletions src/BsConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -117,4 +117,11 @@ export interface BsConfig {
* @default LogLevel.log
*/
logLevel?: LogLevel;
/**
* Override the path to source files in source maps. Use this if you have a preprocess step and want
* to ensure the source maps point to the original location.
* This will only alter source maps for files within rootDir. Any files found outside of rootDir will not
* have their source maps changed.
*/
sourceRoot?: string;
}
52 changes: 52 additions & 0 deletions src/Program.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1381,4 +1381,56 @@ describe('Program', () => {
expect(fsExtra.pathExistsSync(s`${stagingFolderPath}/source/bslib.brs`)).is.true;
});

describe('transpile', () => {
it('uses sourceRoot when provided for brs files', async () => {
let sourceRoot = s`${tmpPath}/sourceRootFolder`;
program = new Program({
rootDir: rootDir,
stagingFolderPath: stagingFolderPath,
sourceRoot: sourceRoot
});
await program.addOrReplaceFile('source/main.brs', `
sub main()
end sub
`);
await program.transpile([{
src: s`${rootDir}/source/main.brs`,
dest: s`source/main.brs`
}], stagingFolderPath);

let contents = fsExtra.readFileSync(s`${stagingFolderPath}/source/main.brs.map`).toString();
let map = JSON.parse(contents);
expect(
s`${map.sources[0]}`
).to.eql(
s`${sourceRoot}/source/main.brs`
);
});

it('uses sourceRoot when provided for bs files', async () => {
let sourceRoot = s`${tmpPath}/sourceRootFolder`;
program = new Program({
rootDir: rootDir,
stagingFolderPath: stagingFolderPath,
sourceRoot: sourceRoot
});
await program.addOrReplaceFile('source/main.bs', `
sub main()
end sub
`);
await program.transpile([{
src: s`${rootDir}/source/main.bs`,
dest: s`source/main.bs`
}], stagingFolderPath);

let contents = fsExtra.readFileSync(s`${stagingFolderPath}/source/main.brs.map`).toString();
let map = JSON.parse(contents);
expect(
s`${map.sources[0]}`
).to.eql(
s`${sourceRoot}/source/main.bs`
);
});
});

});
1 change: 1 addition & 0 deletions src/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ let args = [
{ name: 'root-dir', type: String, description: 'Path to the root of your project files (where the manifest lives). Defaults to current directory.' },
{ name: 'staging-folder-path', type: String, description: 'The path where the files should be staged (right before being zipped up).' },
{ name: 'username', type: String, description: 'The username for deploying to a Roku. Defaults to "rokudev".' },
{ name: 'source-root', type: String, description: 'Override the root directory path where debugger should locate the source files. The location will be embedded in the source map to help debuggers locate the original source files. This only applies to files found within rootDir. This is useful when you want to preprocess files before passing them to BrighterScript, and want a debugger to open the original files.' },
{ name: 'watch', type: Boolean, description: 'Watch input files.' }
];
const options = commandLineArgs(args, { camelCase: true });
Expand Down
7 changes: 3 additions & 4 deletions src/files/BrsFile.ts
Original file line number Diff line number Diff line change
Expand Up @@ -985,26 +985,25 @@ export class BrsFile {
* Convert the brightscript/brighterscript source code into valid brightscript
*/
public transpile() {
const state = new TranspileState(this);
if (this.needsTranspiled) {
const state = new TranspileState(this);
let programNode = new SourceNode(null, null, this.pathAbsolute, this.ast.transpile(state));
let result = programNode.toStringWithSourceMap({
file: this.pathAbsolute
});
return result;
} else {
//create a sourcemap
//create a source map from the original source code
let chunks = [] as (SourceNode | string)[];
let lines = this.fileContents.split(/\r?\n/g);
for (let lineIndex = 0; lineIndex < lines.length; lineIndex++) {
let line = lines[lineIndex];
chunks.push(
lineIndex > 0 ? '\n' : '',
new SourceNode(lineIndex + 1, 0, this.pathAbsolute, line)
new SourceNode(lineIndex + 1, 0, state.pathAbsolute, line)
);
}
return new SourceNode(null, null, this.pathAbsolute, chunks).toStringWithSourceMap();
return new SourceNode(null, null, state.pathAbsolute, chunks).toStringWithSourceMap();
}
}

Expand Down
29 changes: 18 additions & 11 deletions src/parser/TranspileState.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,23 +11,30 @@ export class TranspileState {
file: BrsFile
) {
this.file = file;

//if a sourceRoot is specified, use that instead of the rootDir
if (this.file.program.options.sourceRoot) {
this.pathAbsolute = this.file.pathAbsolute.replace(
this.file.program.options.rootDir,
this.file.program.options.sourceRoot
);
} else {
this.pathAbsolute = this.file.pathAbsolute;
}
}

/**
* The BrsFile that is currently being transpiled
*/
file: BrsFile;
/**
* the path for this file relative to the root of the output package
*/
get pkgPath() {
return this.file.pkgPath;
}
public file: BrsFile;

/**
* the absolute path to the source location of this file
* The absolute path to the source location of this file. If sourceRoot is specified,
* this path will be full path to the file in sourceRoot instead of rootDir.
* If the file resides outside of rootDir, then no changes will be made to this path.
*/
get pathAbsolute() {
return this.file.pathAbsolute;
}
public pathAbsolute: string;

/**
* The number of active parent blocks for the current location of the state.
*/
Expand Down
1 change: 1 addition & 0 deletions src/util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -268,6 +268,7 @@ export class Util {
config.diagnosticFilters = config.diagnosticFilters ?? [];
config.autoImportComponentScript = config.autoImportComponentScript === true ? true : false;
config.showDiagnosticsInConsole = config.showDiagnosticsInConsole === false ? false : true;
config.sourceRoot = config.sourceRoot ? standardizePath(config.sourceRoot) : undefined;
if (typeof config.logLevel === 'string') {
config.logLevel = LogLevel[(config.logLevel as string).toLowerCase()];
}
Expand Down