Class: RBS::TypeAliasDependency

Inherits:
Object
  • Object
show all
Defined in:
sig/type_alias_dependency.rbs,
lib/rbs/type_alias_dependency.rb

Overview

TypeAliasDependency calculates the dependencies between type aliases

The dependencies are normalized automatically.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(env:) ⇒ TypeAliasDependency

Returns a new instance of TypeAliasDependency.

Parameters:



14
15
16
# File 'lib/rbs/type_alias_dependency.rb', line 14

def initialize(env:)
  @env = env
end

Instance Attribute Details

#dependenciesHash[TypeName, Hash[TypeName, bool]] (readonly)

A hash table from type alias name to a hash name with keys of transitive dependencies

The source type name and dependencies are normalized.

Returns:



12
13
14
# File 'lib/rbs/type_alias_dependency.rb', line 12

def dependencies
  @dependencies
end

#direct_dependenciesHash[TypeName, Set[TypeName]] (readonly)

A hash table from type alias name to it's direct dependencies

The source type name and dependencies are normalized.

Returns:



9
10
11
# File 'lib/rbs/type_alias_dependency.rb', line 9

def direct_dependencies
  @direct_dependencies
end

#envEnvironment (readonly)

Returns the value of attribute env.

Returns:



5
6
7
# File 'lib/rbs/type_alias_dependency.rb', line 5

def env
  @env
end

Instance Method Details

#build_dependenciesvoid

This method returns an undefined value.



27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
# File 'lib/rbs/type_alias_dependency.rb', line 27

def build_dependencies
  return if @direct_dependencies

  # Initialize hash(a directed graph)
  @direct_dependencies = {}
  # Initialize dependencies as an empty hash
  @dependencies = {}
  # Iterate over alias declarations inserted into environment
  env.type_alias_decls.each do |name, entry|
    # Construct a directed graph by recursively extracting type aliases
    @direct_dependencies[name] = direct_dependency(entry.decl.type)
    # Initialize dependencies with an empty hash
    @dependencies[name] = {}
  end
end

#circular_definition?(alias_name) ⇒ Boolean

Returns true if given type alias is circular

Normalized given type name automatically.

Parameters:

Returns:

  • (Boolean)


19
20
21
22
23
24
25
# File 'lib/rbs/type_alias_dependency.rb', line 19

def circular_definition?(alias_name)
  # Construct transitive closure, if not constructed already
  transitive_closure() unless @dependencies

  alias_name = env.normalize_type_name!(alias_name)
  @dependencies[alias_name][alias_name]
end

#dependencies_of(name) ⇒ Set[TypeName]

Returns the set of dependencies from the given type name

Given type name will be normalized automatically. Returns normalized type names.

Parameters:

Returns:



41
42
43
44
# File 'sig/type_alias_dependency.rbs', line 41

def dependencies_of(name)
  name = env.normalize_type_name!(name)
  @dependencies[name].each_key.to_set
end

#dependency(start, vertex, nested = nil) ⇒ void

This method returns an undefined value.

Recursive function to construct transitive closure

Parameters:



81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
# File 'lib/rbs/type_alias_dependency.rb', line 81

def dependency(start, vertex, nested = nil)
  if (start == vertex)
    if (@direct_dependencies[start].include?(vertex) || nested)
      # Mark a vertex as connected to itself
      # if it is connected as an edge || a path(traverse multiple edges)
      @dependencies[start][vertex] = true
    end
  else
    # Mark a pair of vertices as connected while recursively performing DFS
    @dependencies[start][vertex] = true
  end

  # Iterate over the direct dependencies of the vertex
  @direct_dependencies[vertex]&.each do |type_name|
    # Invoke the function unless it is already checked
    dependency(start, type_name, start == type_name) unless @dependencies[start][type_name]
  end
end

#direct_dependencies_of(name) ⇒ Set[TypeName]

Returns the set of direct dependencies from the given type name

Given type name will be normalized automatically. Returns normalized type names.

Parameters:

Returns:



34
35
36
37
# File 'sig/type_alias_dependency.rbs', line 34

def direct_dependencies_of(name)
  name = env.normalize_type_name!(name)
  @direct_dependencies[name]
end

#direct_dependency(type, result = Set[]) ⇒ Set[TypeName]

Constructs directed graph recursively

Parameters:

  • (Types::t `type`)
  • result (Set[TypeName]) (defaults to: Set[])

Returns:



65
66
67
68
69
70
71
72
73
74
75
76
77
78
# File 'lib/rbs/type_alias_dependency.rb', line 65

def direct_dependency(type, result = Set[])
  case type
  when RBS::Types::Union, RBS::Types::Intersection, RBS::Types::Optional
    # Iterate over nested types & extract type aliases recursively
    type.each_type do |nested_type|
      direct_dependency(nested_type, result)
    end
  when RBS::Types::Alias
    # Append type name if the type is an alias
    result << env.normalize_type_name(type.name)
  end

  result
end

#transitive_closurevoid

This method returns an undefined value.



43
44
45
46
47
48
49
50
# File 'lib/rbs/type_alias_dependency.rb', line 43

def transitive_closure
  # Construct a graph of direct dependencies
  build_dependencies()
  # Construct transitive closure by using DFS(recursive technique)
  @direct_dependencies.each_key do |name|
    dependency(name, name)
  end
end