Skip to content

Commit fa4c7ac

Browse files
committed
Re-enable Windows CI
1 parent 66f5d46 commit fa4c7ac

8 files changed

Lines changed: 83 additions & 36 deletions

File tree

.github/workflows/ci.yml

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,7 @@ jobs:
2727
strategy:
2828
fail-fast: false
2929
matrix:
30-
# TODO: Put back windows once we have figured how to compile Prism on it.
31-
# os: [shopify-ubuntu-latest, macos-latest, shopify-windows-latest]
32-
os: [shopify-ubuntu-latest, macos-latest]
30+
os: [shopify-ubuntu-latest, macos-latest, shopify-windows-latest]
3331
ruby: ["3.4"]
3432
runs-on: ${{ matrix.os }}
3533
name: Ruby ${{ matrix.ruby }} on ${{ matrix.os }}

Gemfile

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,4 +11,8 @@ gem "minitest"
1111
gem "rubocop"
1212
gem "rubocop-shopify"
1313
gem "extconf_compile_commands_json"
14-
gem "ruby_memcheck"
14+
15+
# Gems that aren't supported on Windows
16+
platforms :ruby do
17+
gem "ruby_memcheck"
18+
end

Rakefile

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ require "bundler/gem_tasks"
44
require "rubocop/rake_task"
55
require "rake/extensiontask"
66
require "rake/testtask"
7-
require "ruby_memcheck"
87

98
GEMSPEC = Gem::Specification.load("saturn.gemspec")
109

@@ -19,7 +18,13 @@ test_config = lambda do |t|
1918
t.test_files = FileList["test/**/*_test.rb"]
2019
end
2120
Rake::TestTask.new(ruby_test: :compile, &test_config)
22-
namespace(:ruby_test) { RubyMemcheck::TestTask.new(valgrind: :compile, &test_config) }
21+
22+
begin
23+
require "ruby_memcheck"
24+
namespace(:ruby_test) { RubyMemcheck::TestTask.new(valgrind: :compile, &test_config) }
25+
rescue LoadError
26+
# ruby_memcheck is not available on Windows
27+
end
2328

2429
RuboCop::RakeTask.new
2530

lib/saturn/location.rb

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,10 @@ def path
2424
uri = URI(@uri)
2525
raise Saturn::Error, "URI is not a file:// URI: #{@uri}" unless uri.scheme == "file"
2626

27-
uri.path
27+
path = uri.path
28+
# TODO: This has to go away once we have a proper URI abstraction
29+
path.delete_prefix!("/") if Gem.win_platform?
30+
path
2831
end
2932

3033
#: (other: BasicObject) -> Integer

rust/saturn/src/indexing.rs

