code_reference_finder 0.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. checksums.yaml +7 -0
  2. data/lib/code_reference_finder.rb +136 -0
  3. metadata +45 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 9af7b22c3b5a984cd962a855e4b60a910e748979d869a15a244a386f032bba06
4
+ data.tar.gz: 6f3125078a4f4d60a005fa392138e7d7eca082a207db5a00fa327c97836cbe93
5
+ SHA512:
6
+ metadata.gz: c04d79e144283a4163fa7dec0733af9b1686b2c41d8a0048c34fae05c6832c0090127267e15cbe12a38031f7ec244ccb2dae27b12f95bf93a5f2e25e52fb55ea
7
+ data.tar.gz: c4ff575f231b3db942c1f0d4231416280c77118423a47c358712f56df10517f4917e55abf27689e2f3a73f15b388b4f4798cf8f53f8872270637fe1273be8875
@@ -0,0 +1,136 @@
1
+ # This is a source code analyzer for finding files containing specific references.
2
+
3
+ class CodeReferenceFinder
4
+ def initialize(dir:, ext:, target:, ignore:)
5
+ @dir = dir
6
+ @ext = ext
7
+ @target = target
8
+ @ignore = ignore
9
+ @results = nil
10
+ @interesting_paths = nil
11
+ end
12
+
13
+ # Performs a parse and returns JSON results.
14
+ def get_json
15
+ @interesting_paths = find_interesting_paths()
16
+ json = parse_interesting_paths(@interesting_paths)
17
+ json
18
+ end
19
+
20
+ # Returns the result hash, nil if unparsed.
21
+ def get_results
22
+ @results
23
+ end
24
+
25
+ # Returns the interesting paths array, nil if unparsed.
26
+ def get_interesting_paths
27
+ @interesting_paths
28
+ end
29
+
30
+ private
31
+
32
+ attr_reader :results, :interesting_paths
33
+
34
+ # First pass pre-processing to locate files of interest to parse.
35
+ def find_interesting_paths
36
+ require 'find'
37
+
38
+ src_paths = []
39
+ Find.find(@dir) do |path|
40
+ src_paths << path if path.end_with? @ext
41
+ end
42
+
43
+ search_file_paths = []
44
+ src_paths.each do |path|
45
+ File.open(path) do |f|
46
+ f.each_line do |line|
47
+ if @target.any? {|s| line.include? s}
48
+ search_file_paths << path unless search_file_paths.include? path
49
+ end
50
+ end
51
+ end
52
+ end
53
+
54
+ search_file_paths
55
+ end
56
+
57
+ # Where the magic happens.
58
+ def parse_interesting_paths(interesting_paths)
59
+ require 'json'
60
+
61
+ def is_comment?(line)
62
+ line.start_with? '*' or line.start_with? '/*' or line.start_with? '//'
63
+ end
64
+
65
+ def is_call?(line, ref)
66
+ line.include? "#{ref}." or line.include? "(#{ref}" or line.include? "#{ref})"
67
+ end
68
+
69
+ def is_ref_search_match?(line, refs)
70
+ tokens = line.split(' ')
71
+ matches = []
72
+ refs.each {|ref| matches << ref if tokens.include? ref }
73
+ matches.size > 0
74
+ end
75
+
76
+ def is_ignorable?(line)
77
+ @ignore.any? {|s| line.include? s}
78
+ end
79
+
80
+ start_time = Process.clock_gettime(Process::CLOCK_MONOTONIC)
81
+
82
+ file_matches = {}
83
+ refined_target = @target.map {|s| s.split(' ').last}
84
+
85
+ # Loop through interesting paths to find targets and references to targets.
86
+ # Add the results of the parse to the file_matches hash.
87
+ interesting_paths.each do |path|
88
+ name = path[path.rindex('/') + 1..].sub(@ext, '').strip
89
+ line_matches = []
90
+ ref_searches = []
91
+ i = 0
92
+
93
+ File.open(path) do |f|
94
+ f.each_line do |line|
95
+ i += 1
96
+ next if is_comment?(line.strip!)
97
+
98
+ if refined_target.any? {|s| line.include? s} and not is_ignorable?(line)
99
+ line_matches << "#{i}: #{line}"
100
+
101
+ if line.include? ' = '
102
+ search = line.strip.split('=')[0].split(' ').last
103
+ ref_searches << search if not ref_searches.include? search
104
+ end
105
+ elsif ref_searches.any? {|s| is_call?(line, s)} or is_ref_search_match?(line, ref_searches)
106
+ line_matches << "#{i}: #{line}"
107
+ end
108
+ end
109
+ end
110
+
111
+ file_matches[name] = {
112
+ :path => path,
113
+ :line_count => i,
114
+ :ref_count => ref_searches.size,
115
+ :match_count => line_matches.size,
116
+ :refs => ref_searches,
117
+ :matches => line_matches
118
+ }
119
+ end
120
+
121
+ end_time = Process.clock_gettime(Process::CLOCK_MONOTONIC)
122
+
123
+ # Define our results hash and return it as a JSON string.
124
+ @results = {
125
+ :params => {
126
+ :dir => @dir,
127
+ :ext => @ext,
128
+ :target => @target,
129
+ :ignore => @ignore
130
+ },
131
+ :duration => "#{end_time - start_time} seconds",
132
+ :file_matches => file_matches
133
+ }
134
+ JSON.pretty_generate(@results)
135
+ end
136
+ end
metadata ADDED
@@ -0,0 +1,45 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: code_reference_finder
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Scott Stauffer
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2023-02-10 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: A source code analyzer to find targets and their references in very large
14
+ solutions.
15
+ email: scott@fuseraft.com
16
+ executables: []
17
+ extensions: []
18
+ extra_rdoc_files: []
19
+ files:
20
+ - lib/code_reference_finder.rb
21
+ homepage: https://rubygems.org/gems/code_reference_finder
22
+ licenses:
23
+ - MIT
24
+ metadata: {}
25
+ post_install_message:
26
+ rdoc_options: []
27
+ require_paths:
28
+ - lib
29
+ required_ruby_version: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ required_rubygems_version: !ruby/object:Gem::Requirement
35
+ requirements:
36
+ - - ">="
37
+ - !ruby/object:Gem::Version
38
+ version: '0'
39
+ requirements: []
40
+ rubygems_version: 3.3.5
41
+ signing_key:
42
+ specification_version: 4
43
+ summary: A source code analyzer to find targets and their references in very large
44
+ solutions.
45
+ test_files: []