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
SpanMarkPointMissingMaskDetector - Ensure that span flags are checked correctly #14
SpanMarkPointMissingMaskDetector - Ensure that span flags are checked correctly #14
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.
Nice work! Mostly little nits and suggestions
slack-lint/src/main/java/slack/lint/text/SpanPointMarkDangerousCheckDetector.kt
Outdated
Show resolved
Hide resolved
slack-lint/src/main/java/slack/lint/text/SpanPointMarkDangerousCheckDetector.kt
Outdated
Show resolved
Hide resolved
slack-lint/src/main/java/slack/lint/text/SpanPointMarkDangerousCheckDetector.kt
Outdated
Show resolved
Hide resolved
slack-lint/src/main/java/slack/lint/text/SpanPointMarkDangerousCheckDetector.kt
Outdated
Show resolved
Hide resolved
slack-lint/src/main/java/slack/lint/text/SpanPointMarkDangerousCheckDetector.kt
Outdated
Show resolved
Hide resolved
slack-lint/src/test/java/slack/lint/text/SpanPointMarkDangerousCheckDetectorTest.kt
Outdated
Show resolved
Hide resolved
slack-lint/src/main/java/slack/lint/text/SpanPointMarkDangerousCheckDetector.kt
Outdated
Show resolved
Hide resolved
slack-lint/src/test/java/slack/lint/text/SpanPointMarkDangerousCheckDetectorTest.kt
Outdated
Show resolved
Hide resolved
slack-lint/src/test/java/slack/lint/text/SpanPointMarkDangerousCheckDetectorTest.kt
Outdated
Show resolved
Hide resolved
slack-lint/src/main/java/slack/lint/text/SpanPointMarkDangerousCheckDetector.kt
Outdated
Show resolved
Hide resolved
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.
Whoops sorry didn't mean to approve just yet
Whoops sorry didn't mean to approve just yet
…sCheckDetector.kt Co-authored-by: Zac Sweers <pandanomic@gmail.com>
- make this name match the others - move class out to be top-level in the file - check UastBinaryOperator.EQUALS - functions can all be private - raw string - use the in operator - make this an extension function - rename to resolveQualifiedNameOrNull() - use a reference expression here
- exercises different levels of imports (constant directly, class + reference, fully qualified reference). - visitBinaryExpression - prefix on all of these are redundant - remove @language("kotlin") - indent inconsistency - keep these names simple
…llen/slack-lints into hunvil-and-josh/span-point-mark
No need to call .trimIndent() in issue registration strings; they are already trimmed by indent by lint when displaying to users [LintImplTrimIndent]
Spans flags can have priority or other bits set. \ | ||
Ensure that Span flags are checked using \ | ||
`currentFlag and Spanned.SPAN_POINT_MARK_MASK == desiredFlag` \ | ||
rather than just `currentFlag == desiredFlag` |
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.
👍
/** | ||
* Checks for SpanPointMarkDangerousCheck. See [ISSUE]. | ||
*/ | ||
class SpanPointMarkDangerousCheckDetector : Detector(), SourceCodeScanner { |
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've been thinking about this and I think "dangerous" is too strong of a word here. Let's pick something else, like "incorrect" or "missing mask check", something to that effect that's more descriptive
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 do you like SpanMarkPointMissingMaskDetector
?
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.
sounds 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.
/** | ||
* Checks for SpanPointMarkDangerousCheck. See [ISSUE]. | ||
*/ |
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.
nit:
/** | |
* Checks for SpanPointMarkDangerousCheck. See [ISSUE]. | |
*/ | |
/** Checks for SpanPointMarkDangerousCheck. See [ISSUE]. */ |
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.
👍 Fixed in affa6e8
companion object { | ||
val ISSUE = Issue.create( | ||
id = "SpanPointMarkDangerousCheck", | ||
briefDescription = "Check Span Flags Using Bitmask", |
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.
This should be a sentence not a title
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.
👍 Fixed in f4b4da4
private fun matchesMarkPoint(expression: UExpression): Boolean { | ||
return getQualifiedName(expression) in MARK_POINT_FIELDS | ||
} |
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.
private fun matchesMarkPoint(expression: UExpression): Boolean { | |
return getQualifiedName(expression) in MARK_POINT_FIELDS | |
} | |
private fun matchesMarkPoint(expression: UExpression) = getQualifiedName(expression) in MARK_POINT_FIELDS |
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.
👍 Fixed in 1ff3397
import org.jetbrains.uast.UReferenceExpression | ||
import org.jetbrains.uast.tryResolve | ||
|
||
fun UExpression.resolveQualifiedNameOrNull(): String? { |
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.
Add this to an existing util file rather than its own dedicated one. Also please write a short doc
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.
👍 Fixed in 130aa73
} | ||
} | ||
|
||
private fun getQualifiedName(expression: UExpression): String? { |
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.
Should this be an extension?
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.
Do you prefer an extension in util file or private extension in this 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.
👍 Fixed in 7804c86
return getQualifiedName(expression) in MARK_POINT_FIELDS | ||
} | ||
|
||
private fun matchesMask(expression: UExpression): Boolean { |
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.
extension? Also seems like this should be "isBinaryExpressionWithMaskOperand" rather than matches? Descriptiveness is better here
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.
ditto, Do you prefer an extension in util file or private extension in this 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.
this isn't reusable elsewhere so keep it here. Same with the other ones
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.
} | ||
} | ||
|
||
private fun matchesMarkPoint(expression: UExpression): Boolean { |
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.
Extension + maybe rename to isMarkPointFieldName
?
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.
ditto, Do you prefer an extension in util file or private extension in this 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.
What do you mean by especially with the merge? |
I believe after a merge, github kind of loses track of how to link shas and I get a page like this. Comments here don't appear to show up in the regular review. So, the better isolated they are the better because it's easier to review quickly. Large "address CR" commits are noisy and essentially require a re-review rather than just confirmation. |
@ZacSweers Thanks for your feedback! I learned a couple things. Note that I usually take a more reserved approach to extension functions, as they make polymorphism down the road more difficult. |
Not sure I follow. In bytecode, these are the same and they're just purely functional fun computeStuff(param: String): String = ...
fun String.computeStuff(): String = ... |
Nice work! |
What I mean is: open class SomeAwesomeClass {
fun doStuff()...
open fun doOtherStuff()...
}
class MyClassThatDoesWhatIWant {
override fun doOtherStuff()....
}
// ... dependency inject MyClassThatDoesWhatIWant instead of SomeAwesomeClass vs. class SomeAwesomeClass {
}
fun SomeAwesomeClass.doStuff()...
fun SomeAwesomeClass.doOtherStuff()... ... Oh no, |
Summary
Ensure that span flags are checked correctly.
❌ Incorrect
spanned.getSpanFlags(span) == Spanned.INCLUSIVE_INCLUSIVE
✅ Correct
spanned.getSpanFlags(span) and Spanned.SPAN_POINT_MARK_MASK == Spanned.INCLUSIVE_INCLUSIVE
❓ Why
Spans flags may have priority bits or other bits set.
Requirements (place an
x
in each[ ]
)