Class: JsDuck::Js::Node
- Inherits:
-
Object
- Object
- JsDuck::Js::Node
- Defined in:
- lib/jsduck/js/node.rb
Overview
Wraps around AST node returned from Esprima, providing methods for investigating it.
Class Method Summary collapse
-
.create(node) ⇒ Object
Factor method that creates either Node or NodeArray.
Instance Method Summary collapse
-
#[](name) ⇒ Object
Shorthand for #child method.
- #array_expression? ⇒ Boolean
- #assignment_expression? ⇒ Boolean
-
#body ⇒ Object
Extracts all sub-statements and sub-expressions from AST node.
-
#call_expression? ⇒ Boolean
Simple shorthands for testing the type of node These have one-to-one mapping to Esprima node types.
-
#child(name) ⇒ Object
Returns a child AST node as Node class.
- #define_property? ⇒ Boolean
-
#each_property ⇒ Object
Iterates over keys and values in ObjectExpression.
- #expression_statement? ⇒ Boolean
- #ext_define? ⇒ Boolean
-
#ext_empty_fn? ⇒ Boolean
Checks dependent on Ext namespace, which may not always be “Ext” but also something user-defined.
- #ext_extend? ⇒ Boolean
- #ext_override? ⇒ Boolean
- #ext_pattern?(pattern) ⇒ Boolean
- #fire_event? ⇒ Boolean
-
#function? ⇒ Boolean
Tests for higher level types which don’t correspond directly to Esprima AST types.
- #function_declaration? ⇒ Boolean
- #function_expression? ⇒ Boolean
- #identifier? ⇒ Boolean
-
#initialize(node) ⇒ Node
constructor
Initialized with a AST Hash from Esprima.
-
#key_value ⇒ Object
Converts object expression property key to string value.
-
#linenr ⇒ Object
Returns line number in parsed source where the Node resides.
- #literal? ⇒ Boolean
- #member_expression? ⇒ Boolean
-
#object_descriptor(descriptor_key) ⇒ Object
Returns value of a given field from Object.defineProperty call descriptor object.
- #object_expression? ⇒ Boolean
- #property? ⇒ Boolean
-
#raw ⇒ Object
Returns the raw Exprima AST node this class wraps.
- #string? ⇒ Boolean
-
#to_s ⇒ Object
Serializes the node into string.
-
#to_value ⇒ Object
Evaluates the node into basic JavaScript value.
-
#type ⇒ Object
Returns the type of node.
-
#value_type ⇒ Object
Returns the type of node value.
- #variable_declaration? ⇒ Boolean
Constructor Details
#initialize(node) ⇒ Node
Initialized with a AST Hash from Esprima.
22 23 24 |
# File 'lib/jsduck/js/node.rb', line 22 def initialize(node) @node = node || {} end |
Class Method Details
Instance Method Details
#[](name) ⇒ Object
Shorthand for #child method
31 32 33 |
# File 'lib/jsduck/js/node.rb', line 31 def [](name) child(name) end |
#array_expression? ⇒ Boolean
201 202 203 |
# File 'lib/jsduck/js/node.rb', line 201 def array_expression? @node["type"] == "ArrayExpression" end |
#assignment_expression? ⇒ Boolean
193 194 195 |
# File 'lib/jsduck/js/node.rb', line 193 def assignment_expression? @node["type"] == "AssignmentExpression" end |
#body ⇒ Object
Extracts all sub-statements and sub-expressions from AST node. Without looking at the type of node, we just take all the sub-hashes and -arrays.
A downside of this simple algorithm is that the statements can end up in different order than they are in source code. For example the IfStatement has three parts in the following order: “test”, “consequent”, “alternate”: But because we’re looping over a hash, they might end up in a totally different order.
98 99 100 101 102 103 104 105 106 107 108 109 110 |
# File 'lib/jsduck/js/node.rb', line 98 def body body = [] @node.each_pair do |key, value| if key == "type" || key == "range" # ignore elsif value.is_a?(Array) body.concat(value.map {|v| Js::Node.create(v) }) elsif value.is_a?(Hash) body << Js::Node.create(value) end end body end |
#call_expression? ⇒ Boolean
Simple shorthands for testing the type of node These have one-to-one mapping to Esprima node types.
189 190 191 |
# File 'lib/jsduck/js/node.rb', line 189 def call_expression? @node["type"] == "CallExpression" end |
#child(name) ⇒ Object
Returns a child AST node as Node class.
27 28 29 |
# File 'lib/jsduck/js/node.rb', line 27 def child(name) Js::Node.create(@node[name]) end |
#define_property? ⇒ Boolean
155 156 157 |
# File 'lib/jsduck/js/node.rb', line 155 def define_property? call_expression? && child("callee").to_s == "Object.defineProperty" end |
#each_property ⇒ Object
Iterates over keys and values in ObjectExpression. The keys are turned into strings, but values are left as is for further processing.
115 116 117 118 119 120 121 |
# File 'lib/jsduck/js/node.rb', line 115 def each_property return unless object_expression? child("properties").each do |ast| yield(ast["key"].key_value, ast["value"], ast) end end |
#expression_statement? ⇒ Boolean
213 214 215 |
# File 'lib/jsduck/js/node.rb', line 213 def expression_statement? @node["type"] == "ExpressionStatement" end |
#ext_define? ⇒ Boolean
170 171 172 |
# File 'lib/jsduck/js/node.rb', line 170 def ext_define? call_expression? && child("callee").ext_pattern?("Ext.define") end |
#ext_empty_fn? ⇒ Boolean
Checks dependent on Ext namespace, which may not always be “Ext” but also something user-defined.
166 167 168 |
# File 'lib/jsduck/js/node.rb', line 166 def ext_empty_fn? member_expression? && ext_pattern?("Ext.emptyFn") end |
#ext_extend? ⇒ Boolean
174 175 176 |
# File 'lib/jsduck/js/node.rb', line 174 def ext_extend? call_expression? && child("callee").ext_pattern?("Ext.extend") end |
#ext_override? ⇒ Boolean
178 179 180 |
# File 'lib/jsduck/js/node.rb', line 178 def ext_override? call_expression? && child("callee").ext_pattern?("Ext.override") end |
#ext_pattern?(pattern) ⇒ Boolean
182 183 184 |
# File 'lib/jsduck/js/node.rb', line 182 def ext_pattern?(pattern) Js::ExtPatterns.matches?(pattern, to_s) end |
#fire_event? ⇒ Boolean
151 152 153 |
# File 'lib/jsduck/js/node.rb', line 151 def fire_event? call_expression? && child("callee").to_s == "this.fireEvent" end |
#function? ⇒ Boolean
Tests for higher level types which don’t correspond directly to Esprima AST types.
147 148 149 |
# File 'lib/jsduck/js/node.rb', line 147 def function? function_declaration? || function_expression? || ext_empty_fn? end |
#function_declaration? ⇒ Boolean
221 222 223 |
# File 'lib/jsduck/js/node.rb', line 221 def function_declaration? @node["type"] == "FunctionDeclaration" end |
#function_expression? ⇒ Boolean
205 206 207 |
# File 'lib/jsduck/js/node.rb', line 205 def function_expression? @node["type"] == "FunctionExpression" end |
#identifier? ⇒ Boolean
229 230 231 |
# File 'lib/jsduck/js/node.rb', line 229 def identifier? @node["type"] == "Identifier" end |
#key_value ⇒ Object
Converts object expression property key to string value
59 60 61 |
# File 'lib/jsduck/js/node.rb', line 59 def key_value Js::Evaluator.new.key_value(@node) end |
#linenr ⇒ Object
Returns line number in parsed source where the Node resides.
137 138 139 140 141 142 |
# File 'lib/jsduck/js/node.rb', line 137 def linenr # Get line number from third place at range array. # This third item exists in forked EsprimaJS at # https://github.com/nene/esprima/tree/linenr-in-range @node["range"][2] end |
#literal? ⇒ Boolean
233 234 235 |
# File 'lib/jsduck/js/node.rb', line 233 def literal? @node["type"] == "Literal" end |
#member_expression? ⇒ Boolean
209 210 211 |
# File 'lib/jsduck/js/node.rb', line 209 def member_expression? @node["type"] == "MemberExpression" end |
#object_descriptor(descriptor_key) ⇒ Object
Returns value of a given field from Object.defineProperty call descriptor object.
125 126 127 128 129 130 131 132 133 134 |
# File 'lib/jsduck/js/node.rb', line 125 def object_descriptor(descriptor_key) return unless define_property? descriptor = child("arguments")[2] descriptor.each_property do |key, value, prop| return value if key == descriptor_key end return nil end |
#object_expression? ⇒ Boolean
197 198 199 |
# File 'lib/jsduck/js/node.rb', line 197 def object_expression? @node["type"] == "ObjectExpression" end |
#property? ⇒ Boolean
225 226 227 |
# File 'lib/jsduck/js/node.rb', line 225 def property? @node["type"] == "Property" end |
#raw ⇒ Object
Returns the raw Exprima AST node this class wraps.
36 37 38 |
# File 'lib/jsduck/js/node.rb', line 36 def raw @node end |
#string? ⇒ Boolean
159 160 161 |
# File 'lib/jsduck/js/node.rb', line 159 def string? literal? && @node["value"].is_a?(String) end |
#to_s ⇒ Object
Serializes the node into string
41 42 43 44 45 46 47 |
# File 'lib/jsduck/js/node.rb', line 41 def to_s begin Js::Serializer.new.to_s(@node) rescue nil end end |
#to_value ⇒ Object
Evaluates the node into basic JavaScript value.
50 51 52 53 54 55 56 |
# File 'lib/jsduck/js/node.rb', line 50 def to_value begin Js::Evaluator.new.to_value(@node) rescue nil end end |
#type ⇒ Object
Returns the type of node.
84 85 86 |
# File 'lib/jsduck/js/node.rb', line 84 def type @node["type"] end |
#value_type ⇒ Object
Returns the type of node value.
64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 |
# File 'lib/jsduck/js/node.rb', line 64 def value_type v = to_value if v.is_a?(String) "String" elsif v.is_a?(Numeric) "Number" elsif v.is_a?(TrueClass) || v.is_a?(FalseClass) "Boolean" elsif v.is_a?(Array) "Array" elsif v.is_a?(Hash) "Object" elsif v == :regexp "RegExp" else nil end end |
#variable_declaration? ⇒ Boolean
217 218 219 |
# File 'lib/jsduck/js/node.rb', line 217 def variable_declaration? @node["type"] == "VariableDeclaration" end |