Skip to content

Conversation

@Veetaha
Copy link
Contributor

@Veetaha Veetaha commented Feb 6, 2020

Followup of #2911, also puts some crosses to the todo list of #223.

AHTUNG! A big part of the diff of this PR are test data files changes.

Simplified SyntaxError that was SyntaxError { kind: { /* big enum */ }, location: Location } to SyntaxError(String, TextRange). I am not sure whether the tuple struct here is best fit, I am inclined to add names to the fields, because I already provide getters SyntaxError::message(), SyntaxError::range().
I also removed Location altogether ...

This is currently WIP, because the following is not done:

  • Add tests to test_data dir for unescape errors // I don't know where to put these errors in particular, because they are out of the scope of the lexer and parser. However, I have an idea in mind that we move all validators we have right now to parsing stage, but this is up to discussion... [UPD] I came to a conclusion that tree validation logic, which unescape errors are a part of, should be rethought of, we currently have no tests and no place to put tests for tree validations. So I'd like to extract potential redesign (maybe move of tree validation to ra_parser) and adding tests for this into a separate task.

@Veetaha Veetaha requested review from aochagavia, kiljacken and matklad and removed request for kiljacken February 6, 2020 00:41
) -> Vec<SyntaxError> {
let mut res = Vec::new();
for e in old_errors {
if e.offset() <= old_range.start() {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AHTUNG! I suppose in this if statement we had a mistake, we need to check that e.range().end() <= old_range.start() and I corrected it in this PR (tests pass anyway...)

res.extend(new_errors.into_iter().map(|new_err| {
// fighting borrow checker with a variable ;)
let offseted_range = *new_err.range() + range_before_reparse.start();
new_err.with_range(offseted_range)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am surprised how this reports a move after borrow error

new_err.with_range(*new_err.range() + range_before_reparse.start())

// where 
fn with_range(mut self, range: TextRange) -> Self;
fn range(&self) -> &TextRange;

pub struct SyntaxError(String, TextRange);

// FIXME: there was an unused SyntaxErrorKind previously (before this enum was removed)
// It was introduced in this PR: https://github.com/rust-analyzer/rust-analyzer/pull/846/files#diff-827da9b03b8f9faa1bade5cdd44d5dafR95
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FYI: there was an enum variant of SyntaxError that was not used anywhere, it was introduced in this PR, but then match arms attributes validation logic was removed without this variant being deleted...

@Veetaha Veetaha force-pushed the feature/reshape-syntax-error branch 2 times, most recently from 076d830 to 34158f1 Compare February 6, 2020 00:55

for old_err in old_errors {
let old_err_range = *old_err.range();
// FIXME: make sure that .start() was here previously by a mistake
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This fixme will be removed before merging this PR

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It should be TODO then

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I just temporarily marked it FIXME to let it pass no todo tests for a while.

@matklad
Copy link
Contributor

matklad commented Feb 6, 2020

A big part of the diff of this PR are test data files changes.

A nice trick here to commit code changes and test data changes in sepparate commits, so that the diff is easier to review.


for old_err in old_errors {
let old_err_range = *old_err.range();
// FIXME: make sure that .start() was here previously by a mistake
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It should be TODO then

@@ -1,209 +1,47 @@
//! FIXME: write short doc here
//! Module that defines `SyntaxError`.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would be better to explain why, rather than what:

This module defines SyntaxError, the type we use to represent errors from

  • tokenization
  • parsing
  • tree validation

The errors are unstructured: just a message and a location.

Copy link
Contributor Author

@Veetaha Veetaha Feb 6, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I moved this description to doc comment on top of SyntaxError itself, otherwise it would be repetition


pub fn location(&self) -> Location {
self.location.clone()
pub fn message(&self) -> &str {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should remove this function and just impl fmt::Display

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, yes, seems reasonable.

Copy link
Member

@bjorn3 bjorn3 Feb 6, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would expect an fmt::Display impl to give both the error message and location, while this method only gives the message, not the location.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You never see error location displayed as a hint on top of error squiggles, but you do want to see the text range if you print it to stdout. In case of std::fmt::Display this is for the first case, whilst std::fmt::Debug is for the second case. But anyway, I think this is not transparent, should we remove impl Display at all here then?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I did remove message() function, though this is a bit controversial, but I'd like to trust matklad here. Maybe I am wrong saying not transparent in my previous comment right here...

Location::Offset(offset) => offset,
Location::Range(range) => range.start(),
}
pub fn range(&self) -> &TextRange {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No need to return a reference, TextRange is small and Copy

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I am just used to getters returning by reference, wanted to hear your thoughts.

Parse, SmolStr, SyntaxKind, TextUnit,
};

pub(crate) use rowan::{GreenNode, GreenToken};
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The "re-export" was intentionally after "imports", but I dont' have strong feelings about htis.

Copy link
Contributor Author

@Veetaha Veetaha Feb 6, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, if I am not mistaken (need to recheck), this is what rustfmt suggested me to do and I couldn't resist

@matklad
Copy link
Contributor

matklad commented Feb 6, 2020 via email

@Veetaha
Copy link
Contributor Author

Veetaha commented Feb 6, 2020

@matklad

No strong opinion here, but I prefer to document modules, rather than
structs, because they are more useful for high-level picture.

https://github.com/rust-analyzer/rust-analyzer/blob/355c98fd0861acf0f0fddad08cbc923fee0698fb/crates/ra_ide_db/src/feature_flags.rs#L1-L16

But I see here you decided to document a struct instead of a module ...

@matklad
Copy link
Contributor

matklad commented Feb 7, 2020 via email

@Veetaha
Copy link
Contributor Author

Veetaha commented Feb 11, 2020

@matklad, I know this is not the most important thing, but might I ask you, please to elaborate on this comment?

@matklad
Copy link
Contributor

matklad commented Feb 11, 2020

Still no strong opinion, though I find there's a meaningful difference between "See X" (which is a redirect) and "This module defines X" (which reads like a placeholder comment) :)

@Veetaha
Copy link
Contributor Author

Veetaha commented Feb 11, 2020

But I do have a strong opinion. When you use the struct itself, you get documentation popups with more detailed docs, but you don't get them when you trigger autocompletion for the module itself (mentioning that you often just use module and never trigger completion for it thereafter), (maybe this is a bug, that docs don't appear on modules?)

@Veetaha
Copy link
Contributor Author

Veetaha commented Feb 11, 2020

See X sounds better, you are right!

@matklad
Copy link
Contributor

matklad commented Feb 11, 2020

Yeah, convinced, you are right! We should move all single-struct modules to See X style!

@Veetaha Veetaha force-pushed the feature/reshape-syntax-error branch from 43df237 to e05eb63 Compare February 17, 2020 20:51
@Veetaha Veetaha marked this pull request as ready for review February 18, 2020 00:11
@Veetaha
Copy link
Contributor Author

Veetaha commented Feb 18, 2020

@matklad, in response to your comment here about the bug I supposedly found.

I did check that there was a bug in reparsing::merge_errors() code. I added 4 tests that don't pass with previous code, but pass with my fixes in this commit: 053ccf4

Also, note that, though unintended to be in this PR, but I was forced to amend reparse_token() code to return errors so that tests pass (because lexer didn't report errors previously and reparsing code ignored them, though until now).

As a side note, we have a bit of code duplication in incremental_reparse() function, but I wouldn't like to tackle this in this PR and anytime soon at all...

@Veetaha
Copy link
Contributor Author

Veetaha commented Feb 18, 2020

Also, @matklad, please note on an [UPD] I wrote in PR description, I hope it makes sense. I'd like to experiment with moving tree validation errors to ra_parser and discuss the outcome of my experiments, after that we may redesign this and add tests for the new design, or leave it as it is and add tests for existing design later.

I hope it makes sense!

@Veetaha Veetaha requested review from bjorn3 and matklad February 18, 2020 00:28
@matklad
Copy link
Contributor

matklad commented Feb 18, 2020

I'd like to experiment with moving tree validation errors to ra_parser

ra_parser by design does not have access to ast:: types, but we probably want to implement validations in terms of typed AST

@matklad
Copy link
Contributor

matklad commented Feb 18, 2020

bors r+

bors bot added a commit that referenced this pull request Feb 18, 2020
3026: ra_syntax: reshape SyntaxError for the sake of removing redundancy r=matklad a=Veetaha

Followup of #2911, also puts some crosses to the todo list of #223.

**AHTUNG!** A big part of the diff of this PR are test data files changes.

Simplified `SyntaxError` that was `SyntaxError { kind: { /* big enum */  }, location: Location }` to `SyntaxError(String, TextRange)`. I am not sure whether the tuple struct here is best fit, I am inclined to add names to the fields, because I already provide getters `SyntaxError::message()`, `SyntaxError::range()`.
I also removed `Location` altogether ...

This is currently WIP, because the following is not done:
- [ ] ~~Add tests to `test_data` dir for unescape errors *// I don't know where to put these errors in particular, because they are out of the scope of the lexer and parser. However, I have an idea in mind that we move all validators we have right now to parsing stage, but this is up to discussion...*~~ **[UPD]** I came to a conclusion that tree validation logic, which unescape errors are a part of, should be rethought of, we currently have no tests and no place to put tests for tree validations. So I'd like to extract potential redesign (maybe move of tree validation to ra_parser) and adding tests for this into a separate task.

Co-authored-by: Veetaha <gerzoh1@gmail.com>
Co-authored-by: Veetaha <veetaha2@gmail.com>
@Veetaha
Copy link
Contributor Author

Veetaha commented Feb 18, 2020

I would not be 100% sure that we can't go without typed asts in a nice way, I'll look over it and make a conclusion...

@bors
Copy link
Contributor

bors bot commented Feb 18, 2020

Build succeeded

  • Rust (macos-latest)
  • Rust (ubuntu-latest)
  • Rust (windows-latest)
  • TypeScript

@bors bors bot merged commit 053ccf4 into rust-lang:master Feb 18, 2020
@Veetaha
Copy link
Contributor Author

Veetaha commented Feb 18, 2020

Oh, I just noticed I forgot to remove one FIXME comment...

@matklad
Copy link
Contributor

matklad commented Feb 18, 2020 via email

@Veetaha Veetaha deleted the feature/reshape-syntax-error branch February 24, 2020 20:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants