Class: Fast::Node

Inherits:
Object
  • Object
show all
Defined in:
lib/fast/git.rb,
lib/fast/node.rb

Overview

This is not required by default, so to use it, you should require it first.

@example
  require 'fast/git'
  Fast.ast_from_file('lib/fast.rb').git_log.first.author.name # => "Jonatas Davi Paganini"

Direct Known Subclasses

PrismAdapter::Node, SQL::Node

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(type, children = [], properties = {}) ⇒ Node

Returns a new instance of Node.



7
8
9
10
11
12
# File 'lib/fast/node.rb', line 7

def initialize(type, children = [], properties = {})
  @type = type.to_sym
  @children = Array(children).freeze
  @loc = properties[:location]
  assign_parents!
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(method_name, *args, &block) ⇒ Object



121
122
123
124
125
# File 'lib/fast/node.rb', line 121

def method_missing(method_name, *args, &block)
  return type == type_query_name(method_name) if type_query_method?(method_name) && args.empty? && !block

  super
end

Instance Attribute Details

#childrenObject (readonly)

Returns the value of attribute children.



5
6
7
# File 'lib/fast/node.rb', line 5

def children
  @children
end

#locObject (readonly)

Returns the value of attribute loc.



5
6
7
# File 'lib/fast/node.rb', line 5

def loc
  @loc
end

#typeObject (readonly)

Returns the value of attribute type.



5
6
7
# File 'lib/fast/node.rb', line 5

def type
  @type
end

Class Method Details

.parent_for(node) ⇒ Object



19
20
21
# File 'lib/fast/node.rb', line 19

def parent_for(node)
  NODE_PARENTS[node]
end

.set_parent(node, parent) ⇒ Object



15
16
17
# File 'lib/fast/node.rb', line 15

def set_parent(node, parent)
  NODE_PARENTS[node] = parent
end

Instance Method Details

#<<(child) ⇒ Object



93
94
95
# File 'lib/fast/node.rb', line 93

def <<(child)
  updated(nil, children + [child])
end

#==(other) ⇒ Object Also known as: eql?



80
81
82
# File 'lib/fast/node.rb', line 80

def ==(other)
  Fast.ast_node?(other) && type == other.type && children == other.children
end

#authorString

Returns with the first element from #blame_authors.

Returns:

  • (String)

    with the first element from #blame_authors



135
136
137
# File 'lib/fast/node.rb', line 135

def author
  blame_authors.first
end

#blame_authorsArray<String>

Returns with authors from the current expression range.

Returns:

  • (Array<String>)

    with authors from the current expression range



128
129
130
131
132
# File 'lib/fast/node.rb', line 128

def blame_authors
  `git blame -L #{expression.first_line},#{expression.last_line} #{buffer_name}`.lines.map do |line|
    line.split('(')[1].split(/\d+/).first.strip
  end
end

#buffer_nameString

Returns with path of the file or simply buffer name.

Returns:

  • (String)

    with path of the file or simply buffer name.



25
26
27
# File 'lib/fast/node.rb', line 25

def buffer_name
  expression.source_buffer.name
end

#capture(pattern, *args) ⇒ Array<Fast::Node>

Captures elements from search recursively

Parameters:

  • pattern (String)
  • *args (Array)

    extra arguments to interpolate in the pattern.

Returns:

  • (Array<Fast::Node>)

    ] with files and results



151
152
153
# File 'lib/fast/node.rb', line 151

def capture(pattern, *args)
  Fast.capture(pattern, self, *args)
end

#deconstructObject



97
98
99
# File 'lib/fast/node.rb', line 97

def deconstruct
  to_a
end

#each_child_nodeObject



49
50
51
52
53
# File 'lib/fast/node.rb', line 49

def each_child_node
  return enum_for(:each_child_node) unless block_given?

  children.select { |child| Fast.ast_node?(child) }.each { |child| yield child }
end

#each_descendant(*types, &block) ⇒ Object



55
56
57
58
59
60
61
62
# File 'lib/fast/node.rb', line 55

def each_descendant(*types, &block)
  return enum_for(:each_descendant, *types) unless block_given?

  each_child_node do |child|
    yield child if types.empty? || types.include?(child.type)
    child.each_descendant(*types, &block) if child.respond_to?(:each_descendant)
  end
end

#expressionFast::Source::Range

Returns from the expression.

Returns:



30
31
32
# File 'lib/fast/node.rb', line 30

def expression
  loc.expression
end

#fileObject



58
59
60
# File 'lib/fast/git.rb', line 58

def file
  buffer_name.gsub("#{Dir.pwd}/", '')
end

#from_file?Boolean

Returns true if a file exists with the #buffer_name.

Returns:

  • (Boolean)

    true if a file exists with the #buffer_name



45
46
47
# File 'lib/fast/node.rb', line 45

def from_file?
  File.exist?(buffer_name)
end

#gitGit::Base

Returns from current directory.

Returns:

  • (Git::Base)

    from current directory



13
14
15
16
# File 'lib/fast/git.rb', line 13

def git
  require 'git' unless defined? Git
  Git.open('.')
end

#git_blobGit::Object::Blob

Returns from current #buffer_name.

Returns:

  • (Git::Object::Blob)

    from current #buffer_name



19
20
21
22
23
# File 'lib/fast/git.rb', line 19

def git_blob
  return unless from_file?

  git.gblob(buffer_name)
