Skip to content

Commit

Permalink
Better handles modules and namespaces, so namespaces can have multipl…
Browse files Browse the repository at this point in the history
…e levels, and classes are put in the correct modules
  • Loading branch information
markwpearce committed Sep 9, 2021
1 parent eeacca4 commit 03ec477
Show file tree
Hide file tree
Showing 7 changed files with 342 additions and 2,299 deletions.
2 changes: 1 addition & 1 deletion .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
"program": "${workspaceFolder}/node_modules/.bin/jsdoc",
"request": "launch",
"cwd": "${workspaceFolder}",
"args": ["-c", "jsdoc.json", "-t", "node_modules/minami", "-d", "docs"],
"args": ["-c", "jsdoc.json", "-d", "docs"],
"skipFiles": ["<node_internals>/**"],
"type": "node",
"sourceMaps": true
Expand Down
22 changes: 18 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,25 +50,39 @@ Example:
"includePattern": ".+\\.br?s$"
},
"opts": {
"recurse": true
"recurse": true,
"template": "node_modules/clean-jsdoc-theme", // or whatever template you've chosen - see below
"brighterscript-jsdocs-plugin": {
"addModule": true // true by default - should we generate module names based on the file names?
}
}
}
```

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.

3. Add a script to `package.json` like:

```json
"scripts": {
"docs": "./node_modules/.bin/jsdoc -c jsdoc.json -d docs -t ./node_modules/braintree-jsdoc-template"
"docs": "./node_modules/.bin/jsdoc -c jsdoc.json -d docs"
}
```

# Generating Documentation

Run the script to generate documentation! (Documentation is put in the `./docs/` folder)

```
npm run docs
```

# Templates

The default JSDocs template may not meet your needs. Here's a good list of templates that are available:

https://cancerberosgx.github.io/jsdoc-templates-demo/demo/

# Brightscript and Brighterscript

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.
Expand All @@ -83,7 +97,7 @@ It is not necessary to wrap BrightScript comments in javascript style comments,

These comments will be parsed the same:

```bs
```
' Give the maximum of two numbers
' @param {integer} x - the first number
' @param {integer} y - the second number
Expand Down Expand Up @@ -111,7 +125,7 @@ end function

## Example

```bs
```
' Namespace for testing
namespace TestBsDoc
Expand Down
134 changes: 92 additions & 42 deletions convert-brighterscript-docs.js
Original file line number Diff line number Diff line change
@@ -1,16 +1,27 @@
'use strict';
const bs = require('brighterscript');
const path = require('path');

const jsCommentStartRegex = /^[\s]*(?:\/\*+)?[\s]*(.*)/g
const bsMeaningfulCommentRegex = /^[\s]*(?:'|REM)[\s]*\**[\s]*(.*)/g
const paramRegex = /@param\s+(?:{([^}]*)})?\s+(?:\[(\w+).*\]|(\w+))[\s-\s|\s]*(.*)/
const returnRegex = /@returns?\s*({(?:[^}]*)})?\s*(.*)/
const extendsRegex = /@extends/
const moduleRegex = /@module ([^\*\s]+)/
const opts = env && env.opts || {}
const pluginOpts = opts['brighterscript-jsdocs-plugin'] || {};

if (pluginOpts.addModule === undefined || pluginOpts.addModule === null) {
pluginOpts.addModule = true
}



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

/** @type {string[]} */
const modulesCreated = []

/** @type {string[]} */
let parserLines = []

Expand Down Expand Up @@ -109,14 +120,28 @@ function getCommentForStatement(comments, stmt) {
}

function getMemberOf(moduleName = "", namespaceName = "") {
const memberOf = namespaceName || moduleName;

const memberOf = namespaceName || moduleName.replace(/\./g, '/');
const memberType = /*namespaceName ? "" : */ "module:"
if (memberOf) {
return (` * @memberof module:${memberOf}`);
return ` * @memberof! ${memberType}${memberOf.replace(/\./g, '/')}`;
}
return ""
}

/**
*
* @param {string} moduleName
* @returns
*/
function getModuleLineComment(moduleName = "") {
const modifiedModuleName = moduleName.replace(/\./g, '/')
if (!modifiedModuleName || modulesCreated.includes(modifiedModuleName)) {
return ""
}
modulesCreated.push(modifiedModuleName);
return [`/**`, ` * @module ${modifiedModuleName}`, ` */`].join('\n');
}

/**
* Convert a comment statement text to Js Doc Lines
* This will return a string[] with each line of a block comment
Expand All @@ -134,13 +159,16 @@ function convertCommentTextToJsDocLines(comment) {
// * Comment here
commentLines.push(...comment.text.split('\n').map((line, i) => {
return line.replace(bsMeaningfulCommentRegex, '$1');
}).map(line => line.trim()).map((line, i, lines) => {
if (i === 0) {
line = line.replace(jsCommentStartRegex, '$1');
}
line = line.replace(/\**\/\s*/g, "")
return " * " + line;
}))
}).map(line => line.trim())
.filter((line) => {
return !line.includes('@module')
}).map((line, i, lines) => {
if (i === 0) {
line = line.replace(jsCommentStartRegex, '$1');
}
line = line.replace(/\**\/\s*/g, "")
return " * " + line;
}))
}
return commentLines
}
Expand Down Expand Up @@ -333,7 +361,7 @@ function processClass(comment, klass, moduleName = "", namespaceName = "") {
let parentClassName = "", extendsLine = ""
if (klass.parentClassName) {
parentClassName = klass.parentClassName.getName()
extendsLine = ` * @extends ${klass.parentClassName.getName()} `
extendsLine = ` * @extends ${klass.parentClassName.getName(bs.ParseMode.BrighterScript)} `
}

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

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

const output = [];
let namespaceName = namespace.name;

if (parentNamespaceName) {
namespaceName = parentNamespaceName + "." + namespaceName
const namespaceParts = namespace.name.split('.');
const namespaceNames = []
let namespaceNameChain = ""
for (const namespacePart of namespaceParts) {
if (namespaceNameChain.length > 0) {
namespaceNameChain += '.'
}
namespaceNameChain += namespacePart;
namespaceNames.push(namespaceNameChain)
}
if (!namespacesCreated.includes(namespaceName)) {
// have not created this namespace yet
let commentLines = convertCommentTextToJsDocLines(comment);

// if (namespaceName !== moduleName) {
commentLines.push(getMemberOf(moduleName, parentNamespaceName));
// }
commentLines.push(` * @namespace ${namespaceName} `)
commentLines.push(' */');

output.push(commentLines.join('\n'));
let index = 0
let previousNamespace = ""
for (const namespaceName of namespaceNames) {
let subNamespace = namespaceName
if (parentNamespaceName) {
output.push(`${parentNamespaceName}.namespaceName = {}`)
subNamespace = parentNamespaceName + "." + namespaceName
}
else {
output.push(`var ${namespaceName} = {}; `);
if (!namespacesCreated.includes(subNamespace)) {
// have not created this namespace yet

output.push(getModuleLineComment(subNamespace));
let commentLines = convertCommentTextToJsDocLines(comment);
if (subNamespace != moduleName) {
commentLines.push(getMemberOf(previousNamespace));
}
//commentLines.push(` * @namespace {object} ${subNamespace} `)
commentLines.push(' */');

output.push(commentLines.join('\n'));
/*
if (parentNamespaceName || index > 0) {
output.push(`${subNamespace} = {}`)
}
else {
output.push(`var ${subNamespace} = {}; `);
}*/
namespacesCreated.push(subNamespace)
}
namespacesCreated.push(namespaceName)
previousNamespace = subNamespace
index++
}

output.push(processStatements(namespace.body.statements, moduleName, namespaceName))
let totalNamespace = namespace.name
if (parentNamespaceName) {
totalNamespace = parentNamespaceName + "." + totalNamespace
}
output.push(processStatements(namespace.body.statements, moduleName, totalNamespace))
return output.join('\n');
}

Expand Down Expand Up @@ -472,19 +521,20 @@ exports.handlers = {
const statements = parseResult.statements

// Add our module to the top of the file if it doesn't exist. If it does find out the name
const moduleMatch = e.source.match(/@module ([^\*\s]+)/);
let moduleName = "";
const moduleMatch = e.source.match(moduleRegex);
const output = [];
if (moduleMatch) {
moduleName = moduleMatch[1];
} else {
moduleName = path.parse(e.filename).name.replace(/\./g, '_');
let moduleName = "";
if (pluginOpts.addModule) {
if (moduleMatch) {
moduleName = moduleMatch[1];
} else {
moduleName = path.parse(e.filename).name.split('.')[0].replace(/\./g, '_');
}
output.push(getModuleLineComment(moduleName));
}
output.push(`/** @module ${moduleName} */`);

output.push(processStatements(statements, moduleName))

e.source = output.join('\n');
//console.log(e.source)
// console.log(e.source)
}
};
17 changes: 17 additions & 0 deletions examples/source/DebugWindow.bs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
' @module BGE
namespace BGE.Debug.Alpha.Beta

class DebugWindow extends BGE.UI.UiContainer

function new(game as BGE.Game) as void
super(game)
m.backgroundRGBA = BGE.RGBAtoRGBA(128, 128, 128, 0.5)
m.padding.set(10)
end function




end class

end namespace
7 changes: 5 additions & 2 deletions jsdoc.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,13 @@
"include": [
"examples"
],
"includePattern": ".+\\.br?s$"
"includePattern": ".+\\DebugWindow.br?s$"
},
"extendedConfig": {},
"opts": {
"recurse": true,
"template": "node_modules/braintree-jsdoc-template"
"readme": "README.md",
"template": "node_modules/braintree-jsdoc-template",
"brighterscript-jsdocs-plugin": {}
}
}
Loading

0 comments on commit 03ec477

Please sign in to comment.