diff --git a/demos/outline.html b/demos/outline.html index 114287d..8838b7e 100644 --- a/demos/outline.html +++ b/demos/outline.html @@ -66,13 +66,13 @@

Demo with Outline Tern plugin

- diff --git a/outline.js b/outline.js index c450da9..f40c13a 100644 --- a/outline.js +++ b/outline.js @@ -74,8 +74,7 @@ });*/ }); - function getChild(parent, name) { - var children = parent.children; + function getChild(name, children) { if (!children) return null; for (var i = 0; i < children.length; i++) { var child = children[i]; @@ -83,21 +82,15 @@ } } - function fillTypes(type, parent, excludeTypes) { - if (!type) return; - excludeTypes.push(type); - infer.forAllPropertiesOf(type, function(prop, obj, depth) { - if (depth > 0) return; - var t = obj && obj.props[prop]; - if (t && t.originNode && t.originNode.type != "ClassDeclaration" && excludeTypes.indexOf(t) == -1) { - excludeTypes.push(t); - var child = getChild(parent, prop); - if (!child) { - child = addChildNode(t.originNode, t, parent); - } - fillTypes(t, child, excludeTypes); + function getChildProperty(node, parent) { + if (node.property) { + var p = getChild(node.object.name, parent) + if (p) { + return getChildProperty(node.property, p.children) } - }) + } else if (node.name) { + return getChild(node.name, parent); + } } function addAnonymousFn(node, type, parent) { @@ -126,10 +119,12 @@ }, AssignmentExpression: function (node, st, c) { var parent = st.parent, scope = st.scope; - if(node.left && node.left.object && node.left.object.type == "ThisExpression") { - var parent = st.parent, scope = st.scope; + if(node.left && node.left.object/* && node.left.object.type == "ThisExpression"*/) { + var left = node.left.property ? node.left.property : node.left.object; + var p = getChildProperty(node.left.property ? node.left.object : node.left, parent); + var parent = p ? p: parent, scope = st.scope; var type = infer.expressionType({node: node.left, state: scope}); - var child = addChildNode(node.left, type, parent); + var child = addChildNode(left, type, parent); st = {parent: child, scope: scope}; } c(node.left, st, "Pattern"); @@ -145,20 +140,21 @@ } } else { var parentNode = infer.parentNode(node, node.sourceFile.ast); - if (!parentNode || (parentNode.type != "Property" && parentNode.type != "VariableDeclarator" && parentNode.type != "MethodDefinition" && parentNode.type != "AssignmentExpression")) parent = addAnonymousFn(node, type, parent); + if (!parentNode || (parentNode.type != "Property" && parentNode.type != "VariableDeclarator" && parentNode.type != "MethodDefinition" && parentNode.type != "AssignmentExpression")) { + parent = addAnonymousFn(node, type, parent); + } } var scope = {parent: parent, scope: node.body.scope ? node.body.scope: node.scope}; if (node.id) c(node.id, scope); for (var i = 0; i < node.params.length; ++i) c(node.params[i], scope); c(node.body, scope, "ScopeBody"); - fillTypes(type, parent, []); }, Property: function (node, st, c) { var parent = st.parent, scope = st.scope; var type = node.value && node.value.name != "✖" ? infer.expressionType({node: node.value, state: scope}) : null; parent = addChildNode(node.key, type, parent); - var scope = {parent: parent, scope: node.scope}; + var scope = {parent: parent, scope: scope}; if (node.computed) c(node.key, scope, "Expression"); c(node.value, scope, "Expression"); }, @@ -168,7 +164,7 @@ }, ClassDeclaration: function (node, st, c) { var parent = st.parent, scope = st.scope, type = infer.expressionType({node: node.id ? node.id : node, state: scope}); - var obj = addChildNode(node, type, parent); + var obj = addChildNode(node.id ? node.id : node, type, parent); obj.kind = "class"; var scope = {parent: obj, scope: st.scope}; if (node.superClass) c(node.superClass, scope, "Expression"); diff --git a/test/class_declaration.js b/test/class_declaration.js index 4970706..938e31d 100644 --- a/test/class_declaration.js +++ b/test/class_declaration.js @@ -9,9 +9,9 @@ exports['test simple class declaration'] = function() { "}"+ "}", {"outline": - [{"name":"Cat","type":"fn(name: ?)","start":0,"end":103,"kind":"class", + [{"name":"Cat","type":"fn(name: ?)","start":6,"end":9,"kind":"class", "children":[{"name":"constructor","type":"fn(name: ?)","start":12,"end":23,"kind":"constructor", - "children":[{"name":"name","type":"?","start":31,"end":40}]}, + "children":[{"name":"name","type":"?","start":36,"end":40}]}, {"name":"speak","type":"fn()","start":49,"end":54,"kind":"method"} ]} ]}); diff --git a/test/function_declaration.js b/test/function_declaration.js index fc09ea8..9bd5519 100644 --- a/test/function_declaration.js +++ b/test/function_declaration.js @@ -87,7 +87,7 @@ exports['test all function case'] = function() { [ {"name":"g","type":"fn()","start":9,"end":10,"children": [ - {"name":"f","type":"?","start":14,"end":20,"children": + {"name":"f","type":"?","start":19,"end":20,"children": [ {"name":"i","type":"number","start":40,"end":41} ] @@ -113,7 +113,7 @@ exports['test all function case'] = function() { util.assertOutline("class c {f() {var i=0;}}", {"outline": [ - {"name":"c","type":"fn()","start":0,"end":24,"kind": "class", "children": + {"name":"c","type":"fn()","start":6,"end":7,"kind": "class", "children": [ {"name":"f","type":"fn()","start":9,"end":10,"kind": "method", "children": [ @@ -126,4 +126,19 @@ exports['test all function case'] = function() { }); } +exports['test prototype properties function'] = function() { + util.assertOutline("function Juan() {};Juan.prototype = Object.create(window);Juan.prototype.constructor = Juan;Juan.prototype.hello = function () {var j = 0;};", + {"outline": + [{"name":"Juan","type":"fn()","start":9,"end":13, + "children":[{"name":"prototype","type":"?","start":24,"end":33, + "children":[{"name":"constructor","type":"?","start":73,"end":84}, + {"name":"hello","type":"?","start":107,"end":112, + "children":[{"name":"j","type":"number","start":132,"end":133}] + } + ] + }] + }]} + ); +} + if (module == require.main) require("test").run(exports); \ No newline at end of file