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
- #block_statement? ⇒ 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.
- #return_statement? ⇒ Boolean
-
#return_statement_expression ⇒ Object
Returns the return statement’s expression for the current function expression.
- #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
228 229 230 |
# File 'lib/jsduck/js/node.rb', line 228 def array_expression? @node["type"] == "ArrayExpression" end |
#assignment_expression? ⇒ Boolean
220 221 222 |
# File 'lib/jsduck/js/node.rb', line 220 def assignment_expression? @node["type"] == "AssignmentExpression" end |
#block_statement? ⇒ Boolean
155 156 157 |
# File 'lib/jsduck/js/node.rb', line 155 def block_statement? @node["type"] == "BlockStatement" 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.
216 217 218 |
# File 'lib/jsduck/js/node.rb', line 216 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
182 183 184 |
# File 'lib/jsduck/js/node.rb', line 182 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
240 241 242 |
# File 'lib/jsduck/js/node.rb', line 240 def expression_statement? @node["type"] == "ExpressionStatement" end |
#ext_define? ⇒ Boolean
197 198 199 |
# File 'lib/jsduck/js/node.rb', line 197 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.
193 194 195 |
# File 'lib/jsduck/js/node.rb', line 193 def ext_empty_fn? member_expression? && ext_pattern?("Ext.emptyFn") end |
#ext_extend? ⇒ Boolean
201 202 203 |
# File 'lib/jsduck/js/node.rb', line 201 def ext_extend? call_expression? && child("callee").ext_pattern?("Ext.extend") end |
#ext_override? ⇒ Boolean
205 206 207 |
# File 'lib/jsduck/js/node.rb', line 205 def ext_override? call_expression? && child("callee").ext_pattern?("Ext.override") end |
#ext_pattern?(pattern) ⇒ Boolean
209 210 211 |
# File 'lib/jsduck/js/node.rb', line 209 def ext_pattern?(pattern) Js::ExtPatterns.matches?(pattern, to_s) end |
#fire_event? ⇒ Boolean
178 179 180 |
# File 'lib/jsduck/js/node.rb', line 178 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.
174 175 176 |
# File 'lib/jsduck/js/node.rb', line 174 def function? function_declaration? || function_expression? || ext_empty_fn? end |
#function_declaration? ⇒ Boolean
248 249 250 |
# File 'lib/jsduck/js/node.rb', line 248 def function_declaration? @node["type"] == "FunctionDeclaration" end |
#function_expression? ⇒ Boolean
232 233 234 |
# File 'lib/jsduck/js/node.rb', line 232 def function_expression? @node["type"] == "FunctionExpression" end |
#identifier? ⇒ Boolean
256 257 258 |
# File 'lib/jsduck/js/node.rb', line 256 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.
164 165 166 167 168 169 |
# File 'lib/jsduck/js/node.rb', line 164 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
260 261 262 |
# File 'lib/jsduck/js/node.rb', line 260 def literal? @node["type"] == "Literal" end |
#member_expression? ⇒ Boolean
236 237 238 |
# File 'lib/jsduck/js/node.rb', line 236 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
224 225 226 |
# File 'lib/jsduck/js/node.rb', line 224 def object_expression? @node["type"] == "ObjectExpression" end |
#property? ⇒ Boolean
252 253 254 |
# File 'lib/jsduck/js/node.rb', line 252 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 |
#return_statement? ⇒ Boolean
159 160 161 |
# File 'lib/jsduck/js/node.rb', line 159 def return_statement? @node["type"] == "ReturnStatement" end |
#return_statement_expression ⇒ Object
Returns the return statement’s expression for the current function expression.
138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 |
# File 'lib/jsduck/js/node.rb', line 138 def return_statement_expression return unless function_expression? node = child("body") if node.block_statement? node["body"].each do |node| if node.return_statement? node = node["argument"] return node.object_expression? ? node : nil end end end return nil end |
#string? ⇒ Boolean
186 187 188 |
# File 'lib/jsduck/js/node.rb', line 186 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
244 245 246 |
# File 'lib/jsduck/js/node.rb', line 244 def variable_declaration? @node["type"] == "VariableDeclaration" end |