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

Errors logs improvements #167

Merged
merged 33 commits into from Aug 15, 2018
Merged

Errors logs improvements #167

merged 33 commits into from Aug 15, 2018

Conversation

ilyapuchka
Copy link
Collaborator

@ilyapuchka ilyapuchka commented Dec 26, 2017

Original PR #146

Example error logs:

1:9: error: 'for' statements should use the following syntax 'for x in y where condition'.
Hello {% for name in %}{{ name }}, {% endfor %}!
         ^~~~~~~~~~~
invalid-base.html2:24: error: filter error
{% block body %}Body {{ target|unknown }} {% endblock %}
                        ^~~~~~~~~~~~~~

invalid-child-super.html2:25: error: filter error
{% block body %}Child {{ block.super }}{% endblock %}
                         ^~~~~~~~~~~

@ilyapuchka ilyapuchka added this to the 1.0.0 milestone Dec 27, 2017

init(dictionary: [String: Any]? = nil, environment: Environment? = nil) {
init(dictionary: [String: Any?]? = nil, environment: Environment? = nil) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

I've seen this change in multiple pull requests. Wanna split this out into a separate PR for discussion?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

it's in #166 , I just based all other branches on its branch so that tests don't randomly fail, that's why you see them in each pr =)

@ilyapuchka
Copy link
Collaborator Author

@kylef I've simplified this a lot by storing filenames and token positions at parsing time instead of calculating them at rendering time, now it looks much closer to what you've started in #82 .

@ilyapuchka
Copy link
Collaborator Author

@kylef this started to fail on swift 3.1 with some creepy compiler error. Maybe we should just drop it already?

@DivineDominion
Copy link

Whoa this looks cool. I'd like to +1 here so somebody from the team takes a look :)

@djbe
Copy link
Contributor

djbe commented Jul 11, 2018

@ilyapuchka Any idea how hard it'd be to rebase/rework this on master for you?
While this may not seem a "flashy" issue with fancy new features, it could end up being the most useful PR of all those that are open right now for template writers.

@djbe djbe modified the milestones: 1.0.0, 0.12.0 Jul 11, 2018
@ilyapuchka
Copy link
Collaborator Author

@djbe I've updated this with the latest master. If you are going to merge any PRs please merge this first.

@@ -98,15 +98,15 @@ func testForNode() {

$0.it("renders the given nodes while filtering items using where expression") {
let nodes: [NodeType] = [VariableNode(variable: "item"), VariableNode(variable: "forloop.counter")]
let `where` = try parseExpression(components: ["item", ">", "1"], tokenParser: TokenParser(tokens: [], environment: Environment()))
let `where` = try parseExpression(components: ["item", ">", "1"], tokenParser: TokenParser(tokens: [], environment: Environment()), token: .text(value: "", at: .unknown))
Copy link
Contributor

Choose a reason for hiding this comment

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

Indentation?

let node = ForNode(resolvable: Variable("items"), loopVariables: ["item"], nodes: nodes, emptyNodes: [], where: `where`)
try expect(try node.render(context)) == "2132"
}

$0.it("renders the given empty nodes when all items filtered out with where expression") {
let nodes: [NodeType] = [VariableNode(variable: "item")]
let emptyNodes: [NodeType] = [TextNode(text: "empty")]
let `where` = try parseExpression(components: ["item", "==", "0"], tokenParser: TokenParser(tokens: [], environment: Environment()))
let `where` = try parseExpression(components: ["item", "==", "0"], tokenParser: TokenParser(tokens: [], environment: Environment()), token: .text(value: "", at: .unknown))
Copy link
Contributor

Choose a reason for hiding this comment

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

Indentation?

: nil

return ForNode(resolvable: resolvable, loopVariables: loopVariables, nodes: forNodes, emptyNodes:emptyNodes, where: `where`)
return ForNode(resolvable: resolvable, loopVariables: loopVariables, nodes: forNodes, emptyNodes:emptyNodes, where: `where`, token: token)
Copy link
Contributor

Choose a reason for hiding this comment

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

Space after the :.

}

init(resolvable: Resolvable, loopVariables: [String], nodes:[NodeType], emptyNodes:[NodeType], where: Expression? = nil) {
init(resolvable: Resolvable, loopVariables: [String], nodes:[NodeType], emptyNodes:[NodeType], where: Expression? = nil, token: Token? = nil) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Space after the :.

lineContent = line
if let rangeOfLine = self.range(of: line), rangeOfLine.contains(range.lowerBound) {
offset = distance(from: rangeOfLine.lowerBound, to:
range.lowerBound)
Copy link
Contributor

Choose a reason for hiding this comment

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

bizarre spacing here?

}


/// Render the collection of nodes in the given context
public func renderNodes(_ nodes:[NodeType], _ context:Context) throws -> String {
return try nodes.map { try $0.render(context) }.joined(separator: "")
return try nodes.map({
Copy link
Contributor

Choose a reason for hiding this comment

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

Those () aren't needed for the map.

do {
return try FilterExpression(token: filterToken, parser: self)
} catch {
if var error = error as? TemplateSyntaxError, error.token == nil {
Copy link
Contributor

Choose a reason for hiding this comment

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

Might be good to use a guard here? It avoids 1 level of indentation.

@@ -32,9 +39,304 @@ func testEnvironment() {

try expect(result) == "here"
}

func expectedSyntaxError(token: String, template: Template, description: String) -> TemplateSyntaxError {
let range = template.templateString.range(of: token)!
Copy link
Contributor

Choose a reason for hiding this comment

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

Always avoid implicit unwraps. You can replace this with a guard that falls back to an error with less information if the token isn't found. Or a fatalError (as this is a test, might as well break early).

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I would prefer failing here as it is crystal clear what is the reason than pollute the code with boilerplate guards especially considering that this is a test and we don't need graceful error handling or whatever.

Copy link
Contributor

Choose a reason for hiding this comment

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

A guard with a fatalError and a message then. It's not because it's a test that it shouldn't be good code.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I think this code is good enough, but I will do that if that's what it takes to merge this.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

@djbe done in 96a004e

file: String = #file, line: Int = #line, function: String = #function) throws {
let expectedError = expectedSyntaxError(token: token, template: template, description: reason)

let error = try expect(environment.render(template: template, context: ["names": ["Bob", "Alice"], "name": "Bob"]),
Copy link
Contributor

Choose a reason for hiding this comment

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

Both the declaration of this func as well as this line have some bizarre indentation. This also applies to the similar functions below.

Copy link
Contributor

Choose a reason for hiding this comment

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

This function is repeated quite a few times. That could be rewritten?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I'd prefer this to 6 arguments stacked on each other
this can be cleared up sometime later, this PR is big without it

"%}{{\n" +
"name\n" +
"}}{%\n" +
"endif %}."
Copy link
Contributor

Choose a reason for hiding this comment

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

Indentation for this last line.

@djbe
Copy link
Contributor

djbe commented Aug 13, 2018

Seeing as you'd rather merge this first, I'll review this one before the others.

@ilyapuchka
Copy link
Collaborator Author

@djbe fixed indentations

public init(loader: Loader? = nil,
extensions: [Extension]? = nil,
templateClass: Template.Type = Template.self,
errorReporter: ErrorReporter = SimpleErrorReporter()) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

If I understand correctly, the errorReporter property is only used by context's errorReporter property. But that isn't used anywhere (I may have missed this)?

What is the reason that the Environment and Context should hold the errorReporter? If I understand how this is intended to be used, a consumer of the library would catch an error and pass it to the errorReporter themselves? In that case I think it would make sense to remove the property from Environment and Context leaving the consumer free to create their own ErrorReporter as desired. Decoupling these a little bit.

@ilyapuchka
Copy link
Collaborator Author

@kylef this is probably a leftover from when I was using it to render error in inheritance nodes. Not needed now, removed in 92ebfe5

@ilyapuchka
Copy link
Collaborator Author

@kylef you'd like to add something?

@djbe djbe merged commit ffe8f9d into master Aug 15, 2018
@djbe djbe deleted the errors-logs-improvements branch August 15, 2018 12:06
@djbe
Copy link
Contributor

djbe commented Aug 15, 2018

Seeing as there's no more feedback, and this PR is GTM for me, we can go on to the next PRs 🎉

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants