Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add to node parsing capabilities #54

Merged
merged 7 commits into from
Nov 25, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions lib/packwerk/node.rb
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ def constant_name(constant_node)
case type_of(constant_node)
when CONSTANT_ROOT_NAMESPACE
""
when CONSTANT, CONSTANT_ASSIGNMENT
when CONSTANT, CONSTANT_ASSIGNMENT, SELF
# (const nil :Foo)
# "Foo"
# (const (cbase) :Foo)
Expand All @@ -40,6 +40,8 @@ def constant_name(constant_node)
# "::Foo = 1"
# (casgn (lvar :a) :Foo (int 1))
# "a::Foo = 1"
# (casgn (self) :Foo (int 1))
# "self::Foo = 1"
namespace, name = constant_node.children
if namespace
[constant_name(namespace), name].join("::")
Expand Down Expand Up @@ -204,12 +206,13 @@ def value_from_hash(hash_node, key)
HASH_PAIR = :pair
METHOD_CALL = :send
MODULE = :module
SELF = :self
STRING = :str
SYMBOL = :sym

private_constant(
:BLOCK, :CLASS, :CONSTANT, :CONSTANT_ASSIGNMENT, :CONSTANT_ROOT_NAMESPACE, :HASH, :HASH_PAIR, :METHOD_CALL,
:MODULE, :STRING, :SYMBOL,
:MODULE, :SELF, :STRING, :SYMBOL,
)

def type_of(node)
Expand Down
4 changes: 2 additions & 2 deletions lib/packwerk/parsed_constant_definitions.rb
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@ def self.reference_qualifications(constant_name, namespace_path:)

fully_qualified_constant_name = "::#{constant_name}"

possible_namespaces = namespace_path.reduce([""]) do |acc, current|
acc << acc.last + "::" + current
possible_namespaces = namespace_path.each_with_object([""]) do |current, acc|
acc << "#{acc.last}::#{current}" if acc.last && current
end

possible_namespaces.map { |namespace| namespace + fully_qualified_constant_name }
Expand Down
7 changes: 7 additions & 0 deletions test/unit/parsed_constant_definitions_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,13 @@ class ParsedConstantDefinitionsTest < Minitest::Test
assert_equal ["::Order", "::Sales::Order", "::Sales::Internal::Order"].sort, qualifications.sort
end

test ".reference_qualifications generates all possible qualifications for a reference even when there are nil nodes in the namespace path" do
qualifications =
ParsedConstantDefinitions.reference_qualifications("Order", namespace_path: [nil, "Sales", "Internal"])

assert_equal ["::Order", "::Sales::Order", "::Sales::Internal::Order"].sort, qualifications.sort
end

private

def parse_code(string)
Expand Down
9 changes: 9 additions & 0 deletions test/unit/reference_extractor_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,15 @@ def setup
assert_equal "::Order::Extension", reference.constant.name
end

test "reports properly on 'self anchored' constants" do
references = process(
"class Entry; self::SOME_CONSTANT = :a; end",
"components/timeline/app/models/entry.rb"
)

assert_equal 0, references.count
end

test "handles inherited class constants in the surrounding namespace" do
references = process(
"module Sales; class Order < Error; end; end",
Expand Down