Skip to content

Commit

Permalink
use pegjs
Browse files Browse the repository at this point in the history
  • Loading branch information
simonseyock committed Oct 4, 2019
1 parent ad56372 commit 3126a4a
Show file tree
Hide file tree
Showing 5 changed files with 268 additions and 20 deletions.
124 changes: 124 additions & 0 deletions builtin_types_peg_rules.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
BuiltinType
// primitives
= "number" &NoChar
/ "string" &NoChar
/ "boolean" &NoChar
/ "undefined" &NoChar
/ "null" &NoChar

// standard types
/ "Object" &NoChar
/ "Function" &NoChar
/ "Symbol" &NoChar
/ "Error" &NoChar
/ "EvalError" &NoChar
/ "InternalError" &NoChar
/ "RangeError" &NoChar
/ "ReferenceError" &NoChar
/ "SyntaxError" &NoChar
/ "TypeError" &NoChar
/ "URIError" &NoChar
/ "Date" &NoChar
/ "RegExp" &NoChar
/ "Array" &NoChar
/ "Int8Array" &NoChar
/ "Uint8Array" &NoChar
/ "Uint8ClampedArray" &NoChar
/ "Int16Array" &NoChar
/ "Uint16Array" &NoChar
/ "Int32Array" &NoChar
/ "Uint32Array" &NoChar
/ "Float32Array" &NoChar
/ "Float64Array" &NoChar
/ "BigInt64Array" &NoChar
/ "BigUint64Array" &NoChar
/ "Promise" &NoChar
/ "Generator" &NoChar
/ "GeneratorFunction" &NoChar
/ "AsyncFunction" &NoChar
/ "XMLHttpRequest" &NoChar
/ "ArrayBuffer" &NoChar
/ "SharedArrayBuffer" &NoChar
/ "Atomics" &NoChar
/ "DataView" &NoChar
/ "JSON" &NoChar
/ "Map" &NoChar
/ "Set" &NoChar
/ "WeakMap" &NoChar
/ "WeakSet" &NoChar
/ "Reflect" &NoChar
/ "Proxy" &NoChar

// Geolocation
/ "PositionError" &NoChar
/ "PositionOptions" &NoChar
/ "Position" &NoChar
/ "Geolocation" &NoChar

// DOM
/ "Attr" &NoChar
/ "CDATASection" &NoChar
/ "CharacterData" &NoChar
/ "ChildNode" &NoChar
/ "Comment" &NoChar
/ "CustomEvent" &NoChar
/ "Document" &NoChar
/ "DocumentFragment" &NoChar
/ "DocumentType" &NoChar
/ "DOMError" &NoChar
/ "DOMException" &NoChar
/ "DOMImplementation" &NoChar
/ "DOMString" &NoChar
/ "DOMTimeStamp" &NoChar
/ "DOMStringList" &NoChar
/ "DOMTokenList" &NoChar
/ "Element" &NoChar
/ "Event" &NoChar
/ "EventTarget" &NoChar
/ "HTMLCollection" &NoChar
/ "MutationObserver" &NoChar
/ "MutationRecord" &NoChar
/ "NamedNodeMap" &NoChar
/ "Node" &NoChar
/ "NodeFilter" &NoChar
/ "NodeIterator" &NoChar
/ "NodeList" &NoChar
/ "NonDocumentTypeChildNode" &NoChar
/ "ParentNode" &NoChar
/ "ProcessingInstruction" &NoChar
/ "Selection" &NoChar
/ "Range" &NoChar
/ "Text" &NoChar
/ "TextDecoder" &NoChar
/ "TextEncoder" &NoChar
/ "TimeRanges" &NoChar
/ "TreeWalker" &NoChar
/ "URL" &NoChar
/ "Window" &NoChar
/ "Worker" &NoChar
/ "XMLDocument" &NoChar

// HTML Types
/ "HTMLElement" &NoChar
/ "HTMLCanvasElement" &NoChar
/ "HTMLImageElement" &NoChar
/ "HTMLVideoElement" &NoChar

// PointerEvent
/ "PointerEvent" &NoChar

// TouchEvent
/ "TouchEvent" &NoChar

// MouseEvent
/ "MouseEvent" &NoChar

// TypeScript types
/ "*" &NoChar
// "?" will be catched by a special rule in type_rewrite_peg_rules
/ "any" &NoChar
/ "void" &NoChar
/ "Partial" &NoChar

// Other special types
/ "Class" &NoChar
49 changes: 29 additions & 20 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ const path = require('path');
const fs = require('fs');
const env = require('jsdoc/env');
const addInherited = require('jsdoc/augment').addInherited;
const peg = require("pegjs");

