Make Position::{line, column} fields private

This commit is contained in:
Joshua Warner 2021-12-23 20:44:43 -08:00
parent fae1bb4458
commit 443d738f9b
5 changed files with 115 additions and 88 deletions

View file

@ -514,11 +514,10 @@ fn fmt_when<'a, 'buf>(
let patterns = &branch.patterns; let patterns = &branch.patterns;
let expr = &branch.value; let expr = &branch.value;
let (first_pattern, rest) = patterns.split_first().unwrap(); let (first_pattern, rest) = patterns.split_first().unwrap();
let is_multiline = match rest.last() { let is_multiline = if rest.is_empty() {
None => false, false
Some(last_pattern) => { } else {
first_pattern.region.start().line != last_pattern.region.end().line patterns.iter().any(|p| p.is_multiline())
}
}; };
fmt_pattern( fmt_pattern(

View file

@ -40,10 +40,7 @@ impl<'a> State<'a> {
/// Returns the current position /// Returns the current position
pub const fn pos(&self) -> Position { pub const fn pos(&self) -> Position {
Position { Position::new(self.xyzlcol.line, self.xyzlcol.column)
line: self.xyzlcol.line,
column: self.xyzlcol.column,
}
} }
/// Returns whether the parser has reached the end of the input /// Returns whether the parser has reached the end of the input
@ -97,14 +94,14 @@ impl<'a> State<'a> {
pub fn len_region(&self, length: u16) -> Region { pub fn len_region(&self, length: u16) -> Region {
Region::new( Region::new(
self.pos(), self.pos(),
Position { Position::new(
line: self.xyzlcol.line, self.xyzlcol.line,
column: self self
.xyzlcol .xyzlcol
.column .column
.checked_add(length) .checked_add(length)
.unwrap_or_else(|| panic!("len_region overflowed")), .unwrap_or_else(|| panic!("len_region overflowed")),
}, ),
) )
} }

View file

@ -154,8 +154,8 @@ impl fmt::Debug for Region {
#[derive(Copy, Clone, Eq, PartialEq, PartialOrd, Ord, Hash, Default)] #[derive(Copy, Clone, Eq, PartialEq, PartialOrd, Ord, Hash, Default)]
pub struct Position { pub struct Position {
pub line: u32, line: u32,
pub column: u16, column: u16,
} }
impl Position { impl Position {
@ -163,12 +163,12 @@ impl Position {
Position { line: 0, column: 0 } Position { line: 0, column: 0 }
} }
pub fn new(line: u32, column: u16) -> Position { pub const fn new(line: u32, column: u16) -> Position {
Position { line, column } Position { line, column }
} }
#[must_use] #[must_use]
pub fn bump_column(self, count: u16) -> Self { pub const fn bump_column(self, count: u16) -> Self {
Self { Self {
line: self.line, line: self.line,
column: self.column + count, column: self.column + count,
@ -191,6 +191,14 @@ impl Position {
column: 0, column: 0,
} }
} }
#[must_use]
pub const fn sub(self, count: u16) -> Self {
Self {
line: self.line,
column: self.column - count,
}
}
} }
impl Debug for Position { impl Debug for Position {
@ -212,6 +220,14 @@ impl LineColumn {
column: 0, column: 0,
} }
} }
#[must_use]
pub const fn bump_column(self, count: u16) -> Self {
Self {
line: self.line,
column: self.column + count,
}
}
} }
#[derive(Copy, Clone, Eq, PartialEq, PartialOrd, Ord, Hash, Default)] #[derive(Copy, Clone, Eq, PartialEq, PartialOrd, Ord, Hash, Default)]
@ -221,6 +237,13 @@ pub struct LineColumnRegion {
} }
impl LineColumnRegion { impl LineColumnRegion {
pub const fn new(start: LineColumn, end: LineColumn) -> Self {
LineColumnRegion {
start,
end,
}
}
pub const fn zero() -> Self { pub const fn zero() -> Self {
LineColumnRegion { LineColumnRegion {
start: LineColumn::zero(), start: LineColumn::zero(),
@ -245,6 +268,13 @@ impl LineColumnRegion {
} }
} }
pub const fn from_pos(pos: LineColumn) -> Self {
Self {
start: pos,
end: pos.bump_column(1),
}
}
pub fn is_empty(&self) -> bool { pub fn is_empty(&self) -> bool {
self.end.line == self.start.line && self.start.column == self.end.column self.end.line == self.start.line && self.start.column == self.end.column
} }

View file

@ -2,7 +2,7 @@ use roc_collections::all::MutSet;
use roc_module::ident::{Ident, Lowercase, ModuleName}; use roc_module::ident::{Ident, Lowercase, ModuleName};
use roc_problem::can::PrecedenceProblem::BothNonAssociative; use roc_problem::can::PrecedenceProblem::BothNonAssociative;
use roc_problem::can::{BadPattern, FloatErrorKind, IntErrorKind, Problem, RuntimeError}; use roc_problem::can::{BadPattern, FloatErrorKind, IntErrorKind, Problem, RuntimeError};
use roc_region::all::{Loc, Position, Region, LineInfo}; use roc_region::all::{Loc, Region, LineInfo, LineColumn};
use std::path::PathBuf; use std::path::PathBuf;
use crate::error::r#type::suggest; use crate::error::r#type::suggest;
@ -570,7 +570,7 @@ fn to_bad_ident_expr_report<'b>(
BadPrivateTag(pos) => { BadPrivateTag(pos) => {
use BadIdentNext::*; use BadIdentNext::*;
match what_is_next(alloc.src_lines, pos) { match what_is_next(alloc.src_lines, lines.convert_pos(pos)) {
LowercaseAccess(width) => { LowercaseAccess(width) => {
let region = Region::new(pos, pos.bump_column(width)); let region = Region::new(pos, pos.bump_column(width));
alloc.stack(vec![ alloc.stack(vec![
@ -694,10 +694,7 @@ fn to_bad_ident_pattern_report<'b>(
} }
Underscore(pos) => { Underscore(pos) => {
let region = Region::from_pos(Position { let region = Region::from_pos(pos.sub(1));
line: pos.line,
column: pos.column - 1,
});
alloc.stack(vec![ alloc.stack(vec![
alloc.reflow("I am trying to parse an identifier here:"), alloc.reflow("I am trying to parse an identifier here:"),
@ -722,7 +719,7 @@ enum BadIdentNext<'a> {
Other(Option<char>), Other(Option<char>),
} }
fn what_is_next<'a>(source_lines: &'a [&'a str], pos: Position) -> BadIdentNext<'a> { fn what_is_next<'a>(source_lines: &'a [&'a str], pos: LineColumn) -> BadIdentNext<'a> {
let row_index = pos.line as usize; let row_index = pos.line as usize;
let col_index = pos.column as usize; let col_index = pos.column as usize;
match source_lines.get(row_index) { match source_lines.get(row_index) {

View file

@ -1,5 +1,5 @@
use roc_parse::parser::{ParseProblem, SyntaxError}; use roc_parse::parser::{ParseProblem, SyntaxError};
use roc_region::all::{Position, Region, LineInfo}; use roc_region::all::{Position, Region, LineInfo, LineColumn, LineColumnRegion};
use std::path::PathBuf; use std::path::PathBuf;
use crate::report::{Report, RocDocAllocator, RocDocBuilder, Severity}; use crate::report::{Report, RocDocAllocator, RocDocBuilder, Severity};
@ -102,9 +102,10 @@ fn to_syntax_report<'a>(
severity: Severity::RuntimeError, severity: Severity::RuntimeError,
} }
} }
Unexpected(mut region) => { Unexpected(region) => {
let mut region = lines.convert_region(*region);
if region.start().column == region.end().column { if region.start().column == region.end().column {
region = Region::new(region.start(), region.end().bump_column(1)); region = LineColumnRegion::new(region.start(), region.end().bump_column(1));
} }
let doc = alloc.stack(vec![ let doc = alloc.stack(vec![
@ -113,7 +114,7 @@ fn to_syntax_report<'a>(
// context(alloc, &parse_problem.context_stack, "here"), // context(alloc, &parse_problem.context_stack, "here"),
alloc.text(":"), alloc.text(":"),
]), ]),
alloc.region(lines.convert_region(region)), alloc.region(region),
]); ]);
report(doc) report(doc)
@ -537,7 +538,7 @@ fn to_lambda_report<'a>(
use roc_parse::parser::ELambda; use roc_parse::parser::ELambda;
match *parse_problem { match *parse_problem {
ELambda::Arrow(pos) => match what_is_next(alloc.src_lines, pos) { ELambda::Arrow(pos) => match what_is_next(alloc.src_lines, lines.convert_pos(pos)) {
Next::Token("=>") => { Next::Token("=>") => {
let surroundings = Region::new(start, pos); let surroundings = Region::new(start, pos);
let region = Region::from_pos(pos); let region = Region::from_pos(pos);
@ -584,7 +585,7 @@ fn to_lambda_report<'a>(
} }
}, },
ELambda::Comma(pos) => match what_is_next(alloc.src_lines, pos) { ELambda::Comma(pos) => match what_is_next(alloc.src_lines, lines.convert_pos(pos)) {
Next::Token("=>") => { Next::Token("=>") => {
let surroundings = Region::new(start, pos); let surroundings = Region::new(start, pos);
let region = Region::from_pos(pos); let region = Region::from_pos(pos);
@ -631,7 +632,7 @@ fn to_lambda_report<'a>(
} }
}, },
ELambda::Arg(pos) => match what_is_next(alloc.src_lines, pos) { ELambda::Arg(pos) => match what_is_next(alloc.src_lines, lines.convert_pos(pos)) {
Next::Other(Some(',')) => { Next::Other(Some(',')) => {
let surroundings = Region::new(start, pos); let surroundings = Region::new(start, pos);
let region = Region::from_pos(pos); let region = Region::from_pos(pos);
@ -1005,7 +1006,7 @@ fn to_list_report<'a>(
pos, pos,
), ),
EList::Open(pos) | EList::End(pos) => match what_is_next(alloc.src_lines, pos) { EList::Open(pos) | EList::End(pos) => match what_is_next(alloc.src_lines, lines.convert_pos(pos)) {
Next::Other(Some(',')) => { Next::Other(Some(',')) => {
let surroundings = Region::new(start, pos); let surroundings = Region::new(start, pos);
let region = Region::from_pos(pos); let region = Region::from_pos(pos);
@ -1217,7 +1218,7 @@ fn to_when_report<'a>(
use roc_parse::parser::EWhen; use roc_parse::parser::EWhen;
match *parse_problem { match *parse_problem {
EWhen::IfGuard(nested, pos) => match what_is_next(alloc.src_lines, pos) { EWhen::IfGuard(nested, pos) => match what_is_next(alloc.src_lines, lines.convert_pos(pos)) {
Next::Token("->") => { Next::Token("->") => {
let surroundings = Region::new(start, pos); let surroundings = Region::new(start, pos);
let region = Region::from_pos(pos); let region = Region::from_pos(pos);
@ -1402,7 +1403,7 @@ fn to_unfinished_when_report<'a>(
start: Position, start: Position,
message: RocDocBuilder<'a>, message: RocDocBuilder<'a>,
) -> Report<'a> { ) -> Report<'a> {
match what_is_next(alloc.src_lines, pos) { match what_is_next(alloc.src_lines, lines.convert_pos(pos)) {
Next::Token("->") => to_unexpected_arrow_report(alloc, lines, filename, pos, start), Next::Token("->") => to_unexpected_arrow_report(alloc, lines, filename, pos, start),
_ => { _ => {
@ -1558,14 +1559,14 @@ fn to_precord_report<'a>(
use roc_parse::parser::PRecord; use roc_parse::parser::PRecord;
match *parse_problem { match *parse_problem {
PRecord::Open(pos) => match what_is_next(alloc.src_lines, pos) { PRecord::Open(pos) => match what_is_next(alloc.src_lines, lines.convert_pos(pos)) {
Next::Keyword(keyword) => { Next::Keyword(keyword) => {
let surroundings = Region::new(start, pos); let surroundings = Region::new(start, pos);
let region = to_keyword_region(pos, keyword); let region = to_keyword_region(lines.convert_pos(pos), keyword);
let doc = alloc.stack(vec![ let doc = alloc.stack(vec![
alloc.reflow(r"I just started parsing a record pattern, but I got stuck on this field name:"), alloc.reflow(r"I just started parsing a record pattern, but I got stuck on this field name:"),
alloc.region_with_subregion(lines.convert_region(surroundings), lines.convert_region(region)), alloc.region_with_subregion(lines.convert_region(surroundings), region),
alloc.concat(vec![ alloc.concat(vec![
alloc.reflow(r"Looks like you are trying to use "), alloc.reflow(r"Looks like you are trying to use "),
alloc.keyword(keyword), alloc.keyword(keyword),
@ -1603,7 +1604,7 @@ fn to_precord_report<'a>(
let surroundings = Region::new(start, pos); let surroundings = Region::new(start, pos);
let region = Region::from_pos(pos); let region = Region::from_pos(pos);
match what_is_next(alloc.src_lines, pos) { match what_is_next(alloc.src_lines, lines.convert_pos(pos)) {
Next::Other(Some(c)) if c.is_alphabetic() => { Next::Other(Some(c)) if c.is_alphabetic() => {
let doc = alloc.stack(vec![ let doc = alloc.stack(vec![
alloc.reflow(r"I am partway through parsing a record pattern, but I got stuck here:"), alloc.reflow(r"I am partway through parsing a record pattern, but I got stuck here:"),
@ -1645,14 +1646,14 @@ fn to_precord_report<'a>(
} }
} }
PRecord::Field(pos) => match what_is_next(alloc.src_lines, pos) { PRecord::Field(pos) => match what_is_next(alloc.src_lines, lines.convert_pos(pos)) {
Next::Keyword(keyword) => { Next::Keyword(keyword) => {
let surroundings = Region::new(start, pos); let surroundings = Region::new(start, pos);
let region = to_keyword_region(pos, keyword); let region = to_keyword_region(lines.convert_pos(pos), keyword);
let doc = alloc.stack(vec![ let doc = alloc.stack(vec![
alloc.reflow(r"I just started parsing a record pattern, but I got stuck on this field name:"), alloc.reflow(r"I just started parsing a record pattern, but I got stuck on this field name:"),
alloc.region_with_subregion(lines.convert_region(surroundings), lines.convert_region(region)), alloc.region_with_subregion(lines.convert_region(surroundings), region),
alloc.concat(vec![ alloc.concat(vec![
alloc.reflow(r"Looks like you are trying to use "), alloc.reflow(r"Looks like you are trying to use "),
alloc.keyword(keyword), alloc.keyword(keyword),
@ -1735,16 +1736,16 @@ fn to_precord_report<'a>(
} }
} }
PRecord::IndentEnd(pos) => match next_line_starts_with_close_curly(alloc.src_lines, pos) { PRecord::IndentEnd(pos) => match next_line_starts_with_close_curly(alloc.src_lines, lines.convert_pos(pos)) {
Some(curly_pos) => { Some(curly_pos) => {
let surroundings = Region::new(start, curly_pos); let surroundings = LineColumnRegion::new(lines.convert_pos(start), curly_pos);
let region = Region::from_pos(curly_pos); let region = LineColumnRegion::from_pos(curly_pos);
let doc = alloc.stack(vec![ let doc = alloc.stack(vec![
alloc.reflow( alloc.reflow(
"I am partway through parsing a record pattern, but I got stuck here:", "I am partway through parsing a record pattern, but I got stuck here:",
), ),
alloc.region_with_subregion(lines.convert_region(surroundings), lines.convert_region(region)), alloc.region_with_subregion(surroundings, region),
alloc.concat(vec![ alloc.concat(vec![
alloc.reflow("I need this curly brace to be indented more. Try adding more spaces before it!"), alloc.reflow("I need this curly brace to be indented more. Try adding more spaces before it!"),
]), ]),
@ -1881,16 +1882,16 @@ fn to_pattern_in_parens_report<'a>(
} }
PInParens::IndentEnd(pos) => { PInParens::IndentEnd(pos) => {
match next_line_starts_with_close_parenthesis(alloc.src_lines, pos) { match next_line_starts_with_close_parenthesis(alloc.src_lines, lines.convert_pos(pos)) {
Some(curly_pos) => { Some(curly_pos) => {
let surroundings = Region::new(start, curly_pos); let surroundings = LineColumnRegion::new(lines.convert_pos(start), curly_pos);
let region = Region::from_pos(curly_pos); let region = LineColumnRegion::from_pos(curly_pos);
let doc = alloc.stack(vec![ let doc = alloc.stack(vec![
alloc.reflow( alloc.reflow(
"I am partway through parsing a pattern in parentheses, but I got stuck here:", "I am partway through parsing a pattern in parentheses, but I got stuck here:",
), ),
alloc.region_with_subregion(lines.convert_region(surroundings), lines.convert_region(region)), alloc.region_with_subregion(surroundings, region),
alloc.concat(vec![ alloc.concat(vec![
alloc.reflow("I need this parenthesis to be indented more. Try adding more spaces before it!"), alloc.reflow("I need this parenthesis to be indented more. Try adding more spaces before it!"),
]), ]),
@ -1951,7 +1952,7 @@ fn to_type_report<'a>(
EType::TApply(tapply, pos) => to_tapply_report(alloc, lines, filename, tapply, *pos), EType::TApply(tapply, pos) => to_tapply_report(alloc, lines, filename, tapply, *pos),
EType::TInlineAlias(talias, _) => to_talias_report(alloc, lines, filename, talias), EType::TInlineAlias(talias, _) => to_talias_report(alloc, lines, filename, talias),
EType::TFunctionArgument(pos) => match what_is_next(alloc.src_lines, *pos) { EType::TFunctionArgument(pos) => match what_is_next(alloc.src_lines, lines.convert_pos(*pos)) {
Next::Other(Some(',')) => { Next::Other(Some(',')) => {
let surroundings = Region::new(start, *pos); let surroundings = Region::new(start, *pos);
let region = Region::from_pos(*pos); let region = Region::from_pos(*pos);
@ -2081,14 +2082,14 @@ fn to_trecord_report<'a>(
use roc_parse::parser::ETypeRecord; use roc_parse::parser::ETypeRecord;
match *parse_problem { match *parse_problem {
ETypeRecord::Open(pos) => match what_is_next(alloc.src_lines, pos) { ETypeRecord::Open(pos) => match what_is_next(alloc.src_lines, lines.convert_pos(pos)) {
Next::Keyword(keyword) => { Next::Keyword(keyword) => {
let surroundings = Region::new(start, pos); let surroundings = Region::new(start, pos);
let region = to_keyword_region(pos, keyword); let region = to_keyword_region(lines.convert_pos(pos), keyword);
let doc = alloc.stack(vec![ let doc = alloc.stack(vec![
alloc.reflow(r"I just started parsing a record type, but I got stuck on this field name:"), alloc.reflow(r"I just started parsing a record type, but I got stuck on this field name:"),
alloc.region_with_subregion(lines.convert_region(surroundings), lines.convert_region(region)), alloc.region_with_subregion(lines.convert_region(surroundings), region),
alloc.concat(vec![ alloc.concat(vec![
alloc.reflow(r"Looks like you are trying to use "), alloc.reflow(r"Looks like you are trying to use "),
alloc.keyword(keyword), alloc.keyword(keyword),
@ -2130,7 +2131,7 @@ fn to_trecord_report<'a>(
let surroundings = Region::new(start, pos); let surroundings = Region::new(start, pos);
let region = Region::from_pos(pos); let region = Region::from_pos(pos);
match what_is_next(alloc.src_lines, pos) { match what_is_next(alloc.src_lines, lines.convert_pos(pos)) {
Next::Other(Some(c)) if c.is_alphabetic() => { Next::Other(Some(c)) if c.is_alphabetic() => {
let doc = alloc.stack(vec![ let doc = alloc.stack(vec![
alloc.reflow(r"I am partway through parsing a record type, but I got stuck here:"), alloc.reflow(r"I am partway through parsing a record type, but I got stuck here:"),
@ -2172,14 +2173,14 @@ fn to_trecord_report<'a>(
} }
} }
ETypeRecord::Field(pos) => match what_is_next(alloc.src_lines, pos) { ETypeRecord::Field(pos) => match what_is_next(alloc.src_lines, lines.convert_pos(pos)) {
Next::Keyword(keyword) => { Next::Keyword(keyword) => {
let surroundings = Region::new(start, pos); let surroundings = Region::new(start, pos);
let region = to_keyword_region(pos, keyword); let region = to_keyword_region(lines.convert_pos(pos), keyword);
let doc = alloc.stack(vec![ let doc = alloc.stack(vec![
alloc.reflow(r"I just started parsing a record type, but I got stuck on this field name:"), alloc.reflow(r"I just started parsing a record type, but I got stuck on this field name:"),
alloc.region_with_subregion(lines.convert_region(surroundings), lines.convert_region(region)), alloc.region_with_subregion(lines.convert_region(surroundings), region),
alloc.concat(vec![ alloc.concat(vec![
alloc.reflow(r"Looks like you are trying to use "), alloc.reflow(r"Looks like you are trying to use "),
alloc.keyword(keyword), alloc.keyword(keyword),
@ -2254,16 +2255,16 @@ fn to_trecord_report<'a>(
} }
ETypeRecord::IndentEnd(pos) => { ETypeRecord::IndentEnd(pos) => {
match next_line_starts_with_close_curly(alloc.src_lines, pos) { match next_line_starts_with_close_curly(alloc.src_lines, lines.convert_pos(pos)) {
Some(curly_pos) => { Some(curly_pos) => {
let surroundings = Region::new(start, curly_pos); let surroundings = LineColumnRegion::new(lines.convert_pos(start), curly_pos);
let region = Region::from_pos(curly_pos); let region = LineColumnRegion::from_pos(curly_pos);
let doc = alloc.stack(vec![ let doc = alloc.stack(vec![
alloc.reflow( alloc.reflow(
"I am partway through parsing a record type, but I got stuck here:", "I am partway through parsing a record type, but I got stuck here:",
), ),
alloc.region_with_subregion(lines.convert_region(surroundings), lines.convert_region(region)), alloc.region_with_subregion(surroundings, region),
alloc.concat(vec![ alloc.concat(vec![
alloc.reflow("I need this curly brace to be indented more. Try adding more spaces before it!"), alloc.reflow("I need this curly brace to be indented more. Try adding more spaces before it!"),
]), ]),
@ -2326,14 +2327,14 @@ fn to_ttag_union_report<'a>(
use roc_parse::parser::ETypeTagUnion; use roc_parse::parser::ETypeTagUnion;
match *parse_problem { match *parse_problem {
ETypeTagUnion::Open(pos) => match what_is_next(alloc.src_lines, pos) { ETypeTagUnion::Open(pos) => match what_is_next(alloc.src_lines, lines.convert_pos(pos)) {
Next::Keyword(keyword) => { Next::Keyword(keyword) => {
let surroundings = Region::new(start, pos); let surroundings = Region::new(start, pos);
let region = to_keyword_region(pos, keyword); let region = to_keyword_region(lines.convert_pos(pos), keyword);
let doc = alloc.stack(vec![ let doc = alloc.stack(vec![
alloc.reflow(r"I just started parsing a tag union, but I got stuck on this field name:"), alloc.reflow(r"I just started parsing a tag union, but I got stuck on this field name:"),
alloc.region_with_subregion(lines.convert_region(surroundings), lines.convert_region(region)), alloc.region_with_subregion(lines.convert_region(surroundings), region),
alloc.concat(vec![ alloc.concat(vec![
alloc.reflow(r"Looks like you are trying to use "), alloc.reflow(r"Looks like you are trying to use "),
alloc.keyword(keyword), alloc.keyword(keyword),
@ -2397,7 +2398,7 @@ fn to_ttag_union_report<'a>(
let surroundings = Region::new(start, pos); let surroundings = Region::new(start, pos);
let region = Region::from_pos(pos); let region = Region::from_pos(pos);
match what_is_next(alloc.src_lines, pos) { match what_is_next(alloc.src_lines, lines.convert_pos(pos)) {
Next::Other(Some(c)) if c.is_alphabetic() => { Next::Other(Some(c)) if c.is_alphabetic() => {
debug_assert!(c.is_lowercase()); debug_assert!(c.is_lowercase());
@ -2483,16 +2484,16 @@ fn to_ttag_union_report<'a>(
} }
ETypeTagUnion::IndentEnd(pos) => { ETypeTagUnion::IndentEnd(pos) => {
match next_line_starts_with_close_square_bracket(alloc.src_lines, pos) { match next_line_starts_with_close_square_bracket(alloc.src_lines, lines.convert_pos(pos)) {
Some(curly_pos) => { Some(curly_pos) => {
let surroundings = Region::new(start, curly_pos); let surroundings = LineColumnRegion::new(lines.convert_pos(start), curly_pos);
let region = Region::from_pos(curly_pos); let region = LineColumnRegion::from_pos(curly_pos);
let doc = alloc.stack(vec![ let doc = alloc.stack(vec![
alloc.reflow( alloc.reflow(
"I am partway through parsing a tag union type, but I got stuck here:", "I am partway through parsing a tag union type, but I got stuck here:",
), ),
alloc.region_with_subregion(lines.convert_region(surroundings), lines.convert_region(region)), alloc.region_with_subregion(surroundings, region),
alloc.concat(vec![ alloc.concat(vec![
alloc.reflow("I need this square bracket to be indented more. Try adding more spaces before it!"), alloc.reflow("I need this square bracket to be indented more. Try adding more spaces before it!"),
]), ]),
@ -2548,14 +2549,14 @@ fn to_tinparens_report<'a>(
match *parse_problem { match *parse_problem {
ETypeInParens::Open(pos) => { ETypeInParens::Open(pos) => {
match what_is_next(alloc.src_lines, pos) { match what_is_next(alloc.src_lines, lines.convert_pos(pos)) {
Next::Keyword(keyword) => { Next::Keyword(keyword) => {
let surroundings = Region::new(start, pos); let surroundings = Region::new(start, pos);
let region = to_keyword_region(pos, keyword); let region = to_keyword_region(lines.convert_pos(pos), keyword);
let doc = alloc.stack(vec![ let doc = alloc.stack(vec![
alloc.reflow(r"I just saw an open parenthesis, so I was expecting to see a type next."), alloc.reflow(r"I just saw an open parenthesis, so I was expecting to see a type next."),
alloc.region_with_subregion(lines.convert_region(surroundings), lines.convert_region(region)), alloc.region_with_subregion(lines.convert_region(surroundings), region),
alloc.concat(vec![ alloc.concat(vec![
alloc.reflow(r"Something like "), alloc.reflow(r"Something like "),
alloc.parser_suggestion("(List Person)"), alloc.parser_suggestion("(List Person)"),
@ -2623,7 +2624,7 @@ fn to_tinparens_report<'a>(
let surroundings = Region::new(start, pos); let surroundings = Region::new(start, pos);
let region = Region::from_pos(pos); let region = Region::from_pos(pos);
match what_is_next(alloc.src_lines, pos) { match what_is_next(alloc.src_lines, lines.convert_pos(pos)) {
Next::Other(Some(c)) if c.is_alphabetic() => { Next::Other(Some(c)) if c.is_alphabetic() => {
debug_assert!(c.is_lowercase()); debug_assert!(c.is_lowercase());
@ -2694,16 +2695,16 @@ fn to_tinparens_report<'a>(
} }
ETypeInParens::IndentEnd(pos) => { ETypeInParens::IndentEnd(pos) => {
match next_line_starts_with_close_parenthesis(alloc.src_lines, pos) { match next_line_starts_with_close_parenthesis(alloc.src_lines, lines.convert_pos(pos)) {
Some(curly_pos) => { Some(curly_pos) => {
let surroundings = Region::new(start, curly_pos); let surroundings = LineColumnRegion::new(lines.convert_pos(start), curly_pos);
let region = Region::from_pos(curly_pos); let region = LineColumnRegion::from_pos(curly_pos);
let doc = alloc.stack(vec![ let doc = alloc.stack(vec![
alloc.reflow( alloc.reflow(
"I am partway through parsing a type in parentheses, but I got stuck here:", "I am partway through parsing a type in parentheses, but I got stuck here:",
), ),
alloc.region_with_subregion(lines.convert_region(surroundings), lines.convert_region(region)), alloc.region_with_subregion(surroundings, region),
alloc.concat(vec![ alloc.concat(vec![
alloc.reflow("I need this parenthesis to be indented more. Try adding more spaces before it!"), alloc.reflow("I need this parenthesis to be indented more. Try adding more spaces before it!"),
]), ]),
@ -3505,7 +3506,7 @@ enum Next<'a> {
Other(Option<char>), Other(Option<char>),
} }
fn what_is_next<'a>(source_lines: &'a [&'a str], pos: Position) -> Next<'a> { fn what_is_next<'a>(source_lines: &'a [&'a str], pos: LineColumn) -> Next<'a> {
let row_index = pos.line as usize; let row_index = pos.line as usize;
let col_index = pos.column as usize; let col_index = pos.column as usize;
match source_lines.get(row_index) { match source_lines.get(row_index) {
@ -3547,36 +3548,36 @@ pub fn starts_with_keyword(rest_of_line: &str, keyword: &str) -> bool {
} }
} }
fn next_line_starts_with_close_curly(source_lines: &[&str], pos: Position) -> Option<Position> { fn next_line_starts_with_close_curly(source_lines: &[&str], pos: LineColumn) -> Option<LineColumn> {
next_line_starts_with_char(source_lines, pos, '}') next_line_starts_with_char(source_lines, pos, '}')
} }
fn next_line_starts_with_close_parenthesis( fn next_line_starts_with_close_parenthesis(
source_lines: &[&str], source_lines: &[&str],
pos: Position, pos: LineColumn,
) -> Option<Position> { ) -> Option<LineColumn> {
next_line_starts_with_char(source_lines, pos, ')') next_line_starts_with_char(source_lines, pos, ')')
} }
fn next_line_starts_with_close_square_bracket( fn next_line_starts_with_close_square_bracket(
source_lines: &[&str], source_lines: &[&str],
pos: Position, pos: LineColumn,
) -> Option<Position> { ) -> Option<LineColumn> {
next_line_starts_with_char(source_lines, pos, ']') next_line_starts_with_char(source_lines, pos, ']')
} }
fn next_line_starts_with_char( fn next_line_starts_with_char(
source_lines: &[&str], source_lines: &[&str],
pos: Position, pos: LineColumn,
character: char, character: char,
) -> Option<Position> { ) -> Option<LineColumn> {
match source_lines.get(pos.line as usize + 1) { match source_lines.get(pos.line as usize + 1) {
None => None, None => None,
Some(line) => { Some(line) => {
let spaces_dropped = line.trim_start_matches(' '); let spaces_dropped = line.trim_start_matches(' ');
match spaces_dropped.chars().next() { match spaces_dropped.chars().next() {
Some(c) if c == character => Some(Position { Some(c) if c == character => Some(LineColumn {
line: pos.line + 1, line: pos.line + 1,
column: (line.len() - spaces_dropped.len()) as u16, column: (line.len() - spaces_dropped.len()) as u16,
}), }),
@ -3586,6 +3587,9 @@ fn next_line_starts_with_char(
} }
} }
fn to_keyword_region(pos: Position, keyword: &str) -> Region { fn to_keyword_region(pos: LineColumn, keyword: &str) -> LineColumnRegion {
Region::new(pos, pos.bump_column(keyword.len() as u16)) LineColumnRegion {
start: pos,
end: pos.bump_column(keyword.len() as u16)
}
} }