-
-
Notifications
You must be signed in to change notification settings - Fork 249
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 source location mapping #168
Add source location mapping #168
Conversation
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.
Looks awesome! Just a couple questions.
@@ -29,6 +31,7 @@ object CalibanError { | |||
case class ExecutionError( | |||
msg: String, | |||
path: List[Either[String, Int]] = Nil, | |||
locationInfo: Option[LocationInfo] = None, |
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.
How about adding it to ParsingError
and ValidationError
?
@@ -418,9 +420,13 @@ trait DerivationSchema[R] { | |||
|
|||
object GenericSchema { | |||
|
|||
def effectfulExecutionError(path: List[Either[String, Int]], e: Throwable): ExecutionError = | |||
def effectfulExecutionError( |
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.
Not related to your code, but this one seems only used in Executor
, how about moving it there?
case ExecutionError(_, path, location, _) if path.nonEmpty => | ||
val locationJson = | ||
location.fold(Json.obj())( | ||
l => Json.obj("location" -> Json.obj("column" -> l.column.asJson, "line" -> l.line.asJson)) |
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, one more thing. As mentioned in #156, the spec suggests a format which is slightly different from what you did: "locations": [ { "line": 6, "column": 7 } ]
.
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.
note that location
is evaluated only when path
is set. This may not be what you want.
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 you’re right, though ive never actually seen multiple locations in the wild. I guess I should change it to be a List
instead of an Option
too
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 mean path
and location
are presumably independent of each other therefore the guard if path.nonEmpty =>
looks to be dangerous as it impacts evaluation of location
. One could consider location
being non-empty and path
being empty even though it's more of an intellectual exercise than a "reality".
case EnumValue(v) if mergeFields(currentField, v).collectFirst { | ||
case Field("__typename", _, _, _, _, _, _) => true | ||
case Field("__typename", _, _, _, _, _, _, _) => true | ||
}.nonEmpty => |
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 personally don't like many underscores, though I understand that was the case prior to this PR...
How about this notation?
case f: Field if f.name == "__typename" => true
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 agree it gets verbose. One concern I have about this change is that it removes exhaustive checks on the case match. I think it’s less of a concern where there are if
constraints because I think that already disables the check as well.
/** | ||
* Implementation taken from https://github.com/lihaoyi/fastparse/blob/master/fastparse/src/fastparse/ParserInput.scala | ||
*/ |
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.
you may need to reproduce his MIT license somewhere if you have not taken care of that.
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.
Good point. Is that usually at the file level or do we just need to have it once at the top level?
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 of firms who do it at product level. You'd have to ask ZIO principals or Pierre I guess.
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 think in the file would be fine. Found an example in ZIO here https://github.com/zio/zio/blob/master/stacktracer/jvm/src/main/scala/zio/internal/stacktracer/impl/AkkaLineNumbers.scala
@@ -132,7 +133,7 @@ object Validator { | |||
private def collectSelectionSets(selectionSet: List[Selection]): List[Selection] = | |||
selectionSet ++ selectionSet.flatMap { | |||
case _: FragmentSpread => Nil | |||
case Field(_, _, _, _, selectionSet) => collectSelectionSets(selectionSet) | |||
case Field(_, _, _, _, selectionSet, _) => collectSelectionSets(selectionSet) |
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'd be inclined to use a more concise notation that does not use underscores much, once again here. Again, my comment relates to pre-PR code, but since we modify this line, we may as well consider it.
case f: Field => collectSelectionSets(f.selectionSet)
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.
Here should be fine since exhaustive checking would already be disabled from the line above
@@ -161,7 +162,7 @@ object Validator { | |||
IO.foreach(selectionSet) { | |||
case FragmentSpread(_, directives) => | |||
checkDirectivesUniqueness(directives).as(directives.map((_, __DirectiveLocation.FRAGMENT_SPREAD))) | |||
case Field(_, _, _, directives, selectionSet) => | |||
case Field(_, _, _, directives, selectionSet, _) => |
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.
since we don't match on special values, again just case f: Field => ...
access f members where needed
case EnumValue(v) if mergeFields(currentField, v).collectFirst { | ||
case Field("__typename", _, _, _, _, _, _) => true | ||
case Field("__typename", _, _, _, _, _, _, _) => true | ||
}.nonEmpty => | ||
// special case of an hybrid union containing case objects, those should return an object instead of a string | ||
val obj = mergeFields(currentField, v).collectFirst { | ||
case Field(name @ "__typename", _, _, alias, _, _, _) => | ||
case Field(name @ "__typename", _, _, alias, _, _, _, _) => | ||
ObjectValue(List(alias.getOrElse(name) -> StringValue(v))) | ||
} | ||
obj.fold(s)(PureStep(_)) |
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.
In fact I am proposing this simplification for current lines 60-68, which pass the tests.
case s @ PureStep(value) =>
value match {
case EnumValue(v) =>
// special case of an hybrid union containing case objects, those should return an object instead of a string
val obj = mergeFields(currentField, v).collectFirst {
case f: Field if f.name == "__typename" =>
ObjectValue(List(f.alias.getOrElse(f.name) -> StringValue(v)))
}
obj.fold(s)(PureStep(_))
case _ => s
}
I don't see any need to do mergeFields...collectFirst
twice here, once in match guard and once in evaluation optional obj
.
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.
Note that I am considering s
to be the default value for value match
in the complex case and the second match all case just like existing code.
81adfd8
to
88b4cba
Compare
Looks good to me! It needs a rebase to solve the merge conflict with master and I think we’re good. |
88b4cba
to
88ffb52
Compare
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.
Thanks, it's awesome!
This PR adds source location mapping to fields and fragments. It is primarily used for outputting when errors occur.