Skip to content

Commit d3fec49

Browse files
authored
Merge pull request #69 from webdoc-labs/feature/readonly
Feature: First-class readonly support
2 parents c9f4515 + 93dfca5 commit d3fec49

File tree

10 files changed

+56
-7
lines changed

10 files changed

+56
-7
lines changed

packages/webdoc-parser/src/symbols-babel/build-symbol-tree.js

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -186,7 +186,7 @@ export default function buildSymbolTree(
186186
let idoc;
187187

188188
try {
189-
idoc = captureSymbols(nodePath.node, scope);
189+
idoc = captureSymbols(nodePath, scope);
190190
} catch (e) {
191191
console.error(ancestorStack);
192192
console.log(node);
@@ -255,10 +255,11 @@ export default function buildSymbolTree(
255255
// them as a child of parent.
256256
//
257257
// The returned symbol is the one backed by the AST node.
258-
function captureSymbols(node: Node, parent: Symbol): ?Symbol {
258+
function captureSymbols(nodePath: NodePath, parent: Symbol): ?Symbol {
259+
const node = nodePath.node;
259260
const symbolInfo = {};
260261

261-
extractSymbol(node, parent, symbolInfo);
262+
extractSymbol(nodePath, parent, symbolInfo);
262263

263264
let {
264265
name: simpleName,

packages/webdoc-parser/src/symbols-babel/extract-symbol.js

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import {
88
type FunctionExpression,
99
type MemberExpression,
1010
type Node,
11+
type NodePath,
1112
type VariableDeclarator,
1213
isArrowFunctionExpression,
1314
isAssignmentExpression,
@@ -54,7 +55,7 @@ import {
5455
// + Set the appopriate flags
5556
// + Set isInit & initComment if the symbol has a initializer child
5657
export default function extractSymbol(
57-
node: Node,
58+
nodePath: NodePath,
5859
parent: Symbol,
5960
out: {
6061
name?: ?string,
@@ -65,6 +66,8 @@ export default function extractSymbol(
6566
init?: ?Node
6667
},
6768
): void {
69+
const node = nodePath.node;
70+
6871
let name;
6972
let flags = out.flags || 0;
7073
let isInit = false;
@@ -101,6 +104,7 @@ export default function extractSymbol(
101104
name = node.key.name;
102105

103106
nodeSymbol.meta.access = node.access || node.accessibility;
107+
nodeSymbol.meta.readonly = node.readonly;
104108
nodeSymbol.meta.dataType = extractType(node);
105109
nodeSymbol.meta.scope = node.static ? "static" : "instance";
106110
nodeSymbol.meta.type = "PropertyDoc";
@@ -173,6 +177,11 @@ export default function extractSymbol(
173177
} else if (isVariableDeclarator(node)) {
174178
name = node.id.name;
175179
init = resolveInit(node);
180+
181+
// Variables defined with the const keyword are inferred to be readonly.
182+
if (nodePath.parent && nodePath.parent.kind === "const") {
183+
nodeSymbol.meta.readonly = true;
184+
}
176185
} else {// ObjectProperty
177186
name = node.key.name;
178187
init = node.value;

packages/webdoc-parser/src/tag-parsers/index.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ export {
2020
parseTodo,
2121
parseThrows,
2222
parseType,
23+
parseReadonly,
2324
parseSee,
2425
parseSince,
2526
} from "./parseSimple";

packages/webdoc-parser/src/tag-parsers/parseSimple.js

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import type {
1111
ExampleTag,
1212
LicenseTag,
1313
NameTag,
14+
ReadonlyTag,
1415
SeeTag,
1516
SinceTag,
1617
ThrowsTag,
@@ -33,6 +34,8 @@ import {parseTypedDescription} from "./helper";
3334
// @todo <TODO>
3435
// @throws <ERROR_TYPE>
3536
// @type {TYPE}
37+
// @readonly
38+
// @readOnly
3639
// @see <URL | DOC_PATH>
3740
// @since <WHEN>
3841

@@ -153,6 +156,15 @@ export function parseType(value: string, doc: $Shape<{ dataType?: ?DataType }>):
153156
};
154157
}
155158

159+
export function parseReadonly(value: string, doc: $Shape<BaseDoc>): $Shape<ReadonlyTag> {
160+
doc.readonly = true;
161+
162+
return {
163+
value,
164+
type: "ReadonlyTag",
165+
};
166+
}
167+
156168
export function parseSee(value: string, doc: $Shape<BaseDoc>): $Shape<SeeTag> {
157169
if (!doc.see) {
158170
doc.see = [];

packages/webdoc-parser/src/transformer/symbol-to-doc.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ import {
3232
parseProperty,
3333
parseProtected,
3434
parsePublic,
35+
parseReadonly,
3536
parseReturn,
3637
parseScope,
3738
parseSee,
@@ -92,6 +93,8 @@ const TAG_PARSERS: { [id: string]: TagParser } = {
9293
"protected": parseProtected,
9394
"private": parsePrivate,
9495
"public": parsePublic,
96+
"readOnly": parseReadonly,
97+
"readonly": parseReadonly,
9598
"return": parseReturn,
9699
"returns": parseReturn, // alias @return
97100
"scope": parseScope,
@@ -135,6 +138,7 @@ export default function symbolToDoc(symbol: Symbol): ?Doc {
135138
options.access = symbol.meta.access;
136139
options.dataType = symbol.meta.dataType;
137140
options.defaultValue = symbol.meta.defaultValue;
141+
options.readonly = symbol.meta.readonly;
138142
options.scope = symbol.meta.scope;
139143
options.loc = symbol.loc;
140144

packages/webdoc-parser/src/types/Symbol.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ export type SymbolSignature = {
3030
implements?: ?Array<string | Symbol>,
3131
object?: ?string,
3232
params?: ?Array<$Shape<Param>>,
33+
readonly?: boolean,
3334
returns?: ?Array<$Shape<Return>>,
3435
scope?: ?string,
3536
value?: ?string,

packages/webdoc-parser/test/lang-js.js

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,4 +101,15 @@ describe("@webdoc/parser.LanguageIntegration{@lang js}", function() {
101101
expect(symbolClassName.members[0].simpleName).to.equal("constructor");
102102
expect(symbolClassName.members[0].members.length).to.equal(0);
103103
});
104+
105+
it("should mark const variable declarations as readonly", function() {
106+
const symtree = buildSymbolTree(`
107+
const variable = "value";
108+
let mutable = "mutable";
109+
`);
110+
111+
expect(symtree.members.length).to.equal(2);
112+
expect(symtree.members[0].meta.readonly).to.equal(true);
113+
expect(symtree.members[1].meta.readonly).to.not.equal(true);
114+
});
104115
});

packages/webdoc-parser/test/lang-ts.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,11 @@ describe("@webdoc/parser.LanguageIntegration{@lang ts}", function() {
88
it("should parse classes correctly", function() {
99
let symtree = buildSymbolTree(`
1010
class ClassName {
11-
private initProperty: number = 11;
11+
private readonly initProperty: number = 11;
1212
1313
constructor() {
1414
/**
1515
* This is a property whose data-type & access should be inferred.
16-
* @default 9
1716
*/
1817
this.initProperty = 9;
1918
}
@@ -50,6 +49,7 @@ describe("@webdoc/parser.LanguageIntegration{@lang ts}", function() {
5049
expect(symbolInitProperty.meta.access).to.equal("private");
5150
expect(symbolInitProperty.meta.defaultValue).to.equal(11);
5251
expect(symbolInitProperty.comment).to.not.equal("");
52+
expect(symbolInitProperty.meta.readonly).to.equal(true);
5353
});
5454

5555
it("should be able to parse type-casted objects for property symbols", function() {

packages/webdoc-parser/test/parse-ts.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ class Example {
1212
/**
1313
* Field description
1414
*/
15-
protected field: boolean = true;
15+
protected readonly field: boolean = true;
1616
}
1717
`,
1818
path: ".ts",
@@ -27,6 +27,7 @@ class Example {
2727
expect(fieldDoc.access).to.equal("protected");
2828
expect(fieldDoc.dataType && fieldDoc.dataType[0]).to.equal("boolean");
2929
expect(fieldDoc.defaultValue).to.equal(true);
30+
expect(fieldDoc.readonly).to.equal(true);
3031

3132
// TODO: Fix this. No space should be there (added/not-fixed b/c this was
3233
// in a PR for different issue)

packages/webdoc-types/index.js.flow

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ export type BaseDoc = {
7070
fires?: [],
7171
license?: string,
7272
loc?: SymbolLocation,
73+
readonly?: boolean,
7374
scope?: "static" | "instance" | "inner" | "default",
7475
see?: DocLink[],
7576
since?: string,
@@ -258,6 +259,7 @@ export type TagType =
258259
"NSTag" |
259260
"LicenseTag" |
260261
"ParamTag" |
262+
"ReadonlyTag" |
261263
"ReturnTag" |
262264
"SeeTag" |
263265
"SinceTag" |
@@ -286,6 +288,7 @@ export type Tag =
286288
NSTag |
287289
LicenseTag |
288290
ParamTag |
291+
ReadonlyTag |
289292
ReturnTag |
290293
SeeTag |
291294
SinceTag |
@@ -314,6 +317,7 @@ export type TagShape =
314317
$Shape<NSTag> |
315318
$Shape<LicenseTag> |
316319
$Shape<ParamTag> |
320+
$Shape<ReadonlyTag> |
317321
$Shape<ReturnTag> |
318322
$Shape<SeeTag> |
319323
$Shape<SinceTag> |
@@ -455,6 +459,11 @@ export type ParamTag = {
455459
type: "ParamTag"
456460
};
457461

462+
export type ReadonlyTag = {
463+
...BaseTag,
464+
type: "ReadonlyTag"
465+
};
466+
458467
export type ReturnTag = {
459468
...TypedTag,
460469
type: "ReturnTag"

0 commit comments

Comments
 (0)