Skip to content

Commit f6872b6

Browse files
authored
Merge pull request #3 from markwpearce/fix/missing_semicolon
Fixes issue with generating documentation with namespaces
2 parents eeacca4 + 03ec477 commit f6872b6

File tree

7 files changed

+342
-2299
lines changed

7 files changed

+342
-2299
lines changed

.vscode/launch.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
"program": "${workspaceFolder}/node_modules/.bin/jsdoc",
1010
"request": "launch",
1111
"cwd": "${workspaceFolder}",
12-
"args": ["-c", "jsdoc.json", "-t", "node_modules/minami", "-d", "docs"],
12+
"args": ["-c", "jsdoc.json", "-d", "docs"],
1313
"skipFiles": ["<node_internals>/**"],
1414
"type": "node",
1515
"sourceMaps": true

README.md

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -50,25 +50,39 @@ Example:
5050
"includePattern": ".+\\.br?s$"
5151
},
5252
"opts": {
53-
"recurse": true
53+
"recurse": true,
54+
"template": "node_modules/clean-jsdoc-theme", // or whatever template you've chosen - see below
55+
"brighterscript-jsdocs-plugin": {
56+
"addModule": true // true by default - should we generate module names based on the file names?
57+
}
5458
}
5559
}
5660
```
5761

62+
Note: You may want to set configuration value `opts.brighterscript-jsdocs-plugin.addModule` to `false` if you are using Brighterscript namespaces and you want your code grouped by namespace.
63+
5864
3. Add a script to `package.json` like:
5965

6066
```json
6167
"scripts": {
62-
"docs": "./node_modules/.bin/jsdoc -c jsdoc.json -d docs -t ./node_modules/braintree-jsdoc-template"
68+
"docs": "./node_modules/.bin/jsdoc -c jsdoc.json -d docs"
6369
}
6470
```
6571

72+
# Generating Documentation
73+
6674
Run the script to generate documentation! (Documentation is put in the `./docs/` folder)
6775

6876
```
6977
npm run docs
7078
```
7179

80+
# Templates
81+
82+
The default JSDocs template may not meet your needs. Here's a good list of templates that are available:
83+
84+
https://cancerberosgx.github.io/jsdoc-templates-demo/demo/
85+
7286
# Brightscript and Brighterscript
7387

7488
Internally, this plugin uses the [Brighterscript](https://github.com/rokucommunity/brighterscript) parser. Brighterscript is a superset of Roku's Brightscript language, so plain old .brs files should be parsed properly.
@@ -83,7 +97,7 @@ It is not necessary to wrap BrightScript comments in javascript style comments,
8397

8498
These comments will be parsed the same:
8599

86-
```bs
100+
```
87101
' Give the maximum of two numbers
88102
' @param {integer} x - the first number
89103
' @param {integer} y - the second number
@@ -111,7 +125,7 @@ end function
111125

112126
## Example
113127

114-
```bs
128+
```
115129
' Namespace for testing
116130
namespace TestBsDoc
117131

convert-brighterscript-docs.js

Lines changed: 92 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,27 @@
11
'use strict';
22
const bs = require('brighterscript');
33
const path = require('path');
4-
54
const jsCommentStartRegex = /^[\s]*(?:\/\*+)?[\s]*(.*)/g
65
const bsMeaningfulCommentRegex = /^[\s]*(?:'|REM)[\s]*\**[\s]*(.*)/g
76
const paramRegex = /@param\s+(?:{([^}]*)})?\s+(?:\[(\w+).*\]|(\w+))[\s-\s|\s]*(.*)/
87
const returnRegex = /@returns?\s*({(?:[^}]*)})?\s*(.*)/
98
const extendsRegex = /@extends/
9+
const moduleRegex = /@module ([^\*\s]+)/
10+
const opts = env && env.opts || {}
11+
const pluginOpts = opts['brighterscript-jsdocs-plugin'] || {};
12+
13+
if (pluginOpts.addModule === undefined || pluginOpts.addModule === null) {
14+
pluginOpts.addModule = true
15+
}
16+
17+
1018

1119
/** @type {string[]} */
1220
const namespacesCreated = []
1321

22+
/** @type {string[]} */
23+
const modulesCreated = []
24+
1425
/** @type {string[]} */
1526
let parserLines = []
1627

@@ -109,14 +120,28 @@ function getCommentForStatement(comments, stmt) {
109120
}
110121

111122
function getMemberOf(moduleName = "", namespaceName = "") {
112-
const memberOf = namespaceName || moduleName;
113-
123+
const memberOf = namespaceName || moduleName.replace(/\./g, '/');
124+
const memberType = /*namespaceName ? "" : */ "module:"
114125
if (memberOf) {
115-
return (` * @memberof module:${memberOf}`);
126+
return ` * @memberof! ${memberType}${memberOf.replace(/\./g, '/')}`;
116127
}
117128
return ""
118129
}
119130

131+
/**
132+
*
133+
* @param {string} moduleName
134+
* @returns
135+
*/
136+
function getModuleLineComment(moduleName = "") {
137+
const modifiedModuleName = moduleName.replace(/\./g, '/')
138+
if (!modifiedModuleName || modulesCreated.includes(modifiedModuleName)) {
139+
return ""
140+
}
141+
modulesCreated.push(modifiedModuleName);
142+
return [`/**`, ` * @module ${modifiedModuleName}`, ` */`].join('\n');
143+
}
144+
120145
/**
121146
* Convert a comment statement text to Js Doc Lines
122147
* This will return a string[] with each line of a block comment
@@ -134,13 +159,16 @@ function convertCommentTextToJsDocLines(comment) {
134159
// * Comment here
135160
commentLines.push(...comment.text.split('\n').map((line, i) => {
136161
return line.replace(bsMeaningfulCommentRegex, '$1');
137-
}).map(line => line.trim()).map((line, i, lines) => {
138-
if (i === 0) {
139-
line = line.replace(jsCommentStartRegex, '$1');
140-
}
141-
line = line.replace(/\**\/\s*/g, "")
142-
return " * " + line;
143-
}))
162+
}).map(line => line.trim())
163+
.filter((line) => {
164+
return !line.includes('@module')
165+
}).map((line, i, lines) => {
166+
if (i === 0) {
167+
line = line.replace(jsCommentStartRegex, '$1');
168+
}
169+
line = line.replace(/\**\/\s*/g, "")
170+
return " * " + line;
171+
}))
144172
}
145173
return commentLines
146174
}
@@ -333,7 +361,7 @@ function processClass(comment, klass, moduleName = "", namespaceName = "") {
333361
let parentClassName = "", extendsLine = ""
334362
if (klass.parentClassName) {
335363
parentClassName = klass.parentClassName.getName()
336-
extendsLine = ` * @extends ${klass.parentClassName.getName()} `
364+
extendsLine = ` * @extends ${klass.parentClassName.getName(bs.ParseMode.BrighterScript)} `
337365
}
338366

339367
for (var i = 0; i < commentLines.length; i++) {
@@ -371,6 +399,7 @@ function processClass(comment, klass, moduleName = "", namespaceName = "") {
371399

372400
output.push('}\n')
373401
if (namespaceName) {
402+
// output.push(...['/**', ' * @class', ' */']);
374403
output.push(`${namespaceName}.${klassName} = ${klassName}; `)
375404
}
376405
return output.join('\n')
@@ -389,32 +418,52 @@ function processClass(comment, klass, moduleName = "", namespaceName = "") {
389418
function processNamespace(comment, namespace, moduleName = "", parentNamespaceName) {
390419

391420
const output = [];
392-
let namespaceName = namespace.name;
393-
394-
if (parentNamespaceName) {
395-
namespaceName = parentNamespaceName + "." + namespaceName
421+
const namespaceParts = namespace.name.split('.');
422+
const namespaceNames = []
423+
let namespaceNameChain = ""
424+
for (const namespacePart of namespaceParts) {
425+
if (namespaceNameChain.length > 0) {
426+
namespaceNameChain += '.'
427+
}
428+
namespaceNameChain += namespacePart;
429+
namespaceNames.push(namespaceNameChain)
396430
}
397-
if (!namespacesCreated.includes(namespaceName)) {
398-
// have not created this namespace yet
399-
let commentLines = convertCommentTextToJsDocLines(comment);
400-
401-
// if (namespaceName !== moduleName) {
402-
commentLines.push(getMemberOf(moduleName, parentNamespaceName));
403-
// }
404-
commentLines.push(` * @namespace ${namespaceName} `)
405-
commentLines.push(' */');
406-
407-
output.push(commentLines.join('\n'));
431+
let index = 0
432+
let previousNamespace = ""
433+
for (const namespaceName of namespaceNames) {
434+
let subNamespace = namespaceName
408435
if (parentNamespaceName) {
409-
output.push(`${parentNamespaceName}.namespaceName = {}`)
436+
subNamespace = parentNamespaceName + "." + namespaceName
410437
}
411-
else {
412-
output.push(`var ${namespaceName} = {}; `);
438+
if (!namespacesCreated.includes(subNamespace)) {
439+
// have not created this namespace yet
440+
441+
output.push(getModuleLineComment(subNamespace));
442+
let commentLines = convertCommentTextToJsDocLines(comment);
443+
if (subNamespace != moduleName) {
444+
commentLines.push(getMemberOf(previousNamespace));
445+
}
446+
//commentLines.push(` * @namespace {object} ${subNamespace} `)
447+
commentLines.push(' */');
448+
449+
output.push(commentLines.join('\n'));
450+
/*
451+
if (parentNamespaceName || index > 0) {
452+
output.push(`${subNamespace} = {}`)
453+
}
454+
else {
455+
output.push(`var ${subNamespace} = {}; `);
456+
}*/
457+
namespacesCreated.push(subNamespace)
413458
}
414-
namespacesCreated.push(namespaceName)
459+
previousNamespace = subNamespace
460+
index++
415461
}
416-
417-
output.push(processStatements(namespace.body.statements, moduleName, namespaceName))
462+
let totalNamespace = namespace.name
463+
if (parentNamespaceName) {
464+
totalNamespace = parentNamespaceName + "." + totalNamespace
465+
}
466+
output.push(processStatements(namespace.body.statements, moduleName, totalNamespace))
418467
return output.join('\n');
419468
}
420469

@@ -472,19 +521,20 @@ exports.handlers = {
472521
const statements = parseResult.statements
473522

474523
// Add our module to the top of the file if it doesn't exist. If it does find out the name
475-
const moduleMatch = e.source.match(/@module ([^\*\s]+)/);
476-
let moduleName = "";
524+
const moduleMatch = e.source.match(moduleRegex);
477525
const output = [];
478-
if (moduleMatch) {
479-
moduleName = moduleMatch[1];
480-
} else {
481-
moduleName = path.parse(e.filename).name.replace(/\./g, '_');
526+
let moduleName = "";
527+
if (pluginOpts.addModule) {
528+
if (moduleMatch) {
529+
moduleName = moduleMatch[1];
530+
} else {
531+
moduleName = path.parse(e.filename).name.split('.')[0].replace(/\./g, '_');
532+
}
533+
output.push(getModuleLineComment(moduleName));
482534
}
483-
output.push(`/** @module ${moduleName} */`);
484-
485535
output.push(processStatements(statements, moduleName))
486536

487537
e.source = output.join('\n');
488-
//console.log(e.source)
538+
// console.log(e.source)
489539
}
490540
};

examples/source/DebugWindow.bs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
' @module BGE
2+
namespace BGE.Debug.Alpha.Beta
3+
4+
class DebugWindow extends BGE.UI.UiContainer
5+
6+
function new(game as BGE.Game) as void
7+
super(game)
8+
m.backgroundRGBA = BGE.RGBAtoRGBA(128, 128, 128, 0.5)
9+
m.padding.set(10)
10+
end function
11+
12+
13+
14+
15+
end class
16+
17+
end namespace

jsdoc.json

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,13 @@
77
"include": [
88
"examples"
99
],
10-
"includePattern": ".+\\.br?s$"
10+
"includePattern": ".+\\DebugWindow.br?s$"
1111
},
12+
"extendedConfig": {},
1213
"opts": {
1314
"recurse": true,
14-
"template": "node_modules/braintree-jsdoc-template"
15+
"readme": "README.md",
16+
"template": "node_modules/braintree-jsdoc-template",
17+
"brighterscript-jsdocs-plugin": {}
1518
}
1619
}

0 commit comments

Comments
 (0)