Class: Solargraph::TypeChecker

Inherits:
Object
  • Object
show all
Includes:
ParserGem::NodeMethods
Defined in:
lib/solargraph/type_checker.rb,
lib/solargraph/type_checker/rules.rb,
lib/solargraph/type_checker/problem.rb

Overview

A static analysis tool for validating data types.

Defined Under Namespace

Classes: Problem, Rules

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(filename, api_map: nil, level: :normal, workspace: filename ? Workspace.new(File.dirname(filename)) : nil, rules: workspace ? workspace.rules(level) : Rules.new(level, {})) ⇒ TypeChecker

Returns a new instance of TypeChecker.

Parameters:

  • filename (String, nil)
  • api_map (ApiMap, nil) (defaults to: nil)
  • level (Symbol) (defaults to: :normal)

    Don’t complain about anything above this level

  • workspace (Workspace, nil) (defaults to: filename ? Workspace.new(File.dirname(filename)) : nil)

    Workspace to use for loading type checker rules modified by user config

  • rules (Rules) (defaults to: workspace ? workspace.rules(level) : Rules.new(level, {}))

    Type checker rules object



29
30
31
32
33
34
35
36
37
38
39
40
41
# File 'lib/solargraph/type_checker.rb', line 29

def initialize filename,
               api_map: nil,
               level: :normal,
               workspace: filename ? Workspace.new(File.dirname(filename)) : nil,
               rules: workspace ? workspace.rules(level) : Rules.new(level, {})
  @filename = filename
  # @todo Smarter directory resolution
  @api_map = api_map || Solargraph::ApiMap.load(File.dirname(filename),
                                                loose_unions: !rules.require_all_unique_types_support_call?)
  @rules = rules
  # @type [Array<Range>]
  @marked_ranges = []
end

Instance Attribute Details

#api_mapApiMap (readonly)

Returns:



21
22
23
# File 'lib/solargraph/type_checker.rb', line 21

def api_map
  @api_map
end

#filenameString (readonly)

Returns:

  • (String)


15
16
17
# File 'lib/solargraph/type_checker.rb', line 15

def filename
  @filename
end

#rulesRules (readonly)

Returns:



18
19
20
# File 'lib/solargraph/type_checker.rb', line 18

def rules
  @rules
end

Class Method Details

.load(filename, level = :normal) ⇒ self

Parameters:

  • filename (String)
  • level (Symbol) (defaults to: :normal)

Returns:

  • (self)


102
103
104
105
106
107
108
109
# File 'lib/solargraph/type_checker.rb', line 102

def load filename, level = :normal
  source = Solargraph::Source.load(filename)
  rules = Rules.new(level, {})
  api_map = Solargraph::ApiMap.new(loose_unions:
                                     !rules.require_all_unique_types_support_call?)
  api_map.map(source)
  new(filename, api_map: api_map, level: level, rules: rules)
end

.load_string(code, filename = nil, level = :normal, api_map: nil) ⇒ self

Parameters:

  • code (String)
  • filename (String, nil) (defaults to: nil)
  • level (Symbol) (defaults to: :normal)
  • api_map (Solargraph::ApiMap, nil) (defaults to: nil)

Returns:

  • (self)


116
117
118
119
120
121
122
123
124
# File 'lib/solargraph/type_checker.rb', line 116

def load_string code, filename = nil, level = :normal, api_map: nil
  source = Solargraph::Source.load_string(code, filename)
  rules = Rules.new(level, {})
  api_map ||= Solargraph::ApiMap.new(loose_unions:
                                       !rules.require_all_unique_types_support_call?)
  # @sg-ignore flow sensitive typing needs better handling of ||= on lvars
  api_map.map(source)
  new(filename, api_map: api_map, level: level, rules: rules)
end

Instance Method Details

#arg_conforms_to?(inferred, expected) ⇒ Boolean

Parameters:

Returns:

  • (Boolean)


61
62
63
# File 'lib/solargraph/type_checker.rb', line 61

def arg_conforms_to? inferred, expected
  conforms_to?(inferred, expected, :method_call)
end

#assignment_conforms_to?(inferred, expected) ⇒ Boolean

Parameters:

Returns:

  • (Boolean)


67
68
69
# File 'lib/solargraph/type_checker.rb', line 67

def assignment_conforms_to? inferred, expected
  conforms_to?(inferred, expected, :assignment)
end

#conforms_to?(inferred, expected, scenario) ⇒ Boolean

Parameters:

Returns:

  • (Boolean)


74
75
76
77
78
79
80
81
82
83
84
# File 'lib/solargraph/type_checker.rb', line 74

def conforms_to? inferred, expected, scenario
  rules_arr = []
  rules_arr << :allow_empty_params unless rules.require_inferred_type_params?
  rules_arr << :allow_any_match unless rules.require_all_unique_types_match_expected?
  rules_arr << :allow_undefined unless rules.require_no_undefined_args?
  rules_arr << :allow_unresolved_generic unless rules.require_generics_resolved?
  rules_arr << :allow_unmatched_interface unless rules.require_interfaces_resolved?
  rules_arr << :allow_reverse_match unless rules.require_downcasts?
  inferred.conforms_to?(api_map, expected, scenario,
                        rules_arr)
end

#problemsArray<Problem>

Returns:



87
88
89
90
91
92
93
94
95
96
# File 'lib/solargraph/type_checker.rb', line 87

def problems
  @problems ||= begin
    all = method_tag_problems
          .concat(variable_type_tag_problems)
          .concat(const_problems)
          .concat(call_problems)
    unignored = without_ignored(all)
    unignored.concat(unneeded_sgignore_problems)
  end
end

#return_type_conforms_to?(inferred, expected) ⇒ Boolean

Parameters:

Returns:

  • (Boolean)


55
56
57
# File 'lib/solargraph/type_checker.rb', line 55

def return_type_conforms_to? inferred, expected
  conforms_to?(inferred, expected, :return_type)
end

#sourceSource

Returns:



49
50
51
# File 'lib/solargraph/type_checker.rb', line 49

def source
  source_map.source
end

#source_mapSourceMap

Returns:



44
45
46
# File 'lib/solargraph/type_checker.rb', line 44

def source_map
  @source_map ||= api_map.source_map(filename)
end