Skip to content

Commit

Permalink
Add a custom conformance rule BanCreateDom.
Browse files Browse the repository at this point in the history
-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=150071054
  • Loading branch information
vrana authored and Tyler Breisacher committed Mar 14, 2017
1 parent 2ce5423 commit 50981b9
Show file tree
Hide file tree
Showing 2 changed files with 135 additions and 0 deletions.
87 changes: 87 additions & 0 deletions src/com/google/javascript/jscomp/ConformanceRules.java
Original file line number Diff line number Diff line change
Expand Up @@ -1424,4 +1424,91 @@ protected ConformanceResult checkConformance(NodeTraversal t, Node n) {
return ConformanceResult.CONFORMANCE;
}
}

/**
* Ban {@code goog.dom.createDom} and {@code goog.dom.DomHelper#createDom} with parameters
* specified in {@code value} in the format tagname.attribute, e.g. {@code value: 'iframe.src'}.
*/
public static final class BanCreateDom extends AbstractRule {
private List<String[]> bannedTagAttrs;

public BanCreateDom(AbstractCompiler compiler, Requirement requirement)
throws InvalidRequirementSpec {
super(compiler, requirement);
bannedTagAttrs = new ArrayList<>();
for (String value : requirement.getValueList()) {
String[] tagAttr = value.toLowerCase().split("\\.");
if (tagAttr.length != 2 || tagAttr[0].isEmpty() || tagAttr[1].isEmpty()) {
throw new InvalidRequirementSpec("Values must be in the format tagname.attribute.");
}
bannedTagAttrs.add(tagAttr);
}
if (bannedTagAttrs.isEmpty()) {
throw new InvalidRequirementSpec("Specify one or more values.");
}
}

@Override
protected ConformanceResult checkConformance(NodeTraversal t, Node n) {
if (!isCreateDomCall(n)) {
return ConformanceResult.CONFORMANCE;
}
if (n.getChildCount() < 3) {
// goog.dom.createDom('iframe') is fine.
return ConformanceResult.CONFORMANCE;
}

String tagName = getTagName(n.getSecondChild());
Node attrs = n.getChildAtIndex(2);

for (String[] tagAttr : bannedTagAttrs) {
if (tagName != null && !tagAttr[0].equals(tagName)) {
continue;
}
if (!attrs.isObjectLit()) {
// Attrs is not an object literal and tagName matches or is unknown.
return ConformanceResult.POSSIBLE_VIOLATION;
}
if (NodeUtil.getFirstPropMatchingKey(attrs, tagAttr[1]) != null) {
return tagName == null
? ConformanceResult.POSSIBLE_VIOLATION
: ConformanceResult.VIOLATION;
}
}

return ConformanceResult.CONFORMANCE;
}

private String getTagName(Node tag) {
if (tag.isString()) {
return tag.getString().toLowerCase();
} else if (tag.isGetProp()
&& tag.getFirstChild().getQualifiedName().equals("goog.dom.TagName")) {
return tag.getLastChild().getString().toLowerCase();
}
return null;
}

private boolean isCreateDomCall(Node n) {
if (NodeUtil.isCallTo(n, "goog.dom.createDom")) {
return true;
}
if (!n.isCall()) {
return false;
}
Node function = n.getFirstChild();
if (!function.isGetProp()) {
return false;
}
TypeI type = function.getFirstChild().getTypeI();
if (type == null) {
return false;
}
if ("goog.dom.DomHelper".equals(type.getDisplayName()) && function.getLastChild().isString()
&& "createDom".equals(function.getLastChild().getString())) {
return true;
}
return false;
}
}
}
48 changes: 48 additions & 0 deletions test/com/google/javascript/jscomp/CheckConformanceTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -1671,4 +1671,52 @@ public void testRequireUseStrict3() {
"var x$$module$testcode=2;",
"module$testcode.x = x$$module$testcode;"));
}

public void testBanCreateDom() {
configuration =
"requirement: {\n" +
" type: CUSTOM\n" +
" java_class: 'com.google.javascript.jscomp.ConformanceRules$BanCreateDom'\n" +
" error_message: 'BanCreateDom Message'\n" +
" value: 'iframe.src'\n" +
"}";

testWarning(
"goog.dom.createDom('iframe', {'src': ''});",
CheckConformance.CONFORMANCE_VIOLATION,
"Violation: BanCreateDom Message");

testWarning(
"goog.dom.createDom('iframe', {'src': '', 'name': ''}, '');",
CheckConformance.CONFORMANCE_VIOLATION,
"Violation: BanCreateDom Message");

testWarning(
"goog.dom.createDom(goog.dom.TagName.IFRAME, {'src': ''});",
CheckConformance.CONFORMANCE_VIOLATION,
"Violation: BanCreateDom Message");

// TODO(jakubvrana): Add a test for goog.dom.DomHelper.

testWarning(
"goog.dom.createDom(tag, {'src': ''});",
CheckConformance.CONFORMANCE_POSSIBLE_VIOLATION,
"Possible violation: BanCreateDom Message");

testWarning(
"goog.dom.createDom('iframe', attrs);",
CheckConformance.CONFORMANCE_POSSIBLE_VIOLATION,
"Possible violation: BanCreateDom Message");

testWarning(
"goog.dom.createDom(tag, attrs);",
CheckConformance.CONFORMANCE_POSSIBLE_VIOLATION,
"Possible violation: BanCreateDom Message");

testSame("goog.dom.createDom('iframe');");
testSame("goog.dom.createDom('iframe', {'name': ''});");
testSame("goog.dom.createDom('img', {'src': ''});");
testSame("goog.dom.createDom('img', attrs);");
testSame("goog.dom.createDom(tag, {});");
}
}

0 comments on commit 50981b9

Please sign in to comment.