Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix multibyte character counting in processed #812

Merged
merged 3 commits into from
Oct 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion libs/config/src/analyze/chumsky.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ impl ChumskyCode {
{
end += 1;
}
&processed.as_str()[start..end]
processed.extract(start..end).to_string()
}
));
}
Expand Down
4 changes: 2 additions & 2 deletions libs/config/src/analyze/lints/c01_invalid_value.rs
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ impl CodeC01InvalidValue {
#[must_use]
pub fn new(span: Range<usize>, processed: &Processed) -> Self {
Self {
value: processed.as_str()[span.clone()].to_string(),
value: processed.extract(span.clone()).to_string(),
span,
diagnostic: None,
}
Expand Down Expand Up @@ -218,7 +218,7 @@ impl CodeC01InvalidValueMacro {
if let Some(diag) = &mut self.diagnostic {
diag.notes.push(format!(
"The processed output was:\n{} ",
&processed.as_str()[self.span.start..self.span.end]
processed.extract(self.span.clone())
));
}
self
Expand Down
2 changes: 1 addition & 1 deletion libs/config/src/analyze/lints/c07_expected_array.rs
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,7 @@ impl Code07ExpectedArray {
let ident_end = processed
.mapping(name.span.end)
.expect("mapping should exist");
let haystack = &processed.as_str()[ident_end.original_start()..value.span().start];
let haystack = &processed.extract(ident_end.original_start()..value.span().start);
let possible_end = ident_end.original_start() + haystack.find(']').unwrap_or(1) + 1;
self.suggestion = Some(name.value.to_string());
self.diagnostic = Diagnostic::from_code_processed(
Expand Down
2 changes: 1 addition & 1 deletion libs/config/src/analyze/lints/c08_missing_semicolon.rs
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ impl Code08MissingSemicolon {
}

fn generate_processed(mut self, processed: &Processed) -> Self {
let haystack = &processed.as_str()[self.span.clone()];
let haystack = &processed.extract(self.span.clone());
let possible_end = self.span.start
+ haystack
.find('\n')
Expand Down
2 changes: 1 addition & 1 deletion libs/config/src/analyze/lints/c10_class_missing_braces.rs
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ impl Code10ClassMissingBraces {
}

fn generate_processed(mut self, processed: &Processed) -> Self {
let haystack = &processed.as_str()[self.span.clone()];
let haystack = &processed.extract(self.span.clone());
let possible_end = self.span.start
+ haystack
.find('\n')
Expand Down
2 changes: 1 addition & 1 deletion libs/sqf/src/analyze/lints/s05_if_assign.rs
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,7 @@ impl CodeS05IfAssign {
}

fn generate_processed(mut self, processed: &Processed) -> Self {
let haystack = &processed.as_str()[self.rhs.1.end..];
let haystack = &processed.extract_from(self.rhs.1.end..);
let end_position = self.rhs.1.end + haystack.find('}').unwrap_or(0) + 1;
self.diagnostic =
Diagnostic::from_code_processed(&self, self.if_cmd.start..end_position, processed);
Expand Down
6 changes: 3 additions & 3 deletions libs/sqf/src/parser/lexer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ use crate::StringWrapper;
pub type Tokens = Vec<(Token, Range<usize>)>;

macro_rules! chain_collect {
($Collect:ty: $($value:expr),+ $(,)?) => {
std::iter::empty()$(.chain($value))+.collect::<$Collect>()
};
($Collect:ty: $($value:expr),+ $(,)?) => {
std::iter::empty()$(.chain($value))+.collect::<$Collect>()
};
}

pub fn strip_comments(tokens: &mut Tokens) {
Expand Down
1 change: 1 addition & 0 deletions libs/sqf/tests/lints.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ lint!(s02_event_handler_case);
lint!(s03_static_typename);
lint!(s04_command_case);
lint!(s05_if_assign);
lint!(s05_if_assign_emoji);
lint!(s06_find_in_str);
lint!(s07_select_parse_number);
lint!(s08_format_args);
Expand Down
2 changes: 2 additions & 0 deletions libs/sqf/tests/lints/s05_if_assign_emoji.sqf
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
"🌭🌭🌭🌭🌭🌭🌭🌭🌭🌭🌭🌭🌭🌭🌭🌭🌭🌭🌭🌭🌭🌭🌭🌭";
private _workingArms = if (alive player) then { 2 } else { 0 };
13 changes: 13 additions & 0 deletions libs/sqf/tests/snapshots/lints__simple_s05_if_assign_emoji.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
---
source: libs/sqf/tests/lints.rs
expression: lint(stringify! (s05_if_assign_emoji))
---
help[L-S05]: assignment to if can be replaced with select
┌─ s05_if_assign_emoji.sqf:2:24
│
2 │ private _workingArms = if (alive player) then { 2 } else { 0 };
│ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ use select
│
= note: the if and else blocks only return constant values
select is faster in this case
= try: [0, 2] select (alive player)
50 changes: 20 additions & 30 deletions libs/sqf/tests/snapshots/lints__simple_s08_format_args.snap
Original file line number Diff line number Diff line change
Expand Up @@ -3,45 +3,35 @@ source: libs/sqf/tests/lints.rs
expression: lint(stringify! (s08_format_args))
---
error[L-S08]: format string: empty array
┌─ s08_format_args.sqf:4:21
│
4 │ format [" • %1", 1];
│ ╭─────────────────────^
5 │ │ format []; // empty array
│ ╰───────^ format string: empty array
┌─ s08_format_args.sqf:5:1
│
5 │ format []; // empty array
│ ^^^^^^^^^ format string: empty array


error[L-S08]: format string: unused args [used "%1", passed 3]
┌─ s08_format_args.sqf:5:11
│
5 │ format []; // empty array
│ ╭───────────^
6 │ │ format ["%1", 1, 2, 3]; // unused args
│ ╰───────────────────^ format string: unused args [used "%1", passed 3]
┌─ s08_format_args.sqf:6:1
│
6 │ format ["%1", 1, 2, 3]; // unused args
│ ^^^^^^^^^^^^^^^^^^^^^ format string: unused args [used "%1", passed 3]


error[L-S08]: format string: undefined tokens [used "%2", passed 1]
┌─ s08_format_args.sqf:6:24
│
6 │ format ["%1", 1, 2, 3]; // unused args
│ ╭────────────────────────^
7 │ │ format ["%1%2", 1]; // undefined tokens
│ ╰───────────────^ format string: undefined tokens [used "%2", passed 1]
┌─ s08_format_args.sqf:7:1
│
7 │ format ["%1%2", 1]; // undefined tokens
│ ^^^^^^^^^^^^^^^^^ format string: undefined tokens [used "%2", passed 1]


error[L-S08]: format string: skipped tokens [used "%5", but only 1 tokens]
┌─ s08_format_args.sqf:7:20
│
7 │ format ["%1%2", 1]; // undefined tokens
│ ╭────────────────────^
8 │ │ format ["%5", 1, 2 ,3 ,4, 5]; // skipped tokens
│ ╰─────────────────────────^ format string: skipped tokens [used "%5", but only 1 tokens]
┌─ s08_format_args.sqf:8:1
│
8 │ format ["%5", 1, 2 ,3 ,4, 5]; // skipped tokens
│ ^^^^^^^^^^^^^^^^^^^^^^^^^^^ format string: skipped tokens [used "%5", but only 1 tokens]


error[L-S08]: format string: undefined tokens [used "%1", passed 0]
┌─ s08_format_args.sqf:8:30
│
8 │ format ["%5", 1, 2 ,3 ,4, 5]; // skipped tokens
│ ╭──────────────────────────────^
9 │ │ formatText ["me too %1"];
│ ╰─────────────────────^ format string: undefined tokens [used "%1", passed 0]
┌─ s08_format_args.sqf:9:1
│
9 │ formatText ["me too %1"];
│ ^^^^^^^^^^^^^^^^^^^^^^^ format string: undefined tokens [used "%1", passed 0]
28 changes: 22 additions & 6 deletions libs/workspace/src/reporting/processed.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
use std::{collections::HashMap, ops::Range, sync::Arc};
use std::{
collections::HashMap,
ops::{Range, RangeFrom},
sync::Arc,
};
use tracing::warn;

use crate::{
Expand Down Expand Up @@ -106,12 +110,13 @@ fn append_token(
}
processed.mappings.push(Mapping {
processed: (LineCol(processed.total, (processed.line, processed.col)), {
processed.col += str.len();
processed.total += str.len();
let chars = str.chars().count();
processed.col += chars;
processed.total += chars;
processed.output.push_str(&str);
LineCol(
processed.total + str.len(),
(processed.line, processed.col + str.len()),
processed.total + chars,
(processed.line, processed.col + chars),
)
}),
source,
Expand Down Expand Up @@ -288,7 +293,7 @@ impl Processed {
}
let mut real_start = 0;
let mut real_end = 0;
self.output.char_indices().for_each(|(p, c)| {
self.output.chars().enumerate().for_each(|(p, c)| {
if p < span.start {
real_start += c.len_utf8();
}
Expand All @@ -298,6 +303,17 @@ impl Processed {
});
Arc::from(&self.output[real_start..real_end])
}

#[must_use]
pub fn extract_from(&self, from: RangeFrom<usize>) -> Arc<str> {
let mut real_start = 0;
self.output.chars().enumerate().for_each(|(p, c)| {
if p < from.start {
real_start += c.len_utf8();
}
});
Arc::from(&self.output[real_start..])
}
}

#[derive(Debug)]
Expand Down
Loading