diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index d4270166e2..6e453028a1 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -101,11 +101,11 @@ jobs: - os: macOS-latest steps: - uses: actions/checkout@v2 - - name: Install Mac System dependencies + - name: Install Boost on Mac if: startsWith(matrix.os,'macOS') run: | brew install boost - - name: Install Linux dependencies + - name: Install Boost on Linux if: startsWith(matrix.os,'ubuntu') run: | sudo apt-get install -y libboost-all-dev @@ -121,6 +121,37 @@ jobs: run: cargo test --workspace --all-features --no-run --locked - name: Run tests run: cargo test --workspace --all-features --verbose + + test-windows-latest: + runs-on: windows-latest + steps: + - uses: actions/checkout@v2 + - name: Install Boost on Windows. + uses: MarkusJx/install-boost@v2.1.0 + id: install-boost + with: + boost_version: 1.78.0 + platform_version: 2019 + toolset: msvc + - name: Install rust + uses: actions-rs/toolchain@v1 + with: + profile: minimal + toolchain: stable + override: true + - name: Cache Dependencies + uses: Swatinem/rust-cache@v1 + - name: Build + run: cargo test --workspace --all-features --no-run --locked + env: + BOOST_ROOT: ${{ steps.install-boost.outputs.BOOST_ROOT }} + Boost_NO_BOOST_CMAKE: ON + - name: Run tests + run: cargo test --workspace --all-features --verbose + env: + BOOST_ROOT: ${{ steps.install-boost.outputs.BOOST_ROOT }} + Boost_NO_BOOST_CMAKE: ON + wasm-test: runs-on: ubuntu-latest diff --git a/crates/analyzer/tests/snapshots/analysis__strings.snap b/crates/analyzer/tests/snapshots/analysis__strings.snap index ec92f09647..2fb559a12e 100644 --- a/crates/analyzer/tests/snapshots/analysis__strings.snap +++ b/crates/analyzer/tests/snapshots/analysis__strings.snap @@ -1,6 +1,6 @@ --- source: crates/analyzer/tests/analysis.rs -expression: "build_snapshot(\"features/strings.fe\", &src, module, &db)" +expression: "build_snapshot(&files, module_id, &db)" --- note: @@ -132,10 +132,9 @@ note: note: ┌─ features/strings.fe:23:5 │ -23 │ ╭ pub fn return_special_chars() -> String<18>: -24 │ │ return "\n\"'\r\t -25 │ │ foo\\" - │ ╰──────────────^ attributes hash: 14991635520577142188 +23 │ ╭ pub fn return_special_chars() -> String<9>: +24 │ │ return "\n\"'\r\tfoo\\" + │ ╰───────────────────────────────^ attributes hash: 2714027657010055129 │ = FunctionSignature { self_decl: None, @@ -143,7 +142,7 @@ note: return_type: Ok( String( FeString { - max_size: 18, + max_size: 9, }, ), ), @@ -151,10 +150,8 @@ note: note: ┌─ features/strings.fe:24:16 - │ -24 │ return "\n\"'\r\t - │ ╭────────────────^ -25 │ │ foo\\" - │ ╰──────────────^ String<18>: Memory + │ +24 │ return "\n\"'\r\tfoo\\" + │ ^^^^^^^^^^^^^^^^ String<9>: Memory diff --git a/crates/common/src/files.rs b/crates/common/src/files.rs index d63ac88cf5..5e00b40c89 100644 --- a/crates/common/src/files.rs +++ b/crates/common/src/files.rs @@ -6,7 +6,7 @@ use include_dir::Dir; use indexmap::indexmap; use indexmap::IndexMap; use smol_str::SmolStr; -use std::collections::HashMap; +use std::collections::BTreeMap; use std::ops::Range; use std::path::Path; use std::{fs, io}; @@ -24,7 +24,10 @@ pub struct SourceFileId(pub u128); impl SourceFile { pub fn new(name: &str, content: &str) -> Self { - let hash = keccak::full_as_bytes(content.as_bytes()); + // Canonicalize new line character for Windows. + let content_canonicalized = content.replace("\r\n", "\n"); + let hash = keccak::full_as_bytes(content_canonicalized.as_bytes()); + let line_starts = cs::files::line_starts(content).collect(); Self { id: SourceFileId(u128::from_be_bytes(hash[..16].try_into().unwrap())), @@ -63,21 +66,21 @@ impl FileLoader for OsFileLoader { } pub struct FileStore { - pub files: HashMap, + pub files: BTreeMap, loader: Box, } impl FileStore { pub fn new() -> Self { Self { - files: HashMap::new(), + files: BTreeMap::new(), loader: Box::new(OsFileLoader), } } pub fn with_loader(loader: Box) -> Self { Self { - files: HashMap::new(), + files: BTreeMap::new(), loader, } } diff --git a/crates/parser/src/lexer/token.rs b/crates/parser/src/lexer/token.rs index 4a76fe6001..ad1506c063 100644 --- a/crates/parser/src/lexer/token.rs +++ b/crates/parser/src/lexer/token.rs @@ -34,7 +34,7 @@ pub enum TokenKind { #[error] Error, - #[regex(r"\n[ \t]*")] + #[regex(r"[\r]?\n[ \t]*")] Newline, /// Virtual tokens emitted by the parser @@ -52,8 +52,8 @@ pub enum TokenKind { #[regex("0[bB][0-1]+")] Binary, // Float, - #[regex(r#""([^"\\]|\\.)*""#)] - #[regex(r#"'([^'\\]|\\.)*'"#)] + #[regex(r#""([^"\\\n]|\\.)*""#)] + #[regex(r#"'([^'\\\n]|\\.)*'"#)] Text, #[token("true")] True, diff --git a/crates/test-files/fixtures/compile_errors/string_literal.fe b/crates/test-files/fixtures/compile_errors/string_literal.fe new file mode 100644 index 0000000000..462521fdf5 --- /dev/null +++ b/crates/test-files/fixtures/compile_errors/string_literal.fe @@ -0,0 +1,4 @@ +contract Foo: + pub fn bar(): + let s: String<16> = "This is + Invalid" \ No newline at end of file diff --git a/crates/test-files/fixtures/features/strings.fe b/crates/test-files/fixtures/features/strings.fe index 132bceb7fb..b974185ac9 100644 --- a/crates/test-files/fixtures/features/strings.fe +++ b/crates/test-files/fixtures/features/strings.fe @@ -20,6 +20,5 @@ contract Foo: pub fn return_casted_static_string() -> String<100>: return String<100>("foo") - pub fn return_special_chars() -> String<18>: - return "\n\"'\r\t - foo\\" \ No newline at end of file + pub fn return_special_chars() -> String<9>: + return "\n\"'\r\tfoo\\" \ No newline at end of file diff --git a/crates/tests/src/features.rs b/crates/tests/src/features.rs index d8fef49122..fd53de4d70 100644 --- a/crates/tests/src/features.rs +++ b/crates/tests/src/features.rs @@ -797,10 +797,7 @@ fn strings() { &mut executor, "return_special_chars", &[], - Some(&string_token( - "\n\"'\r\t - foo\\", - )), + Some(&string_token("\n\"'\r\tfoo\\")), ); harness.events_emitted( @@ -1696,8 +1693,8 @@ fn abi_decode_checks() { // this would break the equivalence of string's `data_offset + data_size` and // the bytes' `data_offset`, making the encoding invalid tampered_data[byte_index] = 33; - // the string length is completely valid otherwise. 32 for example will not revert - // tampered_data[byte_index] = 32; + // the string length is completely valid otherwise. 32 for example will not + // revert tampered_data[byte_index] = 32; harness.test_call_reverts(&mut executor, tampered_data, &revert_data); // place non-zero byte in padded region of the string