end

#git_logGit::Log

Returns from the current #git_blob buffer-name.

Returns:

  • (Git::Log)

    from the current #git_blob buffer-name



27
28
29
# File 'lib/fast/git.rb', line 27

def git_log
  git_blob.log
end

#hashObject



85
86
87
# File 'lib/fast/node.rb', line 85

def hash
  [type, children].hash
end

#inspectObject



113
114
115
# File 'lib/fast/node.rb', line 113

def inspect
  format_node(:inspect)
end

#last_commitGit::Object::Commit

Returns:

  • (Git::Object::Commit)


32
33
34
# File 'lib/fast/git.rb', line 32

def last_commit
  git_log.first
end

#line_rangeObject

Returns:



63
64
65
# File 'lib/fast/git.rb', line 63

def line_range
  lines.map { |l| "L#{l}" }.join('-')
end

#linesArray

Returns with lines range.

Returns:

  • (Array)

    with lines range



68
69
70
71
72
73
# File 'lib/fast/git.rb', line 68

def lines
  exp = loc.expression
  first_line = exp.first_line
  last_line = exp.last_line
  [first_line, last_line].uniq
end

#lines_of_codeInteger

Returns lines of code from current block.

Returns:

  • (Integer)

    lines of code from current block



76
77
78
# File 'lib/fast/git.rb', line 76

def lines_of_code
  lines.last - lines.first + 1
end

Returns with formatted repositorym link.

Returns:

  • (String)

    with formatted repositorym link



92
93
94
# File 'lib/fast/git.rb', line 92

def link
  "#{project_url}/blob/master/#{buffer_name}##{line_range}"
end

#locationObject

Backward-compatible alias for callers that still use location.



35
36
37
# File 'lib/fast/node.rb', line 35

def location
  loc
end

Returns a markdown link with #md_link_description and #link.

Returns:

  • (String)

    a markdown link with #md_link_description and #link



81
82
83
# File 'lib/fast/git.rb', line 81

def md_link(text = md_link_description)
  "[#{text}](#{link})"
end

able to create a markdown link without parens.

Returns:

  • (String)

    with the source cutting arguments from method calls to be



87
88
89
# File 'lib/fast/git.rb', line 87

def md_link_description
  source[/([^\r\(]+)\(/, 1] || source
end

#parentObject



68
69
70
# File 'lib/fast/node.rb', line 68

def parent
  self.class.parent_for(self)
end

Returns with permanent link to the actual commit.

Returns:

  • (String)

    with permanent link to the actual commit



97
98
99
# File 'lib/fast/git.rb', line 97

def permalink
  "#{project_url}/blob/#{sha}/#{buffer_name}##{line_range}"
end

#project_urlString

Given #remote_url is “[email protected]:namespace/project.git” Or #remote_url is “github.com/namespace/project.git

Returns:



49
50
51
52
53
54
55
56
# File 'lib/fast/git.rb', line 49

def project_url
  return remote_url.gsub(/\.git$/, '') if remote_url.start_with?('https')

  remote_url
    .gsub('git@', 'https://')
    .gsub(/:(\w)/, '/\\1')
    .gsub(/\.git$/, '')
end

#remote_urlString

Returns with remote URL.

Returns:

  • (String)

    with remote URL



42
43
44
# File 'lib/fast/git.rb', line 42

def remote_url
  git.remote.url
end

#respond_to_missing?(method_name, include_private = false) ⇒ Boolean

Returns:

  • (Boolean)


117
118
119
# File 'lib/fast/node.rb', line 117

def respond_to_missing?(method_name, include_private = false)
  type_query_method?(method_name) || super
end

#root?Boolean

Returns:

  • (Boolean)


64
65
66
# File 'lib/fast/node.rb', line 64

def root?
  parent.nil?
end

#search(pattern, *args) ⇒ Array<Fast::Node>

Search recursively into a node and its children using a pattern.

Parameters:

  • pattern (String)
  • *args (Array)

    extra arguments to interpolate in the pattern.

Returns:

  • (Array<Fast::Node>)

    ] with files and results



143
144
145
# File 'lib/fast/node.rb', line 143

def search(pattern, *args)
  Fast.search(pattern, self, *args)
end

#shaString

Returns with last commit SHA.

Returns:

  • (String)

    with last commit SHA



37
38
39
# File 'lib/fast/git.rb', line 37

def sha
  last_commit.sha
end

#sourceString

Returns with the content of the #expression.

Returns:

  • (String)

    with the content of the #expression



40
41
42
# File 'lib/fast/node.rb', line 40

def source
  expression.source
end

#to_aObject



89
90
91
# File 'lib/fast/node.rb', line 89

def to_a
  children.dup
end

#to_astObject



101
102
103
# File 'lib/fast/node.rb', line 101

def to_ast
  self
end

#to_sObject



109
110
111
# File 'lib/fast/node.rb', line 109

def to_s
  to_sexp
end

#to_sexpObject



105
106
107
# File 'lib/fast/node.rb', line 105

def to_sexp
  format_node(:sexp)
end

#updated(type = nil, children = nil, properties = nil) ⇒ Object



72
73
74
75
76
77
78
# File 'lib/fast/node.rb', line 72

def updated(type = nil, children = nil, properties = nil)
  self.class.new(
    type || self.type,
    children || self.children,
    { location: properties&.fetch(:location, loc) || loc }
  )
end