-
-
Notifications
You must be signed in to change notification settings - Fork 220
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
Positional info [SL-2197] #106
Conversation
RE the chat we had elsewhere about showing file path or JSON path: I think we should include both in JSON, and only show file path in the CLI. Most users will be really excited to be able to CTRL/CMD+Click the file path and open it right up. If folk need the path information it will be available in JSON and other formats as we grow them out, and if users request we find a way to include it in stylish we can do that later. Does that sound good? |
@philsturgeon |
Awesome! This means v2.0 is very close.
|
c8d805e
to
2b4576a
Compare
src/spectral.ts
Outdated
@@ -25,9 +26,9 @@ export class Spectral { | |||
this.resolver = opts && opts.resolver ? opts.resolver : new Resolver(); | |||
} | |||
|
|||
public async run(target: object): Promise<IRuleResult[]> { | |||
public async run(target: object, parserMeta?: IParserMeta): Promise<IRuleResult[]> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
parserMeta
is needed to calculate lines and columns for given JSON Path.
Ideally, we could have a single argument accepting IParserResult
, but that would be breaking and would force users to use parseWithPointers
functions.
If parserMeta
is provided, range property (lines and columns) is attached to a single result and hence can be displayed in the output (CLI) or consumed programmatically (API).
@philsturgeon @tbarn your thoughts on that?
We will need to document it for sure.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is this thing for?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also, IRange
(range property) follows LSP standard and hence lines and characters (columns) are 0-based.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@philsturgeon It's needed by getJsonPathForPosition
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I know the above looks slightly weird, but it preserves the old behavior.
It simply degrades gracefully - if no parserMeta
is provided, all validation results will still have all the properties except range (and source - name of the file).
We could have a single argument, but we'd force user to use parseWithPointers
function in such case, which is something we most likely want to avoid.
The other possible solution is to have another method, i.e. runParsed
or similar, but IMHO this would introduce even bigger confusion to end-users.
@tbarn @philsturgeon @marbemac thoughts?
Note, The solution is also briefly described in the readme above.
Let me know what your thoughts are.
Edit:
Alternatively, we could also make run
accept strings only (that'd be my favorite solution)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, sounds good to me.
What about S^2 (I hope ya know what I mean)? I'd like to avoid reparsing as much as possible in this particular case as this may degrade performance.
Apart from that, we'd still need to figure out some solution for CLI. CLI passes an already parsed content and I assume the result of safeStringify
wouldn't equal the actual content of a file.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Or did you mean to have the following implementation?
run(target: IParserAstResult | object) {
// if plain object, reparse
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What about something like this?
Not sure we even need to document the IParserAstResult
right now - can use internally and from studio for now.
run(target: IParserAstResult | object | string) {
let parsed = target;
if (!isParserAstResult(target)) {
parsed = parseWithPointers(safeStringify(target));
}
// ...resolve parsed, etc
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The above looks good to me.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah having it there but hidden from docs is fine with me.
I'm getting an error when I do
|
@tbarn make sure to run |
@P0lip I did but I missed that it had an error too:
what version of node should I be using? |
@tbarn In any case, I don't see a reason not to support Node 9, therefore, the issue you expected should be fixed. |
@P0lip I probably set my nvm to v9 to test something else. I just want to make sure we have these kinds of things recorded in the contributing doc for others. I got it running, tested out a few different spec documents, and it looks great to me. |
@tbarn |
Shared elsewhere, but I wanted to share here too. The bump on the stoplight/yaml package fixed the problem on v9. |
src/spectral.ts
Outdated
public async run(target: object): Promise<IRuleResult[]> { | ||
const resolvedTarget = (await this.resolver.resolve(target)).result; | ||
return runRules(target, this.rules, this.functions, { resolvedTarget }); | ||
public async run(target: IParserMeta | object | string): Promise<IRuleResult[]> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Instead of messing with the target argument, could we possibly add a second optional argument for this stuff?
then we can throw warnings saying "We cannot give you any positional information because you didnt give us enough information" and the output can be ?? or something? Does that make any sense?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, we had that done this way initially but was changed as discussed here #106 (comment)
In general, I'm not opinionated on that at all and I'm happy to go with whatever is more intuitive for users.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, my comment saying Yeah having it there but hidden from docs is fine with me.
was written from mobile and I hadn't seen marcs suggestion.
Ok, so the name IParserMeta is whats throwing me. Marcs example makes it clear that it can either be a parsed AST object, or a generic object, and if its the generic object then its not gonna work with line numbers and stuff. That's all fine if we use a name a bit more like his.
Metadata is usually a different thing to data, so if it has meta in the name I'd expect it to be a different argument.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@philsturgeon
Yeah, naming is certainly not my strongest asset 😆
I can name it IParsedAst
if it makes everything more clear.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Renamed to IParsedResult
since it also has some different properties than just ast
, so this could be confusing.
Let me know what you think @philsturgeon
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
and if its the generic object then its not gonna work with line numbers and stuff
It should still work if go with original suggestion. Basically, if it's a plain object we stringily it and parse it with our parser to get positional info:
run(target: IParserAstResult | object | string) {
let parsed = target;
if (!isParserAstResult(target)) {
parsed = parseWithPointers(safeStringify(target));
}
// ...resolve parsed, etc
}
So no compromise for end user passing in plain object or stringified object.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, we reparse it therefore some ranges are attached. Initially, when we didn't reparse the object, ranges were missing.
fddf53f
to
4636c76
Compare
4636c76
to
9d91ed4
Compare
Perfect!
|
* feat: implement positional info * feat: show filepath * test: update snapshots * feat: use resolve instead of join * fix: show message if rule summary is missing * chore: document code, update readme and rename uri to source * refactor: exclude source if undefined * refactor: enhance run * feat: sort results by line * fix: summary is yellow in some cases * feat: rename IParsedResult -> IParsedResult
Please check if the PR fulfills these requirements
What kind of change does this PR introduce?
fixes #92
Range is now attached to a single validation object, therefore it's possible to see where the issue/error actually occurs in a file (when using Spectral using API)
Moreover, CLI makes use of them to display line and column as shown in the screenshot below
What is the current behavior?
Range is not included (API usage) and positional info is not displayed (CLI usage).
If this is a feature change, what is the new behavior?
See the screenshot above.
Does this PR introduce a breaking change?
No changes required!
Other information
(e.g. detailed explanation, related issues, links for us to have context, eg. stackoverflow, issues outside of the repo, forum, etc.)