summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/prism/ffi.rb9
-rw-r--r--prism/extension.c53
-rw-r--r--prism/util/pm_string.c7
-rw-r--r--test/prism/parse_test.rb85
4 files changed, 133 insertions, 21 deletions
diff --git a/lib/prism/ffi.rb b/lib/prism/ffi.rb
index 12177450f4..617c469df6 100644
--- a/lib/prism/ffi.rb
+++ b/lib/prism/ffi.rb
@@ -160,8 +160,13 @@ module Prism
pointer = FFI::MemoryPointer.new(SIZEOF)
begin
- raise unless LibRubyParser.pm_string_mapped_init(pointer, filepath)
- yield new(pointer)
+ raise TypeError unless filepath.is_a?(String)
+
+ if LibRubyParser.pm_string_mapped_init(pointer, filepath)
+ yield new(pointer)
+ else
+ raise SystemCallError.new(filepath, FFI.errno)
+ end
ensure
LibRubyParser.pm_string_free(pointer)
pointer.free
diff --git a/prism/extension.c b/prism/extension.c
index 7cad38404e..c20ce5b525 100644
--- a/prism/extension.c
+++ b/prism/extension.c
@@ -1,5 +1,9 @@
#include "prism/extension.h"
+#ifdef _WIN32
+#include <ruby/win32.h>
+#endif
+
// NOTE: this file should contain only bindings. All non-trivial logic should be
// in libprism so it can be shared its the various callers.
@@ -212,20 +216,29 @@ string_options(int argc, VALUE *argv, pm_string_t *input, pm_options_t *options)
/**
* Read options for methods that look like (filepath, **options).
*/
-static bool
+static void
file_options(int argc, VALUE *argv, pm_string_t *input, pm_options_t *options) {
VALUE filepath;
VALUE keywords;
rb_scan_args(argc, argv, "1:", &filepath, &keywords);
+ Check_Type(filepath, T_STRING);
+
extract_options(options, filepath, keywords);
- if (!pm_string_mapped_init(input, (const char *) pm_string_source(&options->filepath))) {
+ const char * string_source = (const char *) pm_string_source(&options->filepath);
+
+ if (!pm_string_mapped_init(input, string_source)) {
pm_options_free(options);
- return false;
- }
- return true;
+#ifdef _WIN32
+ int e = rb_w32_map_errno(GetLastError());
+#else
+ int e = errno;
+#endif
+
+ rb_syserr_fail(e, string_source);
+ }
}
/******************************************************************************/
@@ -299,7 +312,8 @@ static VALUE
dump_file(int argc, VALUE *argv, VALUE self) {
pm_string_t input;
pm_options_t options = { 0 };
- if (!file_options(argc, argv, &input, &options)) return Qnil;
+
+ file_options(argc, argv, &input, &options);
VALUE value = dump_input(&input, &options);
pm_string_free(&input);
@@ -609,7 +623,8 @@ static VALUE
lex_file(int argc, VALUE *argv, VALUE self) {
pm_string_t input;
pm_options_t options = { 0 };
- if (!file_options(argc, argv, &input, &options)) return Qnil;
+
+ file_options(argc, argv, &input, &options);
VALUE value = parse_lex_input(&input, &options, false);
pm_string_free(&input);
@@ -710,7 +725,8 @@ static VALUE
parse_file(int argc, VALUE *argv, VALUE self) {
pm_string_t input;
pm_options_t options = { 0 };
- if (!file_options(argc, argv, &input, &options)) return Qnil;
+
+ file_options(argc, argv, &input, &options);
VALUE value = parse_input(&input, &options);
pm_string_free(&input);
@@ -770,7 +786,8 @@ static VALUE
parse_file_comments(int argc, VALUE *argv, VALUE self) {
pm_string_t input;
pm_options_t options = { 0 };
- if (!file_options(argc, argv, &input, &options)) return Qnil;
+
+ file_options(argc, argv, &input, &options);
VALUE value = parse_input_comments(&input, &options);
pm_string_free(&input);
@@ -824,7 +841,8 @@ static VALUE
parse_lex_file(int argc, VALUE *argv, VALUE self) {
pm_string_t input;
pm_options_t options = { 0 };
- if (!file_options(argc, argv, &input, &options)) return Qnil;
+
+ file_options(argc, argv, &input, &options);
VALUE value = parse_lex_input(&input, &options, true);
pm_string_free(&input);
@@ -881,7 +899,8 @@ static VALUE
parse_file_success_p(int argc, VALUE *argv, VALUE self) {
pm_string_t input;
pm_options_t options = { 0 };
- if (!file_options(argc, argv, &input, &options)) return Qnil;
+
+ file_options(argc, argv, &input, &options);
VALUE result = parse_input_success_p(&input, &options);
pm_string_free(&input);
@@ -959,7 +978,17 @@ profile_file(VALUE self, VALUE filepath) {
pm_string_t input;
const char *checked = check_string(filepath);
- if (!pm_string_mapped_init(&input, checked)) return Qnil;
+ Check_Type(filepath, T_STRING);
+
+ if (!pm_string_mapped_init(&input, checked)) {
+#ifdef _WIN32
+ int e = rb_w32_map_errno(GetLastError());
+#else
+ int e = errno;
+#endif
+
+ rb_syserr_fail(e, checked);
+ }
pm_options_t options = { 0 };
pm_options_filepath_set(&options, checked);
diff --git a/prism/util/pm_string.c b/prism/util/pm_string.c
index f4d3033a1b..e67fcee0ec 100644
--- a/prism/util/pm_string.c
+++ b/prism/util/pm_string.c
@@ -65,7 +65,6 @@ pm_string_mapped_init(pm_string_t *string, const char *filepath) {
HANDLE file = CreateFile(filepath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (file == INVALID_HANDLE_VALUE) {
- perror("CreateFile failed");
return false;
}
@@ -73,7 +72,6 @@ pm_string_mapped_init(pm_string_t *string, const char *filepath) {
DWORD file_size = GetFileSize(file, NULL);
if (file_size == INVALID_FILE_SIZE) {
CloseHandle(file);
- perror("GetFileSize failed");
return false;
}
@@ -90,7 +88,6 @@ pm_string_mapped_init(pm_string_t *string, const char *filepath) {
HANDLE mapping = CreateFileMapping(file, NULL, PAGE_READONLY, 0, 0, NULL);
if (mapping == NULL) {
CloseHandle(file);
- perror("CreateFileMapping failed");
return false;
}
@@ -100,7 +97,6 @@ pm_string_mapped_init(pm_string_t *string, const char *filepath) {
CloseHandle(file);
if (source == NULL) {
- perror("MapViewOfFile failed");
return false;
}
@@ -110,7 +106,6 @@ pm_string_mapped_init(pm_string_t *string, const char *filepath) {
// Open the file for reading
int fd = open(filepath, O_RDONLY);
if (fd == -1) {
- perror("open");
return false;
}
@@ -118,7 +113,6 @@ pm_string_mapped_init(pm_string_t *string, const char *filepath) {
struct stat sb;
if (fstat(fd, &sb) == -1) {
close(fd);
- perror("fstat");
return false;
}
@@ -135,7 +129,6 @@ pm_string_mapped_init(pm_string_t *string, const char *filepath) {
source = mmap(NULL, size, PROT_READ, MAP_PRIVATE, fd, 0);
if (source == MAP_FAILED) {
- perror("Map failed");
return false;
}
diff --git a/test/prism/parse_test.rb b/test/prism/parse_test.rb
index 2624315008..3a2bc3716f 100644
--- a/test/prism/parse_test.rb
+++ b/test/prism/parse_test.rb
@@ -69,11 +69,96 @@ module Prism
assert_equal 5, tokens.length
end
+ def test_dump_file
+ assert_nothing_raised do
+ Prism.dump_file(__FILE__)
+ end
+
+ error = assert_raise Errno::ENOENT do
+ Prism.dump_file("idontexist.rb")
+ end
+
+ assert_equal "No such file or directory - idontexist.rb", error.message
+
+ assert_raise TypeError do
+ Prism.dump_file(nil)
+ end
+ end
+
+ def test_lex_file
+ assert_nothing_raised do
+ Prism.lex_file(__FILE__)
+ end
+
+ error = assert_raise Errno::ENOENT do
+ Prism.lex_file("idontexist.rb")
+ end
+
+ assert_equal "No such file or directory - idontexist.rb", error.message
+
+ assert_raise TypeError do
+ Prism.lex_file(nil)
+ end
+ end
+
def test_parse_lex_file
node, tokens = Prism.parse_lex_file(__FILE__).value
assert_kind_of ProgramNode, node
refute_empty tokens
+
+ error = assert_raise Errno::ENOENT do
+ Prism.parse_lex_file("idontexist.rb")
+ end
+
+ assert_equal "No such file or directory - idontexist.rb", error.message
+
+ assert_raise TypeError do
+ Prism.parse_lex_file(nil)
+ end
+ end
+
+ def test_parse_file
+ node = Prism.parse_file(__FILE__).value
+ assert_kind_of ProgramNode, node
+
+ error = assert_raise Errno::ENOENT do
+ Prism.parse_file("idontexist.rb")
+ end
+
+ assert_equal "No such file or directory - idontexist.rb", error.message
+
+ assert_raise TypeError do
+ Prism.parse_file(nil)
+ end
+ end
+
+ def test_parse_file_success
+ assert_predicate Prism.parse_file_comments(__FILE__), :any?
+
+ error = assert_raise Errno::ENOENT do
+ Prism.parse_file_comments("idontexist.rb")
+ end
+
+ assert_equal "No such file or directory - idontexist.rb", error.message
+
+ assert_raise TypeError do
+ Prism.parse_file_comments(nil)
+ end
+ end
+
+ def test_parse_file_comments
+ assert_predicate Prism.parse_file_comments(__FILE__), :any?
+
+ error = assert_raise Errno::ENOENT do
+ Prism.parse_file_comments("idontexist.rb")
+ end
+
+ assert_equal "No such file or directory - idontexist.rb", error.message
+
+ assert_raise TypeError do
+ Prism.parse_file_comments(nil)
+ end
end
# To accurately compare against Ripper, we need to make sure that we're