Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: crystal-lang/crystal
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: f7fff74057a5
Choose a base ref
...
head repository: crystal-lang/crystal
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 89fe6b78bab1
Choose a head ref
  • 2 commits
  • 3 files changed
  • 1 contributor

Commits on Jul 31, 2016

  1. Compiler: simplified a bit suggestions.cr

    Ary Borenszweig committed Jul 31, 2016
    Copy the full SHA
    dd4fd7c View commit details
  2. Compiler: fixed path lookup relative to free variable

    Ary Borenszweig committed Jul 31, 2016
    Copy the full SHA
    89fe6b7 View commit details
Showing with 42 additions and 43 deletions.
  1. +11 −0 spec/compiler/semantic/def_spec.cr
  2. +30 −42 src/compiler/crystal/semantic/suggestions.cr
  3. +1 −1 src/compiler/crystal/semantic/type_lookup.cr
11 changes: 11 additions & 0 deletions spec/compiler/semantic/def_spec.cr
Original file line number Diff line number Diff line change
@@ -388,4 +388,15 @@ describe "Semantic: def" do
foo("")
)) { int32 }
end

it "doesn't find type in namespace through free var" do
assert_error %(
def foo(x : T)
T::String
end
foo(1)
),
"undefined constant T::String"
end
end
72 changes: 30 additions & 42 deletions src/compiler/crystal/semantic/suggestions.cr
Original file line number Diff line number Diff line change
@@ -2,35 +2,49 @@ require "../types"

module Crystal
class Type
SuggestableDefName = /\A[a-z_]/

def lookup_similar_path(node : Path)
(node.global? ? program : self).lookup_similar_path(node.names)
end

def lookup_similar_path(names : Array, lookup_in_namespace = true)
nil
end
def lookup_similar_path(names : Array(String), lookup_in_namespace = true)
type = self
names.each_with_index do |name, idx|
previous_type = type
type = previous_type.types?.try &.[name]?
unless type
best_match = Levenshtein.find(name.downcase) do |finder|
previous_type.types?.try &.each_key do |type_name|
finder.test(type_name.downcase, type_name)
end
end

def lookup_similar_def(name, args_size, block)
nil
end
if best_match
return (names[0...idx] + [best_match]).join "::"
else
break
end
end
end

def lookup_similar_def_name(name, args_size, block)
lookup_similar_def(name, args_size, block).try &.name
end
end
parents.try &.each do |parent|
match = parent.lookup_similar_path(names, false)
return match if match
end

module MatchesLookup
SuggestableName = /\A[a-z_]/
lookup_in_namespace && self != program ? namespace.lookup_similar_path(names) : nil
end

def lookup_similar_def(name, args_size, block)
return nil unless name =~ SuggestableName
return nil unless name =~ SuggestableDefName

if (defs = self.defs)
best_def = nil
best_match = nil
Levenshtein.find(name) do |finder|
defs.each do |def_name, hash|
if def_name =~ SuggestableName
if def_name =~ SuggestableDefName
hash.each do |def_with_metadata|
if def_with_metadata.max_size == args_size && def_with_metadata.yields == !!block && def_with_metadata.def.name != name
finder.test(def_name)
@@ -53,35 +67,9 @@ module Crystal

nil
end
end

class ModuleType
def lookup_similar_path(names : Array, lookup_in_namespace = true)
type = self
names.each_with_index do |name, idx|
previous_type = type
type = previous_type.types?.try &.[name]?
unless type
best_match = Levenshtein.find(name.downcase) do |finder|
previous_type.types?.try &.each_key do |type_name|
finder.test(type_name.downcase, type_name)
end
end

if best_match
return (names[0...idx] + [best_match]).join "::"
else
break
end
end
end

parents.each do |parent|
match = parent.lookup_similar_path(names, false)
return match if match
end

lookup_in_namespace && self != program ? namespace.lookup_similar_path(names) : nil
def lookup_similar_def_name(name, args_size, block)
lookup_similar_def(name, args_size, block).try &.name
end
end

2 changes: 1 addition & 1 deletion src/compiler/crystal/semantic/type_lookup.cr
Original file line number Diff line number Diff line change
@@ -94,7 +94,7 @@ class Crystal::Type
if node.names.size == 1
return free_var
elsif free_var.is_a?(Type)
type = free_var.lookup_path(node.names[1..-1])
type = free_var.lookup_path(node.names[1..-1], lookup_in_namespace: false)
end
else
type = @root.lookup_path(node)