-
Notifications
You must be signed in to change notification settings - Fork 89
DeepLink Query Parameter Value Template Matching #157
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
base: main
Are you sure you want to change the base?
DeepLink Query Parameter Value Template Matching #157
Conversation
Summary of ChangesHello @yutailang0119, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed! This pull request addresses a critical issue in the Highlights
Using Gemini Code AssistThe full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips. Invoking Gemini You can request assistance from Gemini at any point by creating a comment using either
Customization To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a Limitations & Feedback Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here. You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension. Footnotes
|
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.
Code Review
This pull request correctly addresses the issue of mismatched query parameter keys and value templates in deep links. The changes in DeepLinkPattern.kt are well-implemented to extract both the query key and the property name from the URI pattern.
My review includes two main points:
- A critical fix in
DeepLinkMatcher.ktto prevent a potentialNullPointerExceptionwhen handling unknown query parameters in a requested URI. - A suggestion in
DeepLinkPattern.ktto convert the newQueryParameterclass to adata classfor better maintainability, following Kotlin best practices.
Overall, the changes are good, but the potential crash needs to be addressed.
| request.queries.forEach { query -> | ||
| val name = query.key | ||
| val queryStringParser = deepLinkPattern.queryValueParsers[name] | ||
| val queryParsedValue = try { | ||
| queryStringParser!!.invoke(query.value) | ||
| val queryParameter = deepLinkPattern.queryParameters[name]!! | ||
| val (argName, parsedValue) = try { | ||
| Pair(queryParameter.serialName ?: name, queryParameter.typeParser.invoke(query.value)) | ||
| } catch (e: IllegalArgumentException) { | ||
| Log.e(TAG_LOG_ERROR, "Failed to parse query name:[$name] value:[${query.value}].", e) | ||
| return null | ||
| } | ||
| args[name] = queryParsedValue | ||
| args[argName] = parsedValue | ||
| } |
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 use of the non-null assertion operator (!!) on line 51 can cause a NullPointerException if the request URI contains a query parameter that is not defined in the deep link pattern. This would crash the application. It's safer to handle this case by treating it as a non-match, which is consistent with how path segments are handled. Using a for loop instead of forEach allows for an early return from the match function if an unknown parameter is found.
| request.queries.forEach { query -> | |
| val name = query.key | |
| val queryStringParser = deepLinkPattern.queryValueParsers[name] | |
| val queryParsedValue = try { | |
| queryStringParser!!.invoke(query.value) | |
| val queryParameter = deepLinkPattern.queryParameters[name]!! | |
| val (argName, parsedValue) = try { | |
| Pair(queryParameter.serialName ?: name, queryParameter.typeParser.invoke(query.value)) | |
| } catch (e: IllegalArgumentException) { | |
| Log.e(TAG_LOG_ERROR, "Failed to parse query name:[$name] value:[${query.value}].", e) | |
| return null | |
| } | |
| args[name] = queryParsedValue | |
| args[argName] = parsedValue | |
| } | |
| for (query in request.queries) { | |
| val name = query.key | |
| val queryParameter = deepLinkPattern.queryParameters[name] ?: return null | |
| val (argName, parsedValue) = try { | |
| Pair(queryParameter.serialName ?: name, queryParameter.typeParser.invoke(query.value)) | |
| } catch (e: IllegalArgumentException) { | |
| Log.e(TAG_LOG_ERROR, "Failed to parse query name:[$name] value:[${query.value}].", e) | |
| return null | |
| } | |
| args[argName] = parsedValue | |
| } |
| class QueryParameter( | ||
| val serialName: String?, | ||
| val typeParser: TypeParser, | ||
| ) |
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.
For classes that primarily hold data, like QueryParameter, it's a good practice to declare them as a data class. This automatically generates useful methods like equals(), hashCode(), toString(), and copy(), which improves code conciseness and can be helpful for debugging.
| class QueryParameter( | |
| val serialName: String?, | |
| val typeParser: TypeParser, | |
| ) | |
| data class QueryParameter( | |
| val serialName: String?, | |
| val typeParser: TypeParser, | |
| ) |
|
Hi thanks for the PR! The query matching in this recipe is based on matching the deeplink url's The original recipe's query paramName is based on In your solution, you updated the So the key point here is making sure the url's paramName matches the serialName, and not necessarily whether the serialName matches the template name. So if you do want to support |
|
Thank you for the response! I agree that the difficulty arises because the sample use case currently constructs the URL using To allow the use of However, since the query matching is based on Given this, would the approach of restricting the use of |
This PR addresses an issue where DeepLink handling fails when the query parameter's key and its value template are different, leading to an
ArrayIndexOutOfBoundsException.Issue
When using a
uriPatternin Navigation 2 that includes a query parameter with a value template (e.g.,?firstName={first_name}), thenav3-recipesimplementation currently fails if the key (firstName) does not exactly match the template variable (first_name).This happens because the current logic incorrectly assumes that the query parameter key will always be identical to the variable name (the value template) and does not account for cases where the two might differ, such as when using
@SerialName.Reproduction
The issue is triggered if a key uses a different serialization name than its property name, for example:
In the DeepLink URI pattern:
...?first_name={firstName}This recipe currently throws an
ArrayIndexOutOfBoundsExceptionwhen trying to process this mismatched key/value template pair.Solution
This fix modifies the DeepLink processing to correctly handle and match the parameter key with the separate parameter value template, resolving the
ArrayIndexOutOfBoundsExceptionand allowing for flexibility in parameter naming (e.g., when using@SerialName).