textmate_grammar 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.
- checksums.yaml +7 -0
- data/LICENSE +21 -0
- data/lib/textmate_grammar/generated/grammar.rb +32 -0
- data/lib/textmate_grammar/generated/rule.rb +144 -0
- data/lib/textmate_grammar/grammar.rb +670 -0
- data/lib/textmate_grammar/grammar_plugin.rb +189 -0
- data/lib/textmate_grammar/import_patterns.rb +14 -0
- data/lib/textmate_grammar/linters/flat_includes.rb +32 -0
- data/lib/textmate_grammar/linters/includes_then_tag_as.rb +48 -0
- data/lib/textmate_grammar/linters/standard_naming.rb +226 -0
- data/lib/textmate_grammar/linters/start_match_empty.rb +49 -0
- data/lib/textmate_grammar/linters/tests.rb +19 -0
- data/lib/textmate_grammar/linters/unused_unresolved.rb +9 -0
- data/lib/textmate_grammar/pattern_extensions/look_ahead_for.rb +32 -0
- data/lib/textmate_grammar/pattern_extensions/look_ahead_to_avoid.rb +31 -0
- data/lib/textmate_grammar/pattern_extensions/look_behind_for.rb +31 -0
- data/lib/textmate_grammar/pattern_extensions/look_behind_to_avoid.rb +31 -0
- data/lib/textmate_grammar/pattern_extensions/lookaround_pattern.rb +169 -0
- data/lib/textmate_grammar/pattern_extensions/match_result_of.rb +67 -0
- data/lib/textmate_grammar/pattern_extensions/maybe.rb +50 -0
- data/lib/textmate_grammar/pattern_extensions/one_of.rb +107 -0
- data/lib/textmate_grammar/pattern_extensions/one_or_more_of.rb +42 -0
- data/lib/textmate_grammar/pattern_extensions/or_pattern.rb +55 -0
- data/lib/textmate_grammar/pattern_extensions/placeholder.rb +102 -0
- data/lib/textmate_grammar/pattern_extensions/recursively_match.rb +76 -0
- data/lib/textmate_grammar/pattern_extensions/zero_or_more_of.rb +50 -0
- data/lib/textmate_grammar/pattern_variations/base_pattern.rb +870 -0
- data/lib/textmate_grammar/pattern_variations/legacy_pattern.rb +61 -0
- data/lib/textmate_grammar/pattern_variations/pattern.rb +9 -0
- data/lib/textmate_grammar/pattern_variations/pattern_range.rb +233 -0
- data/lib/textmate_grammar/pattern_variations/repeatable_pattern.rb +204 -0
- data/lib/textmate_grammar/regex_operator.rb +182 -0
- data/lib/textmate_grammar/regex_operators/alternation.rb +24 -0
- data/lib/textmate_grammar/regex_operators/concat.rb +23 -0
- data/lib/textmate_grammar/stdlib/common.rb +20 -0
- data/lib/textmate_grammar/tokens.rb +110 -0
- data/lib/textmate_grammar/transforms/add_ending.rb +25 -0
- data/lib/textmate_grammar/transforms/bailout.rb +92 -0
- data/lib/textmate_grammar/transforms/fix_repeated_tag_as.rb +75 -0
- data/lib/textmate_grammar/transforms/resolve_placeholders.rb +121 -0
- data/lib/textmate_grammar/util.rb +198 -0
- data/lib/textmate_grammar.rb +4 -0
- metadata +85 -0
@@ -0,0 +1,189 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# @abstract Subclass GrammarLinter or GrammarTransform to implement a plugin
|
4
|
+
class GrammarPlugin
|
5
|
+
# The options this plugin supports
|
6
|
+
# @return [Array<Symbol>] a list of symbols that represent keys that can
|
7
|
+
# be read by the plugin
|
8
|
+
# @note the keys :grammar and :repository are reserved for passing grammar information
|
9
|
+
def self.options
|
10
|
+
[]
|
11
|
+
end
|
12
|
+
|
13
|
+
# display the options as they would appear in the source
|
14
|
+
# @abstract override this to display the options as they would be entered into
|
15
|
+
# source code
|
16
|
+
# @param indent [String] the spaces to indent each line width
|
17
|
+
# @param options [Hash] all options passed to the pattern
|
18
|
+
# @return [String] the options as a string
|
19
|
+
# @note each option should be prepended with +"\\n,#{indent}"+
|
20
|
+
# @note only display the options that are unique to this plugin
|
21
|
+
def self.display_options(indent, options) # rubocop:disable Lint/UnusedMethodArgument
|
22
|
+
raise "Internal error: display_options called with no provided options" if options.empty?
|
23
|
+
|
24
|
+
if self.options.empty?
|
25
|
+
raise "Internal error: display_options called on a plugin that provides no options"
|
26
|
+
end
|
27
|
+
|
28
|
+
raise "GrammarPlugin::options implemented but GrammarPlugin::display_options has not been"
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
# @abstract Subclass and override {#pre_lint} and/or {#post_lint}
|
33
|
+
# to implement a linter
|
34
|
+
class GrammarLinter < GrammarPlugin
|
35
|
+
#
|
36
|
+
# Runs the linter on each pattern
|
37
|
+
#
|
38
|
+
# @param pattern [PatternBase, Symbol, Hash] the pattern to lint
|
39
|
+
# @param options [Hash] hash of any of the option keys provided by self.options.
|
40
|
+
# options will only be populated when pattern is a PatternBase
|
41
|
+
#
|
42
|
+
# @return [Boolean] the result of the lint
|
43
|
+
def pre_lint(pattern, options = {}) # rubocop:disable Lint/UnusedMethodArgument
|
44
|
+
true
|
45
|
+
end
|
46
|
+
|
47
|
+
#
|
48
|
+
# Runs the linter on the entire grammar
|
49
|
+
#
|
50
|
+
# @param [Hash] grammar_hash The entire grammar
|
51
|
+
#
|
52
|
+
# @return [Boolean] the result og the lint
|
53
|
+
#
|
54
|
+
def post_lint(grammar_hash) # rubocop:disable Lint/UnusedMethodArgument
|
55
|
+
true
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
# @abstract Subclass and override {#pre_transform} and/or {#post_transform}
|
60
|
+
# to implement a transformation
|
61
|
+
class GrammarTransform < GrammarPlugin
|
62
|
+
#
|
63
|
+
# Preforms the transformation on each pattern
|
64
|
+
#
|
65
|
+
# @param pattern [PatternBase, Symbol, Hash] the pattern to transform
|
66
|
+
# @param options [Hash] hash of any of the option keys provided by self.options.
|
67
|
+
# options will only be populated when pattern is a PatternBase
|
68
|
+
#
|
69
|
+
# @return [PatternBase, Symbol, Hash] The transformed pattern. The return type should
|
70
|
+
# match the type of pattern
|
71
|
+
#
|
72
|
+
# @note pattern should not be modified
|
73
|
+
#
|
74
|
+
def pre_transform(pattern, options) # rubocop:disable Lint/UnusedMethodArgument
|
75
|
+
pattern
|
76
|
+
end
|
77
|
+
|
78
|
+
#
|
79
|
+
# Performs the transformation on the whole grammar
|
80
|
+
#
|
81
|
+
# @param [Hash] grammar_hash The entire grammar
|
82
|
+
#
|
83
|
+
# @return [Hash] The transformed grammar
|
84
|
+
#
|
85
|
+
# @note grammar_hash should not be modified
|
86
|
+
#
|
87
|
+
def post_transform(grammar_hash)
|
88
|
+
grammar_hash
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
class Grammar
|
93
|
+
@@linters = []
|
94
|
+
@@transforms = {
|
95
|
+
before_pre_linter: [],
|
96
|
+
after_pre_linter: [],
|
97
|
+
before_post_linter: [],
|
98
|
+
after_post_linter: [],
|
99
|
+
}
|
100
|
+
|
101
|
+
#
|
102
|
+
# Register a linter plugin
|
103
|
+
#
|
104
|
+
# @param [GrammarLinter] linter the linter plugin
|
105
|
+
#
|
106
|
+
# @return [void] nothing
|
107
|
+
#
|
108
|
+
def self.register_linter(linter)
|
109
|
+
@@linters << linter
|
110
|
+
end
|
111
|
+
|
112
|
+
#
|
113
|
+
# Register a transformation plugin
|
114
|
+
#
|
115
|
+
# @param [GrammarTransform] transform the transformation plugin
|
116
|
+
# @param [Numeric] priority an optional priority
|
117
|
+
#
|
118
|
+
# @note The priority controls when a transformation runs in relation to
|
119
|
+
# other events in addition to ordering transformations
|
120
|
+
# priorities < 100 have their pre transform run before pre linters
|
121
|
+
# priorities >= 100 have their pre transform run after pre linters
|
122
|
+
# priorities >= 200 do not have their pre_transform function ran
|
123
|
+
# priorities < 300 have their post transorm run before post linters
|
124
|
+
# priorities >= 300 have their post transorm run before post linters
|
125
|
+
#
|
126
|
+
# @return [void] nothing
|
127
|
+
#
|
128
|
+
def self.register_transform(transform, priority = 150)
|
129
|
+
key = if priority < 100 then :before_pre_linter
|
130
|
+
elsif priority < 200 then :after_pre_linter
|
131
|
+
elsif priority < 300 then :before_post_linter
|
132
|
+
else :after_pre_linter
|
133
|
+
end
|
134
|
+
|
135
|
+
@@transforms[key] << {
|
136
|
+
priority: priority,
|
137
|
+
transform: transform,
|
138
|
+
}
|
139
|
+
end
|
140
|
+
|
141
|
+
#
|
142
|
+
# Gets all registered plugins
|
143
|
+
#
|
144
|
+
# @api private
|
145
|
+
#
|
146
|
+
# @return [Array<GrammarPlugin>] A list of all plugins
|
147
|
+
#
|
148
|
+
def self.plugins
|
149
|
+
@@linters + @@transforms.values.flatten.map { |v| v[:transform] }
|
150
|
+
end
|
151
|
+
|
152
|
+
#
|
153
|
+
# Removes a plugin whose classname matches plugin
|
154
|
+
#
|
155
|
+
# @param [#to_s] plugin The plugin name to remove
|
156
|
+
#
|
157
|
+
# @return [void]
|
158
|
+
#
|
159
|
+
def self.remove_plugin(plugin)
|
160
|
+
@@linters.delete_if { |linter| linter.class.to_s == plugin.to_s }
|
161
|
+
@@transforms[:before_pre_linter].delete_if { |t| t[:transform].class.to_s == plugin.to_s }
|
162
|
+
@@transforms[:after_pre_linter].delete_if { |t| t[:transform].class.to_s == plugin.to_s }
|
163
|
+
@@transforms[:before_post_linter].delete_if { |t| t[:transform].class.to_s == plugin.to_s }
|
164
|
+
@@transforms[:after_post_linter].delete_if { |t| t[:transform].class.to_s == plugin.to_s }
|
165
|
+
end
|
166
|
+
end
|
167
|
+
|
168
|
+
#
|
169
|
+
# Filters a {PatternBase#original_arguments} to just the options required for a plugin
|
170
|
+
#
|
171
|
+
# @api private
|
172
|
+
#
|
173
|
+
# @param [GrammarPlugin] plugin The plugin to filter options
|
174
|
+
# @param [PatternBase, Symbol, Hash] pattern the pattern with options to filter
|
175
|
+
# @param [Hash] default the default options to supply to the plugin
|
176
|
+
#
|
177
|
+
# @return [Hash] the filtered options
|
178
|
+
#
|
179
|
+
def filter_options(plugin, pattern, default)
|
180
|
+
options = {}
|
181
|
+
if pattern.is_a? PatternBase
|
182
|
+
options = pattern.original_arguments.select { |k| plugin.class.options.include? k }
|
183
|
+
end
|
184
|
+
options.merge(default)
|
185
|
+
end
|
186
|
+
|
187
|
+
# load default linters and transforms
|
188
|
+
Dir[File.join(__dir__, 'linters', '*.rb')].each { |file| require file }
|
189
|
+
Dir[File.join(__dir__, 'transforms', '*.rb')].each { |file| require file }
|
@@ -0,0 +1,14 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'deep_clone'
|
4
|
+
require 'yaml'
|
5
|
+
require 'textmate_grammar/grammar_plugin'
|
6
|
+
require 'textmate_grammar/util'
|
7
|
+
require 'textmate_grammar/regex_operator'
|
8
|
+
require 'textmate_grammar/regex_operators/concat'
|
9
|
+
require 'textmate_grammar/tokens'
|
10
|
+
|
11
|
+
# import Pattern, LegacyPattern, and PatternRange
|
12
|
+
Dir[File.join(__dir__, 'pattern_variations', '*.rb')].each { |file| require file }
|
13
|
+
# import .or(), .maybe(), .zeroOrMoreOf(), etc
|
14
|
+
Dir[File.join(__dir__, 'pattern_extensions', '*.rb')].each { |file| require file }
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'textmate_grammar/util'
|
4
|
+
|
5
|
+
#
|
6
|
+
# Internal check, ensures that :includes is nil or a flat array
|
7
|
+
#
|
8
|
+
class FlatIncludes < GrammarLinter
|
9
|
+
#
|
10
|
+
# (see GrammarLinter#pre_lint)
|
11
|
+
#
|
12
|
+
def pre_lint(pattern, options)
|
13
|
+
return true unless pattern.is_a? PatternBase
|
14
|
+
return true if pattern.arguments[:includes].nil?
|
15
|
+
|
16
|
+
if pattern.arguments[:includes].is_a?(Array) &&
|
17
|
+
pattern.arguments[:includes].none? { |v| v.is_a? Array }
|
18
|
+
flat = true
|
19
|
+
pattern.arguments[:includes].map do |s|
|
20
|
+
flat = false unless pre_lint(s, options)
|
21
|
+
end
|
22
|
+
return flat
|
23
|
+
end
|
24
|
+
|
25
|
+
puts "The pattern `#{pattern.name}' does not have a flat includes array."
|
26
|
+
puts "This is an internal error"
|
27
|
+
|
28
|
+
false
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
Grammar.register_linter(FlatIncludes.new)
|
@@ -0,0 +1,48 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'textmate_grammar/util'
|
4
|
+
|
5
|
+
#
|
6
|
+
# A pattern that has an includes cannot have any tag_as in @match
|
7
|
+
#
|
8
|
+
class IncludesThenTagAs < GrammarLinter
|
9
|
+
#
|
10
|
+
# Does pattern or any of its children / siblings have a tag_as
|
11
|
+
#
|
12
|
+
# @param [PatternBase, String] pattern the pattern to check
|
13
|
+
#
|
14
|
+
# @return [Boolean] if any of the patterns have a tag_as
|
15
|
+
#
|
16
|
+
def tag_as?(pattern)
|
17
|
+
return false unless pattern.is_a? PatternBase
|
18
|
+
|
19
|
+
pattern.each do |s|
|
20
|
+
puts s.arguments[:tag_as] if s.arguments[:tag_as]
|
21
|
+
return true if s.arguments[:tag_as]
|
22
|
+
end
|
23
|
+
|
24
|
+
false
|
25
|
+
end
|
26
|
+
|
27
|
+
#
|
28
|
+
# (see GrammarLinter#pre_lint)
|
29
|
+
#
|
30
|
+
def pre_lint(pattern, options)
|
31
|
+
return true unless pattern.is_a? PatternBase
|
32
|
+
return true if pattern.is_a? PatternRange
|
33
|
+
|
34
|
+
return false unless pre_lint(pattern.match, options)
|
35
|
+
|
36
|
+
return true unless pattern.arguments[:includes].is_a? Array
|
37
|
+
return true unless tag_as?(pattern.match)
|
38
|
+
|
39
|
+
name = pattern.name
|
40
|
+
puts "The pattern `#{name}' has both an includes argument and a match argument that,"
|
41
|
+
puts "it or a sub pattern has a tag_as argument."
|
42
|
+
puts "this is not supported"
|
43
|
+
|
44
|
+
true # TODO: fix issue
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
Grammar.register_linter(IncludesThenTagAs.new)
|
@@ -0,0 +1,226 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
#
|
4
|
+
# Checks for names to match expected naming format
|
5
|
+
# see https://www.sublimetext.com/docs/3/scope_naming.html
|
6
|
+
#
|
7
|
+
|
8
|
+
class StandardNaming < GrammarLinter
|
9
|
+
# This is a summarization of the rules on the sublime text website for scope name
|
10
|
+
# process:
|
11
|
+
# 1. start at root
|
12
|
+
# 2. for each component in name
|
13
|
+
# 1. if there exists a key with that name
|
14
|
+
# 1. if the value is a hash: repeat with next component and that hash
|
15
|
+
# 2. otherwise return the value
|
16
|
+
# 2. else
|
17
|
+
# 1. if there exists a key of "*" return true, otherwise false
|
18
|
+
#
|
19
|
+
# to ease parsing, there should only every be one valid path
|
20
|
+
# if "a" exists, dont add "a.b" to the same key
|
21
|
+
|
22
|
+
# @return [Hash] a summarization of expected names
|
23
|
+
EXPECTED_NAMES = {
|
24
|
+
"comment" => {
|
25
|
+
"line" => true,
|
26
|
+
"block" => true,
|
27
|
+
}.freeze,
|
28
|
+
"constant" => {
|
29
|
+
"numeric" => true,
|
30
|
+
"language" => true,
|
31
|
+
"character" => {"escape" => true}.freeze,
|
32
|
+
"other" => true,
|
33
|
+
}.freeze,
|
34
|
+
"entity" => {
|
35
|
+
"name" => {
|
36
|
+
"class" => true,
|
37
|
+
"struct" => true,
|
38
|
+
"enum" => true,
|
39
|
+
"union" => true,
|
40
|
+
"trait" => true,
|
41
|
+
"interface" => true,
|
42
|
+
"impl" => true,
|
43
|
+
"type" => true,
|
44
|
+
"function" => true,
|
45
|
+
"namespace" => true,
|
46
|
+
"constant" => true,
|
47
|
+
"label" => true,
|
48
|
+
"section" => true,
|
49
|
+
"scope-resolution" => true,
|
50
|
+
"tag" => true,
|
51
|
+
"attribute-name" => true,
|
52
|
+
"other" => true,
|
53
|
+
}.freeze,
|
54
|
+
"other" => true,
|
55
|
+
}.freeze,
|
56
|
+
"invalid" => {
|
57
|
+
"illegal" => true,
|
58
|
+
"deprecated" => true,
|
59
|
+
"unknown" => true,
|
60
|
+
}.freeze,
|
61
|
+
"keyword" => {
|
62
|
+
"control" => true,
|
63
|
+
"operator" => true,
|
64
|
+
"other" => true,
|
65
|
+
"declaration" => true,
|
66
|
+
}.freeze,
|
67
|
+
"markup" => {
|
68
|
+
"heading" => true,
|
69
|
+
"list" => {
|
70
|
+
"numbered" => true,
|
71
|
+
"unnumbered" => true,
|
72
|
+
}.freeze,
|
73
|
+
"bold" => true,
|
74
|
+
"italic" => true,
|
75
|
+
"inline" => true,
|
76
|
+
"underline" => true,
|
77
|
+
"inserted" => true,
|
78
|
+
"deleted" => true,
|
79
|
+
"quote" => true,
|
80
|
+
"raw" => {
|
81
|
+
"inline" => true,
|
82
|
+
"block" => true,
|
83
|
+
}.freeze,
|
84
|
+
"other" => true,
|
85
|
+
}.freeze,
|
86
|
+
"meta" => {
|
87
|
+
"asm" => true,
|
88
|
+
"class" => true,
|
89
|
+
"struct" => true,
|
90
|
+
"enum" => true,
|
91
|
+
"union" => true,
|
92
|
+
"trait" => true,
|
93
|
+
"interface" => true,
|
94
|
+
"declaration" => true,
|
95
|
+
"impl" => true,
|
96
|
+
"initialization" => true,
|
97
|
+
"type" => true,
|
98
|
+
"qualified_type" => true,
|
99
|
+
"function" => true,
|
100
|
+
"parameter" => true,
|
101
|
+
"namespace" => true,
|
102
|
+
"using-namespace" => true,
|
103
|
+
"preprocessor" => true,
|
104
|
+
"conditional" => true,
|
105
|
+
"annotation" => true,
|
106
|
+
"path" => true,
|
107
|
+
"function-call" => true,
|
108
|
+
"block" => true,
|
109
|
+
"group" => true,
|
110
|
+
"braces" => true,
|
111
|
+
"parens" => true,
|
112
|
+
"brackets" => true,
|
113
|
+
"generic" => true,
|
114
|
+
"template" => true,
|
115
|
+
"tag" => true,
|
116
|
+
"paragraph" => true,
|
117
|
+
"string" => true,
|
118
|
+
"interpolation" => true,
|
119
|
+
"toc-list" => true,
|
120
|
+
"banner" => true,
|
121
|
+
}.freeze,
|
122
|
+
"punctuation" => {
|
123
|
+
"definition" => true,
|
124
|
+
"separator" => true,
|
125
|
+
"terminator" => true,
|
126
|
+
"accessor" => true,
|
127
|
+
"section" => true,
|
128
|
+
"vararg-ellipses" => true,
|
129
|
+
}.freeze,
|
130
|
+
"source" => true,
|
131
|
+
"storage" => {
|
132
|
+
"type" => true,
|
133
|
+
"modifier" => true,
|
134
|
+
}.freeze,
|
135
|
+
"string" => {
|
136
|
+
"quoted" => {
|
137
|
+
"single" => true,
|
138
|
+
"double" => true,
|
139
|
+
"other" => true,
|
140
|
+
}.freeze,
|
141
|
+
"unquoted" => true,
|
142
|
+
"regexp" => true,
|
143
|
+
}.freeze,
|
144
|
+
"support" => {
|
145
|
+
"constant" => true,
|
146
|
+
"function" => true,
|
147
|
+
"module" => true,
|
148
|
+
"type" => true,
|
149
|
+
"class" => true,
|
150
|
+
"other" => true,
|
151
|
+
}.freeze,
|
152
|
+
"text" => true,
|
153
|
+
"variable" => {
|
154
|
+
"other" => true,
|
155
|
+
"language" => true,
|
156
|
+
"function" => true,
|
157
|
+
"annotation" => true,
|
158
|
+
"parameter" => true,
|
159
|
+
}.freeze,
|
160
|
+
}.freeze
|
161
|
+
|
162
|
+
#
|
163
|
+
# Checks the tag keys at this level
|
164
|
+
#
|
165
|
+
# @param [Array<string>] tag an array of tag components
|
166
|
+
# @param [Numeric] index The index into tag to check
|
167
|
+
# @param [Hash] root the hash to check against
|
168
|
+
#
|
169
|
+
# @return [Boolean] If this is a valid tag
|
170
|
+
#
|
171
|
+
def recursive_check_tag(tag, index = 0, root = EXPECTED_NAMES)
|
172
|
+
if root.has_key?(tag[index])
|
173
|
+
next_part = root[tag[index]]
|
174
|
+
return recursive_check_tag(tag, index+1, next_part) if next_part.is_a? Hash
|
175
|
+
|
176
|
+
return [next_part, index, root]
|
177
|
+
elsif root.has_key? "*"
|
178
|
+
return [root["*"], index, root]
|
179
|
+
end
|
180
|
+
|
181
|
+
[false, index, root]
|
182
|
+
end
|
183
|
+
|
184
|
+
#
|
185
|
+
# Checks a tag for standard naming scheme
|
186
|
+
#
|
187
|
+
# @param [String] tag the tag to check
|
188
|
+
#
|
189
|
+
# @return [void] nothing
|
190
|
+
#
|
191
|
+
def check_tag(tag)
|
192
|
+
result, pos, root = recursive_check_tag(tag)
|
193
|
+
return if result
|
194
|
+
|
195
|
+
valid_prefix = (pos > 0) ? tag[0..(pos-1)].join(".") + "." : ""
|
196
|
+
|
197
|
+
puts "The prefix `#{tag[0..pos].join('.')}' does not follow the standard format"
|
198
|
+
puts "The expected prefixes at this level are:"
|
199
|
+
root.keys.each do |key|
|
200
|
+
if root[:key] == false
|
201
|
+
puts "- #{valid_prefix}#{key}"
|
202
|
+
else
|
203
|
+
puts " #{valid_prefix}#{key}"
|
204
|
+
end
|
205
|
+
end
|
206
|
+
end
|
207
|
+
|
208
|
+
#
|
209
|
+
# Checks for names to match expected naming format
|
210
|
+
#
|
211
|
+
# @return [True] warnings to not return false
|
212
|
+
#
|
213
|
+
def pre_lint(pattern, _options)
|
214
|
+
return true unless pattern.is_a? PatternBase
|
215
|
+
|
216
|
+
pattern.each(true) do |pat|
|
217
|
+
next unless pat.arguments[:tag_as]
|
218
|
+
|
219
|
+
pat.arguments[:tag_as].split(" ").each { |tag| check_tag(tag.split(".")) }
|
220
|
+
end
|
221
|
+
|
222
|
+
true
|
223
|
+
end
|
224
|
+
end
|
225
|
+
|
226
|
+
Grammar.register_linter(StandardNaming.new)
|