-
Notifications
You must be signed in to change notification settings - Fork 21
/
Copy pathvalidation_provider.rb
128 lines (112 loc) · 5.1 KB
/
validation_provider.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
# frozen_string_literal: true
require 'puppet-lint'
module PuppetLanguageServer
module Manifest
module ValidationProvider
# Similar to 'validate' this will run puppet-lint and returns
# the manifest with any fixes applied
#
# Returns:
# [ <Int> Number of problems fixed,
# <String> New Content
# ]
def self.fix_validate_errors(content)
module_root = PuppetLanguageServer::DocumentStore.store_root_path
linter_options = nil
if module_root.nil?
linter_options = PuppetLint::OptParser.build
else
Dir.chdir(module_root.to_s) { linter_options = PuppetLint::OptParser.build }
end
linter_options.parse!(['--fix'])
linter = PuppetLint::Checks.new
linter.load_data(nil, content)
problems = linter.run(nil, content)
problems_fixed = problems.nil? ? 0 : problems.count { |item| item[:kind] == :fixed }
[problems_fixed, linter.manifest]
end
def self.validate(content, options = {})
options = {
:max_problems => 100,
:tasks_mode => false
}.merge(options)
result = []
# TODO: Need to implement max_problems
problems = 0
module_root = PuppetLanguageServer::DocumentStore.store_root_path
linter_options = nil
if module_root.nil?
linter_options = PuppetLint::OptParser.build
else
Dir.chdir(module_root.to_s) { linter_options = PuppetLint::OptParser.build }
end
linter_options.parse!([])
begin
linter = PuppetLint::Checks.new
linter.load_data(nil, content)
problems = linter.run(nil, content)
unless problems.nil?
problems.each do |problem|
# Syntax errors are better handled by the puppet parser, not puppet lint
next if problem[:kind] == :error && problem[:check] == :syntax
# Ignore linting errors what were ignored by puppet-lint
next if problem[:kind] == :ignored
severity = case problem[:kind]
when :error
LSP::DiagnosticSeverity::ERROR
when :warning
LSP::DiagnosticSeverity::WARNING
else
LSP::DiagnosticSeverity::HINT
end
endpos = problem[:column] - 1
endpos = problem[:column] - 1 + problem[:token].to_manifest.length unless problem[:token].nil? || problem[:token].value.nil?
result << LSP::Diagnostic.new('severity' => severity,
'code' => problem[:check].to_s,
'range' => LSP.create_range(problem[:line] - 1, problem[:column] - 1, problem[:line] - 1, endpos),
'source' => 'Puppet',
'message' => problem[:message])
end
end
# rubocop:disable Lint/HandleExceptions
rescue StandardError
# If anything catastrophic happens we resort to puppet parsing anyway
end
# rubocop:enable Lint/HandleExceptions
# TODO: Should I wrap this thing in a big rescue block?
Puppet[:code] = content
env = Puppet.lookup(:current_environment)
loaders = Puppet::Pops::Loaders.new(env)
Puppet.override({ loaders: loaders }, 'For puppet parser validate') do
begin
validation_environment = env
$PuppetParserMutex.synchronize do # rubocop:disable Style/GlobalVars
begin
original_taskmode = Puppet[:tasks] if Puppet.tasks_supported?
Puppet[:tasks] = options[:tasks_mode] if Puppet.tasks_supported?
validation_environment.check_for_reparse
validation_environment.known_resource_types.clear
ensure
Puppet[:tasks] = original_taskmode if Puppet.tasks_supported?
end
end
rescue StandardError => e
# Sometimes the error is in the cause not the root object itself
e = e.cause if !e.respond_to?(:line) && e.respond_to?(:cause)
ex_line = e.respond_to?(:line) && !e.line.nil? ? e.line - 1 : nil # Line numbers from puppet exceptions are base 1
ex_pos = e.respond_to?(:pos) && !e.pos.nil? ? e.pos : nil # Pos numbers from puppet are base 1
message = e.respond_to?(:message) ? e.message : nil
message = e.basic_message if message.nil? && e.respond_to?(:basic_message)
unless ex_line.nil? || ex_pos.nil? || message.nil?
result << LSP::Diagnostic.new('severity' => LSP::DiagnosticSeverity::ERROR,
'range' => LSP.create_range(ex_line, ex_pos, ex_line, ex_pos + 1),
'source' => 'Puppet',
'message' => message)
end
end
end
result
end
end
end
end