Skip to content

Commit 9bda568

Browse files
committed
Merge pull request #453 from arv/class-property
Infer class properties
2 parents 305a3aa + e13e5d7 commit 9bda568

File tree

8 files changed

+309
-294
lines changed

8 files changed

+309
-294
lines changed

lib/infer/kind.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,8 @@ module.exports = function () {
4848
} else if (t.isExpressionStatement(path)) {
4949
// module.exports = function() {}
5050
findKind(path.node.expression.right);
51+
} else if (t.isClassProperty(path)) {
52+
comment.kind = 'member';
5153
} else if (t.isProperty(path)) {
5254
// { foo: function() {} }
5355
findKind(path.node.value);

lib/infer/membership.js

Lines changed: 11 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -170,7 +170,7 @@ module.exports = function () {
170170
/*
171171
* Same as above but for `b: c` vs `b: function () {}`.
172172
*/
173-
if (n.isProperty(path.node) &&
173+
if (n.isObjectProperty(path.node) &&
174174
n.isIdentifier(path.node.key)) {
175175
path = path.get('key');
176176
}
@@ -221,23 +221,18 @@ module.exports = function () {
221221
}
222222

223223
// class Foo { bar() { } }
224-
if (n.isClassMethod(path) &&
225-
n.isClassBody(path.parentPath) &&
226-
n.isClassDeclaration(path.parentPath.parentPath)) {
227-
identifiers = [path.parentPath.parentPath.node.id.name];
228-
var scope = 'instance';
229-
if (path.node.static == true) {
230-
scope = 'static';
231-
}
232-
inferMembershipFromIdentifiers(comment, identifiers, scope);
233-
}
234-
235224
// var Foo = class { bar() { } }
236-
if (n.isClassMethod(path) &&
225+
// class Foo { prop: T }
226+
// var Foo = class { prop: T }
227+
if ((n.isClassMethod(path) || n.isClassProperty(path)) &&
237228
n.isClassBody(path.parentPath) &&
238-
n.isClassExpression(path.parentPath.parentPath)) {
239-
identifiers = extractIdentifiers(path.parentPath.parentPath.parentPath.get('left'));
240-
scope = 'instance';
229+
n.isClass(path.parentPath.parentPath)) {
230+
if (n.isExpression(path.parentPath.parentPath)) {
231+
identifiers = extractIdentifiers(path.parentPath.parentPath.parentPath.get('left'));
232+
} else {
233+
identifiers = [path.parentPath.parentPath.node.id.name];
234+
}
235+
var scope = 'instance';
241236
if (path.node.static == true) {
242237
scope = 'static';
243238
}

test/fixture/es6-import.output.json

Lines changed: 99 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -839,6 +839,105 @@
839839
"kind": "class",
840840
"members": {
841841
"instance": [
842+
{
843+
"description": {
844+
"type": "root",
845+
"children": [
846+
{
847+
"type": "paragraph",
848+
"children": [
849+
{
850+
"type": "text",
851+
"value": "This is a property of the sink.",
852+
"position": {
853+
"start": {
854+
"line": 1,
855+
"column": 1,
856+
"offset": 0
857+
},
858+
"end": {
859+
"line": 1,
860+
"column": 32,
861+
"offset": 31
862+
},
863+
"indent": []
864+
}
865+
}
866+
],
867+
"position": {
868+
"start": {
869+
"line": 1,
870+
"column": 1,
871+
"offset": 0
872+
},
873+
"end": {
874+
"line": 1,
875+
"column": 32,
876+
"offset": 31
877+
},
878+
"indent": []
879+
}
880+
}
881+
],
882+
"position": {
883+
"start": {
884+
"line": 1,
885+
"column": 1,
886+
"offset": 0
887+
},
888+
"end": {
889+
"line": 1,
890+
"column": 32,
891+
"offset": 31
892+
}
893+
}
894+
},
895+
"tags": [],
896+
"loc": {
897+
"start": {
898+
"line": 24,
899+
"column": 2
900+
},
901+
"end": {
902+
"line": 26,
903+
"column": 5
904+
}
905+
},
906+
"context": {
907+
"loc": {
908+
"start": {
909+
"line": 27,
910+
"column": 2
911+
},
912+
"end": {
913+
"line": 27,
914+
"column": 18
915+
}
916+
},
917+
"code": "/**\n * This function destructures with defaults.\n */\nfunction destructure({phoneNumbers = [], emailAddresses = [], ...params} = {}) {\n}\n\n/**\n * Similar, but with an array\n */\nfunction destructure([a, b, c]) {\n}\n\n/**\n * This function returns the number one.\n * @param {Array<Number>} a an array of numbers\n * @returns {Number} numberone\n */\nvar multiply = (a, b) => a * b;\n\n/**\n * This is a sink\n */\nclass Sink {\n /**\n * This is a property of the sink.\n */\n staticProp = 42;\n\n /**\n * Is it empty\n */\n empty() {\n return 1;\n }\n\n /**\n * This method says hello\n */\n static hello() {\n return 'hello';\n }\n\n /**\n * This is a getter method: it should be documented\n * as a property.\n */\n get aGetter() {\n return 42;\n }\n\n /**\n * @param {number} height the height of the thing\n * @param {number} width the width of the thing\n */\n constructor(height, width) {\n this.height = height;\n this.width = width;\n }\n}\n\n/**\n * This function takes rest params\n */\nfunction functionWithRest(...someParams) {\n}\n\n/**\n * So does this one, with types\n */\nfunction functionWithRestAndType(...someParams: number) {\n}\n\n// FUNCTION TYPES\n\n/**\n * This is an async method\n */\nasync function foo() { }\n\nexport default multiply;\n\n/**\n * @public\n */\nexport default (thisIsTheArgument) => {};\n\n/**\n * This function returns the number one.\n * @returns {Number} numberone\n */\nmodule.exports = () => (<p>hello</p>);\n\n/**\n * This tests our support of optional parameters in ES6\n */\nfunction veryImportantTransform(foo = 'bar') {\n return \"42\";\n}\n\n// ACCESS LEVELS\n\n/**\n * A private function\n * @private\n */\nfunction iAmPrivate() { }\n\n/**\n * A protected function\n * @protected\n */\nfunction iAmProtected() { }\n\n/**\n * A public function\n * @public\n */\nfunction iAmPublic() { }\n\n/**\n * A private function using the access tag\n * @access private\n */\nfunction iAmAccessPrivate() { }\n\n/**\n * This is re-exported\n */\nexport { execute } from 'external-module';\n"
918+
},
919+
"errors": [],
920+
"name": "staticProp",
921+
"kind": "member",
922+
"memberof": "Sink",
923+
"scope": "instance",
924+
"members": {
925+
"instance": [],
926+
"static": []
927+
},
928+
"path": [
929+
{
930+
"name": "Sink",
931+
"kind": "class"
932+
},
933+
{
934+
"name": "staticProp",
935+
"kind": "member",
936+
"scope": "instance"
937+
}
938+
],
939+
"namespace": "Sink#staticProp"
940+
},
842941
{
843942
"description": {
844943
"type": "root",
@@ -1344,96 +1443,6 @@
13441443
],
13451444
"namespace": "Sink"
13461445
},
1347-
{
1348-
"description": {
1349-
"type": "root",
1350-
"children": [
1351-
{
1352-
"type": "paragraph",
1353-
"children": [
1354-
{
1355-
"type": "text",
1356-
"value": "This is a property of the sink.",
1357-
"position": {
1358-
"start": {
1359-
"line": 1,
1360-
"column": 1,
1361-
"offset": 0
1362-
},
1363-
"end": {
1364-
"line": 1,
1365-
"column": 32,
1366-
"offset": 31
1367-
},
1368-
"indent": []
1369-
}
1370-
}
1371-
],
1372-
"position": {
1373-
"start": {
1374-
"line": 1,
1375-
"column": 1,
1376-
"offset": 0
1377-
},
1378-
"end": {
1379-
"line": 1,
1380-
"column": 32,
1381-
"offset": 31
1382-
},
1383-
"indent": []
1384-
}
1385-
}
1386-
],
1387-
"position": {
1388-
"start": {
1389-
"line": 1,
1390-
"column": 1,
1391-
"offset": 0
1392-
},
1393-
"end": {
1394-
"line": 1,
1395-
"column": 32,
1396-
"offset": 31
1397-
}
1398-
}
1399-
},
1400-
"tags": [],
1401-
"loc": {
1402-
"start": {
1403-
"line": 24,
1404-
"column": 2
1405-
},
1406-
"end": {
1407-
"line": 26,
1408-
"column": 5
1409-
}
1410-
},
1411-
"context": {
1412-
"loc": {
1413-
"start": {
1414-
"line": 27,
1415-
"column": 2
1416-
},
1417-
"end": {
1418-
"line": 27,
1419-
"column": 18
1420-
}
1421-
},
1422-
"code": "/**\n * This function destructures with defaults.\n */\nfunction destructure({phoneNumbers = [], emailAddresses = [], ...params} = {}) {\n}\n\n/**\n * Similar, but with an array\n */\nfunction destructure([a, b, c]) {\n}\n\n/**\n * This function returns the number one.\n * @param {Array<Number>} a an array of numbers\n * @returns {Number} numberone\n */\nvar multiply = (a, b) => a * b;\n\n/**\n * This is a sink\n */\nclass Sink {\n /**\n * This is a property of the sink.\n */\n staticProp = 42;\n\n /**\n * Is it empty\n */\n empty() {\n return 1;\n }\n\n /**\n * This method says hello\n */\n static hello() {\n return 'hello';\n }\n\n /**\n * This is a getter method: it should be documented\n * as a property.\n */\n get aGetter() {\n return 42;\n }\n\n /**\n * @param {number} height the height of the thing\n * @param {number} width the width of the thing\n */\n constructor(height, width) {\n this.height = height;\n this.width = width;\n }\n}\n\n/**\n * This function takes rest params\n */\nfunction functionWithRest(...someParams) {\n}\n\n/**\n * So does this one, with types\n */\nfunction functionWithRestAndType(...someParams: number) {\n}\n\n// FUNCTION TYPES\n\n/**\n * This is an async method\n */\nasync function foo() { }\n\nexport default multiply;\n\n/**\n * @public\n */\nexport default (thisIsTheArgument) => {};\n\n/**\n * This function returns the number one.\n * @returns {Number} numberone\n */\nmodule.exports = () => (<p>hello</p>);\n\n/**\n * This tests our support of optional parameters in ES6\n */\nfunction veryImportantTransform(foo = 'bar') {\n return \"42\";\n}\n\n// ACCESS LEVELS\n\n/**\n * A private function\n * @private\n */\nfunction iAmPrivate() { }\n\n/**\n * A protected function\n * @protected\n */\nfunction iAmProtected() { }\n\n/**\n * A public function\n * @public\n */\nfunction iAmPublic() { }\n\n/**\n * A private function using the access tag\n * @access private\n */\nfunction iAmAccessPrivate() { }\n\n/**\n * This is re-exported\n */\nexport { execute } from 'external-module';\n"
1423-
},
1424-
"errors": [],
1425-
"name": "staticProp",
1426-
"members": {
1427-
"instance": [],
1428-
"static": []
1429-
},
1430-
"path": [
1431-
{
1432-
"name": "staticProp"
1433-
}
1434-
],
1435-
"namespace": "staticProp"
1436-
},
14371446
{
14381447
"description": {
14391448
"type": "root",

test/fixture/es6-import.output.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,10 @@ Returns **[Number](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Refer
4949

5050
This is a sink
5151

52+
## staticProp
53+
54+
This is a property of the sink.
55+
5256
## empty
5357

5458
Is it empty
@@ -69,10 +73,6 @@ as a property.
6973

7074
This method says hello
7175

72-
# staticProp
73-
74-
This is a property of the sink.
75-
7676
# functionWithRest
7777

7878
This function takes rest params

test/fixture/es6-import.output.md.json

Lines changed: 45 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -875,6 +875,51 @@
875875
"indent": []
876876
}
877877
},
878+
{
879+
"depth": 2,
880+
"type": "heading",
881+
"children": [
882+
{
883+
"type": "text",
884+
"value": "staticProp"
885+
}
886+
]
887+
},
888+
{
889+
"type": "paragraph",
890+
"children": [
891+
{
892+
"type": "text",
893+
"value": "This is a property of the sink.",
894+
"position": {
895+
"start": {
896+
"line": 1,
897+
"column": 1,
898+
"offset": 0
899+
},
900+
"end": {
901+
"line": 1,
902+
"column": 32,
903+
"offset": 31
904+
},
905+
"indent": []
906+
}
907+
}
908+
],
909+
"position": {
910+
"start": {
911+
"line": 1,
912+
"column": 1,
913+
"offset": 0
914+
},
915+
"end": {
916+
"line": 1,
917+
"column": 32,
918+
"offset": 31
919+
},
920+
"indent": []
921+
}
922+
},
878923
{
879924
"depth": 2,
880925
"type": "heading",
@@ -1185,51 +1230,6 @@
11851230
"indent": []
11861231
}
11871232
},
1188-
{
1189-
"depth": 1,
1190-
"type": "heading",
1191-
"children": [
1192-
{
1193-
"type": "text",
1194-
"value": "staticProp"
1195-
}
1196-
]
1197-
},
1198-
{
1199-
"type": "paragraph",
1200-
"children": [
1201-
{
1202-
"type": "text",
1203-
"value": "This is a property of the sink.",
1204-
"position": {
1205-
"start": {
1206-
"line": 1,
1207-
"column": 1,
1208-
"offset": 0
1209-
},
1210-
"end": {
1211-
"line": 1,
1212-
"column": 32,
1213-
"offset": 31
1214-
},
1215-
"indent": []
1216-
}
1217-
}
1218-
],
1219-
"position": {
1220-
"start": {
1221-
"line": 1,
1222-
"column": 1,
1223-
"offset": 0
1224-
},
1225-
"end": {
1226-
"line": 1,
1227-
"column": 32,
1228-
"offset": 31
1229-
},
1230-
"indent": []
1231-
}
1232-
},
12331233
{
12341234
"depth": 1,
12351235
"type": "heading",

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy