Module: PuppetLanguageServer::Manifest::ValidationProvider

Defined in:
lib/puppet-languageserver/manifest/validation_provider.rb

Class Method Summary collapse

Class Method Details

.fix_validate_errors(session_state, content) ⇒ Object

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
]


14
15
16
17
18
19
20
21
22
23
24
# File 'lib/puppet-languageserver/manifest/validation_provider.rb', line 14

def self.fix_validate_errors(session_state, content)
  init_puppet_lint(session_state.documents.store_root_path, ['--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

.validate(session_state, content, options = {}) ⇒ Object



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
# File 'lib/puppet-languageserver/manifest/validation_provider.rb', line 26

def self.validate(session_state, content, options = {})
  options = {
    max_problems: 100,
    tasks_mode: false
  }.merge(options)

  result = []
  # TODO: Need to implement max_problems
  problems = 0

  init_puppet_lint(session_state.documents.store_root_path, [])

  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
  rescue StandardError
    # If anything catastrophic happens we resort to puppet parsing anyway
  end
  # 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
    validation_environment = env
    $PuppetParserMutex.synchronize do # rubocop:disable Style/GlobalVars
      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
  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

  result
end