const config = env.conf.typescript;
if (!config) {
Expand All @@ -24,6 +25,28 @@ const slashRegEx = /\\/g;
const moduleInfos = {};
const fileNodes = {};

const pegRules = fs.readFileSync(path.join(__dirname, "./type_rewrite_peg_rules.txt"), 'utf8');
const pegBuiltinRules = fs.readFileSync(path.join(__dirname, "./builtin_types_peg_rules.txt"), 'utf8');

function buildTypeRewriteRules(identifiers, parser, currentSourceName) {
const keys = Object.keys(identifiers).sort().reverse();
let rules = 'RewriteType\n';
let first = true;
for (const key of keys) {
const identifier = identifiers[key];
const absolutePath = path.resolve(path.dirname(currentSourceName), identifier.value);
const moduleId = path.relative(path.join(process.cwd(), moduleRoot), absolutePath).replace(/\.js$/, '');
if (getModuleInfo(moduleId, parser)) {
const exportName = identifier.defaultImport ? getDefaultExportName(moduleId, parser) : key;
const delimiter = identifier.defaultImport ? '~' : getDelimiter(moduleId, exportName, parser);
const replacement = `module:${moduleId.replace(slashRegEx, '/')}${exportName ? delimiter + exportName : ''}`;
rules += ` ${first ? '=' : '/'} "${key}" &NoChar { return "${replacement}" }\n`;
first = false;
}
}
return pegRules + '\n' + pegBuiltinRules + '\n' + rules;
}

function getModuleInfo(moduleId, parser) {
if (!moduleInfos[moduleId]) {
const moduleInfo = moduleInfos[moduleId] = {
Expand Down Expand Up @@ -198,30 +221,16 @@ exports.astNodeVisitor = {
}
});

node.comments.forEach(comment => {
if (Object.keys(identifiers).length > 0) {
// Replace local types with the full `module:` path
Object.keys(identifiers).forEach(key => {
const eventRegex = new RegExp(`@(event |fires )${key}(\\s*)`, 'g');
replace(eventRegex);

const typeRegex = new RegExp(`@(.*[{<|,]\\s*[!?]?)${key}(=?\\s*[}>|,])`, 'g');
replace(typeRegex);
const rules = buildTypeRewriteRules(identifiers, parser, currentSourceName);
const rewriter = peg.generate(rules);

function replace(regex) {
if (regex.test(comment.value)) {
const identifier = identifiers[key];
const absolutePath = path.resolve(path.dirname(currentSourceName), identifier.value);
const moduleId = path.relative(path.join(process.cwd(), moduleRoot), absolutePath).replace(/\.js$/, '');
if (getModuleInfo(moduleId, parser)) {
const exportName = identifier.defaultImport ? getDefaultExportName(moduleId, parser) : key;
const delimiter = identifier.defaultImport ? '~' : getDelimiter(moduleId, exportName, parser);
let replacement = `module:${moduleId.replace(slashRegEx, '/')}${exportName ? delimiter + exportName : ''}`;
comment.value = comment.value.replace(regex, '@$1' + replacement + '$2');
}
}
}
node.comments.forEach(comment => {
comment.value = rewriter.parse(comment.value);
});
});
}
}
}
}
Expand Down
13 changes: 13 additions & 0 deletions package-lock.json

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

3 changes: 3 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,5 +17,8 @@
"repository": {
"type": "git",
"url": "git://github.com/openlayers/jsdoc-plugin-typescript.git"
},
"dependencies": {
"pegjs": "^0.10.0"
}
}
99 changes: 99 additions & 0 deletions type_rewrite_peg_rules.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
{
function flatten(input) {
return Array.isArray(input) ? input.map(i => flatten(i)).join("") : input;
}
}

All
= all: Lines { return flatten(all); }

Lines
= Line "\n" Lines
/ Line

Line
= _ "*" _ TypeExpecting _ ComplexType ("#" [^\n\r]*)?
/ _ "*" _ CurlyTypeExpecting _ CurlyType [^\n\r]*
/ _ "*" _ !TypeExpecting !CurlyTypeExpecting [^\n\r]*
/ _ [^\n\r]* [^*\n\r]*

CurlyTypeExpecting
= "@param"
/ "@property"
/ "@return" "s"?
/ "@typedef"
/ "@type"
/ "@this"
/ "@enum"

TypeExpecting
= "@fires"
/ "@event"

CurlyType
= "{" _ TypeList _ "}"

TypeList
= ComplexType _b "|" _b TypeList
/ ComplexType

ComplexType
= [?!]? ComplexTypeUnmodified "="?
/ "?" // short curcuit for the builtin type "?"

ComplexTypeUnmodified
= "(" _ TypeList _ ")"
/ Spread
/ GenericType
/ FunctionType
/ SimpleType
/ InlineObjectType

InlineObjectType
= "{" _b InlineObjectPropertyList _b "}"

InlineObjectPropertyList
= InlineObjectProperty _ "," _b InlineObjectPropertyList
/ InlineObjectProperty

InlineObjectProperty
= [A-Za-z][A-Za-z0-9_]* _ ":" _b ComplexType

Spread
= "..." ComplexType

FunctionType
= "function" _ "(" _ (FunctionThis? _b ParameterList)? ")" (":" _b ComplexType)?

FunctionThis
= "this:"
/ "new:"

SimpleType
= RewriteType
/ BuiltinType
/ ConvertedType
/ GenericParameter

NoChar
= [^A-Za-z0-9_]

GenericType
= SimpleType "."? "<" ParameterList ">"

ParameterList
= TypeList "," _b ParameterList
/ TypeList

ConvertedType
= "module:" [a-zA-Z/]+ (("~" / ".") [a-zA-Z]+)? &NoChar

GenericParameter
= [A-Z] &NoChar

_b "break or whitespace"
= _ "\n" _ "*" _
/ _

_ "whitespace"
= [ \t]*

0 comments on commit 3126a4a

Please sign in to comment.