-
Notifications
You must be signed in to change notification settings - Fork 1.7k
update the style guide on alert-messages #10405
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
Changes from 2 commits
338aead
93a6710
59c1ac2
88f1d2a
8b3ba38
9e56128
e3990e8
abb5c38
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -179,8 +179,13 @@ The select clause of each alert query defines the alert message that is displaye | |
* The message should factually describe the problem that is being highlighted–it should not contain recommendations about how to fix the problem or value judgements. | ||
* Program element references should be in 'single quotes' to distinguish them from ordinary words. Quotes are not needed around substitutions (`$@`). | ||
* Avoid constant alert message strings and include some context, if possible. For example, `The class 'Foo' is duplicated as 'Bar'.` is preferable to `This class is duplicated here.` | ||
* If a reference to the current location can't be avoided use "this location" instead of "here". For example, `Bad thing at this location.` is preferable to `Bad thing here.`. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It's not obvious to me why 'this location' would be better. I don't mind the rule, because consistent writing is a good thing — but can you add a half sentence to explain the reasoning? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I remember someone suggesting it to avoid the "click here" anti-pattern, but now I can't find that review comment. I've inserted a short sentence referencing the "click here" anti-pattern in the end. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm wondering a bit if we should keep this line. @aibaars suggested in a Slack comment that the "this location" phrasing got around the general "click-here" anti-pattern. Maybe the guidance should be that a link-text shouldn't be "here"? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In most cases could you just linkify the immediately preceding text, so something like
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Then you can keep There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I've tried to revise the text a bit, and moved the the parts about link-texts into a separate sub-section.
Yes, and the guide now includes that 👍 I still have the guidance about "this location" when you have an alert message without links, for when you can't get around mentioning the current location in the message. |
||
* Where you reference another program element, link to it if possible using a substitution (`$@`). Links should be used inline in the sentence, rather than as parenthesised lists or appositions. | ||
* When a message contains multiple links, construct a sentence that has the most variable link (that is, the link with most targets) last. For further information, see [Defining the results of a query](https://codeql.github.com/docs/writing-codeql-queries/defining-the-results-of-a-query/). | ||
* Make link texts as concise and precise as possible. E.g. avoid starting a link text with an indefinite article (a, an). For example `Path construction depends on a [user-provided value]` is preferable to `Path construction depends on [a user-provided value]`. (Where the square brackets indicate a link.) See [the W3C guide on link texts](https://www.w3.org/WAI/WCAG22/Understanding/link-purpose-in-context.html) for further information. | ||
erik-krogh marked this conversation as resolved.
Show resolved
Hide resolved
|
||
* For path queries, if possible, try to follow the template: `This path depends on a [user-provided value].`, or alternatively (if the first option doesn't work) `[User-provided value] flows to this location and is used in a path.`. | ||
* Taint tracking queries generally have that a sink "depends on" the source, and dataflow queries generally have a source that "flows to" the sink. | ||
erik-krogh marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
|
||
For examples of select clauses and alert messages, see the query source files at the following pages: | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,140 @@ | ||
/** | ||
* @name Alert messages style violation | ||
erik-krogh marked this conversation as resolved.
Show resolved
Hide resolved
|
||
* @description Alert message that doesn't follow some aspect of the style guide. | ||
erik-krogh marked this conversation as resolved.
Show resolved
Hide resolved
|
||
* See the style guide here: https://github.com/github/codeql/blob/main/docs/query-metadata-style-guide.md#alert-messages | ||
kaeluka marked this conversation as resolved.
Show resolved
Hide resolved
|
||
* @kind problem | ||
* @problem.severity warning | ||
* @id ql/alert-messages-style-violation | ||
erik-krogh marked this conversation as resolved.
Show resolved
Hide resolved
|
||
* @precision high | ||
*/ | ||
|
||
import ql | ||
|
||
/** Gets the `index`th part of the select statement. */ | ||
private AstNode getSelectPart(Select sel, int index) { | ||
result = | ||
rank[index](AstNode n, Location loc | | ||
( | ||
n.getParent*() = sel.getExpr(_) and loc = n.getLocation() | ||
or | ||
// the strings are behind a predicate call. | ||
exists(Call c, Predicate target | | ||
c.getParent*() = sel.getExpr(_) and loc = c.getLocation() | ||
| | ||
c.getTarget() = target and | ||
( | ||
target.getBody().(ComparisonFormula).getAnOperand() = n | ||
or | ||
exists(ClassPredicate sub | sub.overrides(target) | | ||
sub.getBody().(ComparisonFormula).getAnOperand() = n | ||
) | ||
) | ||
) | ||
) | ||
| | ||
n | ||
order by | ||
loc.getStartLine(), loc.getStartColumn(), loc.getEndLine(), loc.getEndColumn(), | ||
loc.getFile().getRelativePath() | ||
) | ||
} | ||
|
||
String shouldHaveFullStop(Select sel) { | ||
result = | ||
max(AstNode str, int i | | ||
str.getParent+() = sel.getExpr(1) and str = getSelectPart(sel, i) | ||
| | ||
str order by i | ||
) and | ||
not result.getValue().matches("%.") and | ||
not result.getValue().matches("%?") | ||
} | ||
|
||
String shouldStartCapital(Select sel) { | ||
result = | ||
min(AstNode str, int i | | ||
str.getParent+() = sel.getExpr(1) and str = getSelectPart(sel, i) | ||
| | ||
str order by i | ||
) and | ||
result.getValue().regexpMatch("^[a-z].*") | ||
} | ||
|
||
// see https://www.w3.org/WAI/WCAG22/Understanding/link-purpose-in-context.html | ||
String avoidHere(string part) { | ||
part = ["here", "this location"] and // TODO: prefer "this location" of the two. | ||
( | ||
result.getValue().regexpMatch(".*\\b" + part + "\\b.*") and | ||
result = getSelectPart(_, _) | ||
) | ||
} | ||
|
||
// see https://www.w3.org/WAI/WCAG22/Understanding/link-purpose-in-context.html | ||
String avoidArticleInLinkText(Select sel) { | ||
result = sel.getExpr((any(int i | i > 1))) and | ||
result = getSelectPart(sel, _) and | ||
result.getValue().regexpMatch("a|an .*") | ||
} | ||
|
||
String dontQuoteSubstitutions(Select sel) { | ||
result = getSelectPart(sel, _) and | ||
result.getValue().matches(["%'$@'%", "%\"$@\"%"]) | ||
} | ||
|
||
// "data" or "taint" | ||
string getQueryKind(Select s) { | ||
exists(TypeExpr sup | | ||
sup = s.getVarDecl(_).getType().(ClassType).getDeclaration().getASuperType() and | ||
sup.getResolvedType().(ClassType).getName() = "Configuration" | ||
| | ||
result = "data" and | ||
sup.getModule().getName() = "DataFlow" | ||
or | ||
result = "taint" and | ||
sup.getModule().getName() = "TaintTracking" | ||
) | ||
} | ||
|
||
String wrongFlowsPhrase(Select sel, string kind) { | ||
result = getSelectPart(sel, _) and | ||
kind = getQueryKind(sel) and | ||
( | ||
kind = "data" and | ||
result.getValue().matches(["% depends %", "% depend %"]) | ||
or | ||
kind = "taint" and | ||
result.getValue().matches(["% flows to %", "% flow to %"]) | ||
) | ||
} | ||
|
||
from AstNode node, string msg | ||
where | ||
not node.getLocation().getFile().getAbsolutePath().matches("%/test/%") and | ||
( | ||
node = shouldHaveFullStop(_) and | ||
msg = "Alert message should end with a full stop." | ||
kaeluka marked this conversation as resolved.
Show resolved
Hide resolved
|
||
or | ||
node = shouldStartCapital(_) and | ||
msg = "Alert message should start with a capital letter." | ||
or | ||
exists(string part | node = avoidHere(part) | | ||
part = "here" and | ||
msg = "Avoid using the phrase \"" + part + "\" in alert messages." | ||
kaeluka marked this conversation as resolved.
Show resolved
Hide resolved
|
||
or | ||
part != "here" and | ||
msg = "Try to avoid using the phrase \"" + part + "\" in alert messages if possible." | ||
) | ||
or | ||
node = avoidArticleInLinkText(_) and | ||
msg = "Avoid starting a link text with an indefinite article." | ||
or | ||
node = dontQuoteSubstitutions(_) and | ||
msg = "Don't quote substitutions in alert messages." | ||
kaeluka marked this conversation as resolved.
Show resolved
Hide resolved
|
||
or | ||
node = wrongFlowsPhrase(_, "data") and | ||
msg = "Use \"flows to\" instead of \"depends on\" in taint tracking queries." | ||
or | ||
node = wrongFlowsPhrase(_, "taint") and | ||
msg = "Use \"depends on\" instead of \"flows to\" in data flow queries." | ||
erik-krogh marked this conversation as resolved.
Show resolved
Hide resolved
|
||
) | ||
select node, msg |
Uh oh!
There was an error while loading. Please reload this page.