From b12e734347aabfc95ef7ad3ba830480c9c6ddc1f Mon Sep 17 00:00:00 2001 From: Ary Borenszweig Date: Wed, 8 May 2019 17:35:27 -0300 Subject: [PATCH 1/2] Compiler: fix require relative path resolution --- .../crystal_path/crystal_path_spec.cr | 3 + src/compiler/crystal/crystal_path.cr | 113 ++++++++++-------- 2 files changed, 64 insertions(+), 52 deletions(-) diff --git a/spec/compiler/crystal_path/crystal_path_spec.cr b/spec/compiler/crystal_path/crystal_path_spec.cr index b867733794c6..8cbe0ab8376d 100644 --- a/spec/compiler/crystal_path/crystal_path_spec.cr +++ b/spec/compiler/crystal_path/crystal_path_spec.cr @@ -96,6 +96,9 @@ describe Crystal::CrystalPath do assert_doesnt_find "./crystal_path_spec.cr", relative_to: "test_files/file_one.cr" assert_doesnt_find "../crystal_path/test_files/file_one" + # Don't find relative filenames in src or shards + assert_doesnt_find "../../src/file_three", relative_to: "test_files/test_folder/test_folder.cr" + it "prints an explanatory message for non-relative requires" do crystal_path = Crystal::CrystalPath.new(__DIR__) ex = expect_raises Exception, /If you're trying to require a shard/ do diff --git a/src/compiler/crystal/crystal_path.cr b/src/compiler/crystal/crystal_path.cr index e31495f6b0cb..031711948ded 100644 --- a/src/compiler/crystal/crystal_path.cr +++ b/src/compiler/crystal/crystal_path.cr @@ -45,60 +45,69 @@ module Crystal end private def find_in_path_relative_to_dir(filename, relative_to) - if relative_to.is_a?(String) - # Check if it's a wildcard. - if filename.ends_with?("/*") || (recursive = filename.ends_with?("/**")) - filename_dir_index = filename.rindex('/').not_nil! - filename_dir = filename[0..filename_dir_index] - relative_dir = "#{relative_to}/#{filename_dir}" - if File.exists?(relative_dir) - files = [] of String - gather_dir_files(relative_dir, files, recursive) - return files - end - else - relative_filename = "#{relative_to}/#{filename}" + return unless relative_to.is_a?(String) + + # Check if it's a wildcard. + if filename.ends_with?("/*") || (recursive = filename.ends_with?("/**")) + filename_dir_index = filename.rindex('/').not_nil! + filename_dir = filename[0..filename_dir_index] + relative_dir = "#{relative_to}/#{filename_dir}" + if File.exists?(relative_dir) + files = [] of String + gather_dir_files(relative_dir, files, recursive) + return files + end - # Check if .cr file exists. - relative_filename_cr = relative_filename.ends_with?(".cr") ? relative_filename : "#{relative_filename}.cr" - if File.exists?(relative_filename_cr) - return make_relative_unless_absolute relative_filename_cr - end + return nil + end - if slash_index = filename.index('/') - # If it's "foo/bar/baz", check if "foo/src/bar/baz.cr" exists (for a shard, non-namespaced structure) - before_slash, after_slash = filename.split('/', 2) - absolute_filename = make_relative_unless_absolute("#{relative_to}/#{before_slash}/src/#{after_slash}.cr") - return absolute_filename if File.exists?(absolute_filename) - - # Then check if "foo/src/foo/bar/baz.cr" exists (for a shard, namespaced structure) - absolute_filename = make_relative_unless_absolute("#{relative_to}/#{before_slash}/src/#{before_slash}/#{after_slash}.cr") - return absolute_filename if File.exists?(absolute_filename) - - # If it's "foo/bar/baz", check if "foo/bar/baz/baz.cr" exists (std, nested) - basename = File.basename(relative_filename) - absolute_filename = make_relative_unless_absolute("#{relative_to}/#{filename}/#{basename}.cr") - return absolute_filename if File.exists?(absolute_filename) - - # If it's "foo/bar/baz", check if "foo/src/foo/bar/baz/baz.cr" exists (shard, non-namespaced, nested) - absolute_filename = make_relative_unless_absolute("#{relative_to}/#{before_slash}/src/#{after_slash}/#{after_slash}.cr") - return absolute_filename if File.exists?(absolute_filename) - - # If it's "foo/bar/baz", check if "foo/src/foo/bar/baz/baz.cr" exists (shard, namespaced, nested) - absolute_filename = make_relative_unless_absolute("#{relative_to}/#{before_slash}/src/#{before_slash}/#{after_slash}/#{after_slash}.cr") - return absolute_filename if File.exists?(absolute_filename) - else - basename = File.basename(relative_filename) - - # If it's "foo", check if "foo/foo.cr" exists (for the std, nested) - absolute_filename = make_relative_unless_absolute("#{relative_filename}/#{basename}.cr") - return absolute_filename if File.exists?(absolute_filename) - - # If it's "foo", check if "foo/src/foo.cr" exists (for a shard) - absolute_filename = make_relative_unless_absolute("#{relative_filename}/src/#{basename}.cr") - return absolute_filename if File.exists?(absolute_filename) - end - end + relative_filename = "#{relative_to}/#{filename}" + + # Check if .cr file exists. + relative_filename_cr = relative_filename.ends_with?(".cr") ? relative_filename : "#{relative_filename}.cr" + if File.exists?(relative_filename_cr) + return make_relative_unless_absolute relative_filename_cr + end + + filename_is_relative = filename.starts_with?('.') + + if !filename_is_relative && (slash_index = filename.index('/')) + # If it's "foo/bar/baz", check if "foo/src/bar/baz.cr" exists (for a shard, non-namespaced structure) + before_slash, after_slash = filename.split('/', 2) + + absolute_filename = make_relative_unless_absolute("#{relative_to}/#{before_slash}/src/#{after_slash}.cr") + return absolute_filename if File.exists?(absolute_filename) + + # Then check if "foo/src/foo/bar/baz.cr" exists (for a shard, namespaced structure) + absolute_filename = make_relative_unless_absolute("#{relative_to}/#{before_slash}/src/#{before_slash}/#{after_slash}.cr") + return absolute_filename if File.exists?(absolute_filename) + + # If it's "foo/bar/baz", check if "foo/bar/baz/baz.cr" exists (std, nested) + basename = File.basename(relative_filename) + absolute_filename = make_relative_unless_absolute("#{relative_to}/#{filename}/#{basename}.cr") + return absolute_filename if File.exists?(absolute_filename) + + # If it's "foo/bar/baz", check if "foo/src/foo/bar/baz/baz.cr" exists (shard, non-namespaced, nested) + absolute_filename = make_relative_unless_absolute("#{relative_to}/#{before_slash}/src/#{after_slash}/#{after_slash}.cr") + return absolute_filename if File.exists?(absolute_filename) + + # If it's "foo/bar/baz", check if "foo/src/foo/bar/baz/baz.cr" exists (shard, namespaced, nested) + absolute_filename = make_relative_unless_absolute("#{relative_to}/#{before_slash}/src/#{before_slash}/#{after_slash}/#{after_slash}.cr") + return absolute_filename if File.exists?(absolute_filename) + + return nil + end + + basename = File.basename(relative_filename) + + # If it's "foo", check if "foo/foo.cr" exists (for the std, nested) + absolute_filename = make_relative_unless_absolute("#{relative_filename}/#{basename}.cr") + return absolute_filename if File.exists?(absolute_filename) + + unless filename_is_relative + # If it's "foo", check if "foo/src/foo.cr" exists (for a shard) + absolute_filename = make_relative_unless_absolute("#{relative_filename}/src/#{basename}.cr") + return absolute_filename if File.exists?(absolute_filename) end nil From 2f53e5bcef3bf6aa6dd1ebf1236b1d42f56fa45f Mon Sep 17 00:00:00 2001 From: Ary Borenszweig Date: Fri, 10 May 2019 09:18:35 -0300 Subject: [PATCH 2/2] Fix a couple of wrong imports in specs --- spec/std/http/web_socket_spec.cr | 2 +- spec/std/kernel_spec.cr | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/spec/std/http/web_socket_spec.cr b/spec/std/http/web_socket_spec.cr index 12dd6a2041b2..5283a33d0986 100644 --- a/spec/std/http/web_socket_spec.cr +++ b/spec/std/http/web_socket_spec.cr @@ -2,7 +2,7 @@ require "./spec_helper" require "../spec_helper" require "http/web_socket" require "random/secure" -require "../../../support/ssl" +require "../../support/ssl" private def assert_text_packet(packet, size, final = false) assert_packet packet, HTTP::WebSocket::Protocol::Opcode::TEXT, size, final: final diff --git a/spec/std/kernel_spec.cr b/spec/std/kernel_spec.cr index bfe99b0f0223..c5fcfd16a373 100644 --- a/spec/std/kernel_spec.cr +++ b/spec/std/kernel_spec.cr @@ -1,5 +1,5 @@ require "spec" -require "../../spec_helper" +require "../spec_helper" describe "exit" do it "exits normally with status 0" do