Lines changed: 33 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,8 @@ pub fn collect_file_paths(paths: Vec<String>) -> (Vec<String>, Vec<Errors>) {
166166

167167
#[cfg(test)]
168168
mod tests {
169+
use std::path::PathBuf;
170+
169171
use super::*;
170172
use crate::test_utils::Context;
171173

@@ -190,18 +192,21 @@ mod tests {
190192
#[test]
191193
fn collect_all_documents() {
192194
let context = Context::new();
193-
context.touch("bar/baz.rb");
194-
context.touch("bar/qux.rb");
195-
context.touch("foo/bar.rb");
195+
let baz = Path::new("bar").join("baz.rb");
196+
let qux = Path::new("bar").join("qux.rb");
197+
let bar = Path::new("foo").join("bar.rb");
198+
context.touch(&baz);
199+
context.touch(&qux);
200+
context.touch(&bar);
196201

197202
let (paths, errors) = collect_document_paths(&context, &["foo", "bar"]);
198203

199204
assert_eq!(
200205
paths,
201206
vec![
202-
"bar/baz.rb".to_string(),
203-
"bar/qux.rb".to_string(),
204-
"foo/bar.rb".to_string()
207+
baz.to_str().unwrap().to_string(),
208+
qux.to_str().unwrap().to_string(),
209+
bar.to_str().unwrap().to_string()
205210
]
206211
);
207212
assert!(errors.is_empty());
@@ -210,13 +215,19 @@ mod tests {
210215
#[test]
211216
fn collect_some_documents_based_on_paths() {
212217
let context = Context::new();
213-
context.touch("bar/baz.rb");
214-
context.touch("bar/qux.rb");
215-
context.touch("foo/bar.rb");
218+
let baz = Path::new("bar").join("baz.rb");
219+
let qux = Path::new("bar").join("qux.rb");
220+
let bar = Path::new("foo").join("bar.rb");
216221

222+
context.touch(&baz);
223+
context.touch(&qux);
224+
context.touch(&bar);
217225
let (paths, errors) = collect_document_paths(&context, &["bar"]);
218226

219-
assert_eq!(paths, vec!["bar/baz.rb".to_string(), "bar/qux.rb".to_string()]);
227+
assert_eq!(
228+
paths,
229+
vec![baz.to_str().unwrap().to_string(), qux.to_str().unwrap().to_string()]
230+
);
220231
assert!(errors.is_empty());
221232
}
222233

@@ -239,30 +250,31 @@ mod tests {
239250
.map(std::string::ToString::to_string)
240251
.collect::<Vec<String>>(),
241252
vec![format!(
242-
"File read error: Path '{}/non_existing_path' does not exist",
243-
context.absolute_path().display()
253+
"File read error: Path '{}' does not exist",
254+
context.absolute_path_to("non_existing_path").display()
244255
)]
245256
);
246257
}
247258

248259
#[test]
249260
fn index_relative_paths() {
261+
let relative_path = Path::new("foo").join("bar.rb");
250262
let context = Context::new();
251-
context.touch("foo/bar.rb");
263+
context.touch(&relative_path);
252264

253265
let working_directory = std::env::current_dir().unwrap();
266+
let absolute_path = context.absolute_path_to("foo/bar.rb");
254267

255-
let dotdots = "../".repeat(working_directory.components().count());
268+
let mut dots = PathBuf::from("..");
256269

257-
let relative_path = dotdots
258-
+ context
259-
.absolute_path_to("foo/bar.rb")
260-
.to_string_lossy()
261-
.into_owned()
262-
.as_str();
270+
for _ in 0..working_directory.components().count() - 1 {
271+
dots = dots.join("..");
272+
}
273+
274+
let relative_to_pwd = &dots.join(absolute_path);
263275

264276
let mut graph = Graph::new();
265-
let errors = index_in_parallel(&mut graph, vec![relative_path]);
277+
let errors = index_in_parallel(&mut graph, vec![relative_to_pwd.to_str().unwrap().to_string()]);
266278

267279
assert!(errors.is_ok());
268280
assert_eq!(graph.documents().len(), 1);

test/definition_test.rb

Lines changed: 24 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ def foo; end
7777
refute_nil(def_a)
7878
location = def_a.location
7979
refute_nil(location)
80-
assert_equal("file://#{context.absolute_path_to("file1.rb")}", location.uri)
80+
assert_equal(context.uri_to("file1.rb"), location.uri)
8181
assert_equal(context.absolute_path_to("file1.rb"), location.path)
8282
assert_equal(1, location.start_line)
8383
assert_equal(1, location.start_column)
@@ -88,7 +88,7 @@ def foo; end
8888
refute_nil(def_foo)
8989
location = def_foo.location
9090
refute_nil(location)
91-
assert_equal("file://#{context.absolute_path_to("file1.rb")}", location.uri)
91+
assert_equal(context.uri_to("file1.rb"), location.uri)
9292
assert_equal(context.absolute_path_to("file1.rb"), location.path)
9393
assert_equal(2, location.start_line)
9494
assert_equal(3, location.start_column)
@@ -104,27 +104,44 @@ def test_definition_comments
104104
# Multi-line comment
105105
class Foo
106106
# Method comment
107-
def foo; end
107+
def bar; end
108108
end
109109
RUBY
110110

111111
graph = Saturn::Graph.new
112112
graph.index_all(context.glob("**/*.rb"))
113113

114-
comments = graph.documents.first.definitions.find { |d| d.name == "Foo" }.comments
114+
foo_comments = graph.documents.first.definitions.find { |d| d.name == "Foo" }.comments
115115
assert_equal(
116116
[
117117
"# This is a class comment (#{context.absolute_path_to("file1.rb")}:1:1-1:26)",
118118
"# Multi-line comment (#{context.absolute_path_to("file1.rb")}:2:1-2:21)",
119119
],
120-
comments.map { |c| "#{c.string} (#{c.location})" },
120+
foo_comments.map { |c| "#{c.string} (#{normalized_comment_location(c)})" },
121121
)
122122

123-
comments = graph.documents.first.definitions.find { |d| d.name == "foo" }.comments
123+
bar_comments = graph.documents.first.definitions.find { |d| d.name == "bar" }.comments
124124
assert_equal(
125125
["# Method comment (#{context.absolute_path_to("file1.rb")}:4:3-4:19)"],
126-
comments.map { |c| "#{c.string} (#{c.location})" },
126+
bar_comments.map { |c| "#{c.string} (#{normalized_comment_location(c)})" },
127127
)
128128
end
129129
end
130+
131+
private
132+
133+
# Comment locations on Windows include the carriage return. This means that the end column is off by one when compared
134+
# to Unix locations. This method creates a fake adjusted location for Windows so that we can assert locations once
135+
def normalized_comment_location(comment)
136+
loc = comment.location
137+
return loc unless Gem.win_platform?
138+
139+
Saturn::Location.new(
140+
uri: loc.uri,
141+
start_line: loc.start_line,
142+
start_column: loc.start_column,
143+
end_line: loc.end_line,
144+
end_column: loc.end_column - 1,
145+
)
146+
end
130147
end

test/document_test.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ def test_document_initialize_from_graph
2323

2424
document = graph.documents.first
2525
assert_instance_of(Saturn::Document, document)
26-
assert_equal("file://#{context.absolute_path}/file1.rb", document.uri)
26+
assert_equal(context.uri_to("file1.rb"), document.uri)
2727
end
2828
end
2929

test/helpers/context.rb

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,14 @@ def absolute_path_to(relative_path)
2626
::File.join(@absolute_path, relative_path)
2727
end
2828

29+
#: (String) -> String
30+
def uri_to(relative_path)
31+
path = absolute_path_to(relative_path)
32+
# TODO: This has to go away once we have a proper URI abstraction
33+
path.prepend("/") if Gem.win_platform?
34+
URI::File.build(path: path).to_s
35+
end
36+
2937
#: (String relative_path, ?String contents, ?append: bool) -> void
3038
def write!(relative_path, contents = "", append: false)
3139
absolute_path = absolute_path_to(relative_path)

0 commit comments

Comments
 (0)