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

Add "extended errors" #299

Merged
merged 1 commit into from Nov 15, 2021
Merged

Add "extended errors" #299

merged 1 commit into from Nov 15, 2021

Conversation

arp242
Copy link
Collaborator

@arp242 arp242 commented Jun 20, 2021

The lexer and parser now always return a ParseError; the Error() method
is mostly unchanged:

toml: line 1 (last key "x.key"): newlines not allowed within inline tables

This adds an ErrorWithLocation() method, which will add some context
where the error occurred, similar to e.g. clang or the Rust compiler:

toml: error: newlines not allowed within inline tables

At line 1, column 18:

      1 | x = [{ key = 42 #
			   ^

And the ErrorWithUsage() also adds some usage guidance (not always
present):

toml: error: newlines not allowed within inline tables

At line 1, column 16:

      1 | x = [{ key = 42
			 ^
Error help:

	Inline tables must always be on a single line:

	    table = {key = 42, second = 43}

	It is invalid to split them over multiple lines like so:

	    # INVALID
	    table = {
		key    = 42,
		second = 43
	    }

	Use regular for this:

	    [table]
	    key    = 42
	    second = 43

The line/column information should now also always be correct, and a
number of error message have been tweaked a bit.

Fixes #201
Fixes #217

arp242 added a commit that referenced this pull request Jun 20, 2021
Refactor things a wee bit to add a decoder struct. This doesn't really
*do* anything right now, but will be needed to add options, such as
"strict mode" in #197 or "extended errors" in #299.

Also add DecodeFS() as a companion to DecodeFile() to read from a fs.FS,
and since using a reader is the default with NewDecoder() (and was
already easy to do before with strings.NewReader()) I marked
DecodeReader() as deprecated.
@arp242 arp242 force-pushed the exterr branch 2 times, most recently from d45efc1 to 5a19592 Compare June 27, 2021 06:10
@arp242 arp242 force-pushed the exterr branch 2 times, most recently from 154bb76 to 075c209 Compare July 4, 2021 12:11
@arp242 arp242 force-pushed the exterr branch 4 times, most recently from d6f7ab6 to dd29c79 Compare September 24, 2021 08:23
@arp242 arp242 marked this pull request as ready for review November 15, 2021 15:19
The lexer and parser now always return a ParseError; the Error() method
is mostly unchanged:

	toml: line 1 (last key "x.key"): newlines not allowed within inline tables

This adds an ErrorWithLocation() method, which will add some context
where the error occurred, similar to e.g. clang or the Rust compiler:

	toml: error: newlines not allowed within inline tables

	At line 1, column 18:

	      1 | x = [{ key = 42 #
				   ^

And the ErrorWithUsage() also adds some usage guidance (not always
present):

	toml: error: newlines not allowed within inline tables

	At line 1, column 16:

	      1 | x = [{ key = 42
				 ^
	Error help:

		Inline tables must always be on a single line:

		    table = {key = 42, second = 43}

		It is invalid to split them over multiple lines like so:

		    # INVALID
		    table = {
			key    = 42,
			second = 43
		    }

		Use regular for this:

		    [table]
		    key    = 42
		    second = 43

The line/column information should now also always be correct, and a
number of error message have been tweaked a bit.

Fixes #201
Fixes #217
@cretz
Copy link

cretz commented Nov 15, 2021

Note that the removal of Line from the ParseError struct here has broken other tools such as the popular https://staticcheck.io/ because it references it at https://github.com/dominikh/go-tools/blob/ce0ed4dfd45dccf9c3b0b6a923f2c65f73031b45/go/loader/loader.go#L330.

@arp242
Copy link
Collaborator Author

arp242 commented Nov 16, 2021

Oops; I think somewhere along the long I forgot that ParseError was already exported. I'll make sure it's fixed before the next release; thanks for the heads-up @cretz.

@dominikh
Copy link

Note that the removal of Line from the ParseError struct here has broken other tools such as the popular https://staticcheck.io/ because it references it at https://github.com/dominikh/go-tools/blob/ce0ed4dfd45dccf9c3b0b6a923f2c65f73031b45/go/loader/loader.go#L330.

Note that it doesn't really affect us, because of Go modules. Staticcheck's main module builds with v0.4.1 of this library, and we can update to the new API when you make a new release.

arp242 added a commit that referenced this pull request Nov 16, 2021
For compatibility; mark it as deprecated, but ensure it's still set to
the correct value. See comments on #299;

Will remove in eventual v2 release.
@arp242
Copy link
Collaborator Author

arp242 commented Nov 16, 2021

Yeah, but I'd like to make sure the releases remain compatible (technically 0.x don't promise compatibility, but I just treat it as-if it's 1.x, with the current versioning scheme predating modules; maybe I should just release 1.0 as the next version).

Anyway, I added a "deprecated" Line field; it's not a lot of trouble, and I'll remove that in an eventual v2 together with some other deprecated things.

@dominikh
Copy link

@arp242 By the way, two tips:

  1. The official way of deprecating things is by saying Deprecated: ... (with that specific casing). Tools pick up that pattern. See https://github.com/golang/go/wiki/Deprecated
  2. Documentation has to precede the identifier it is documenting, so Field int // Field does X isn't technically correct (and tools won't pick it up as documentation).

@arp242
Copy link
Collaborator Author

arp242 commented Nov 16, 2021

Ah, I didn't know about the Deprecated: -convention.

AFAIK it's okay to have struct field comments not start with the identifier name; it's just the package comment, function comments, type comments, etc. that need to follow that format.

@dominikh
Copy link

Sorry, my point wasn't that the documentation has to start with the identifier name, but that the documentation has to be written before (above, really) the identifier being documented. That is, you want

type T struct {
  // This is an amazing field
  X int
}

and not

type T struct {
  X int // This is an amazing field
}

The latter will not associate the comment with the field.

@arp242
Copy link
Collaborator Author

arp242 commented Nov 16, 2021

Hm, in which cases does it fail? If I remember correctly both styles should be associated with go/ast.Field.Doc when parsing Go code, so all tools should work withthis. I'm fairly sure I checked this a few years ago to be sure, but it could be I'm misremembering this.

As far as I can find all tools work with it anyway; for example this other struct uses a mix of both styles, and it seems to work well in go doc, gopls "show documentation", and on the pkg.go.dev and godocs.io sites:

https://godocs.io/zgo.at/termfo#Terminfo
https://pkg.go.dev/zgo.at/termfo#Terminfo

@arp242
Copy link
Collaborator Author

arp242 commented Nov 16, 2021

If I remember correctly both styles should be associated with go/ast.Field.Doc when parsing Go code

Actually, turns out that's not true and I did misremember: it's available as Comment but not Doc: https://play.golang.org/p/690_QeLgLur

Still, I always much preffered this style as it keeps the struct more readable/clearer when you have just a few short comments to add. So unless there's a serious practical problem I'd prefer to keep it this way.

@dominikh
Copy link

Heh, I just finished writing https://play.golang.org/p/X7lKgHo93r5.

As far as "serious practical problems" go, I was going to list all the ways in which tools won't be able to pick up the comments as documentation. But seeing how there's precedent for your style of comments in the Go standard library (see e.g. go/ast.File), maybe this is something that should be fixed elsewhere instead (such as golang/go#20744)

@arp242
Copy link
Collaborator Author

arp242 commented Nov 16, 2021

I think in practice many tools fall back to Comment if Doc is empty, at least for struct fields. That's what e.g. gopls does.

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.

Add line/column reporting to errors More helpful usage guidance on errors
3 participants