Skip to content

Commit 480bf0e

Browse files
lauraharkercopybara-github
authored andcommitted
Add a JS lint check for an @externs tag hidden by the @license tag
Any text in a JSDoc block after @license is just considered part of the license, so we expect that an @externs tag is unintentional. PiperOrigin-RevId: 719353476
1 parent 5dcf355 commit 480bf0e

File tree

2 files changed

+84
-1
lines changed

2 files changed

+84
-1
lines changed

src/com/google/javascript/jscomp/lint/CheckJSDocStyle.java

+21-1
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,13 @@ public final class CheckJSDocStyle extends AbstractPostOrderCallback implements
8282
DiagnosticType.disabled("JSC_EXTERNS_FILES_SHOULD_BE_ANNOTATED",
8383
"Externs files should be annotated with @externs in the @fileoverview block.");
8484

85+
public static final DiagnosticType LICENSE_CONTAINS_AT_EXTERNS =
86+
DiagnosticType.disabled(
87+
"JSC_LICENSE_CONTAINS_AT_EXTERNS",
88+
"@license block contains an @externs annotation, which will be parsed as plain "
89+
+ "license text instead of an actual @externs annotation. You probably meant to put "
90+
+ "@externs in a separate @fileoverview block.");
91+
8592
public static final DiagnosticType PREFER_BACKTICKS_TO_AT_SIGN_CODE =
8693
DiagnosticType.disabled(
8794
"JSC_PREFER_BACKTICKS_TO_AT_SIGN_CODE",
@@ -99,6 +106,7 @@ public final class CheckJSDocStyle extends AbstractPostOrderCallback implements
99106
WRONG_NUMBER_OF_PARAMS,
100107
INCORRECT_PARAM_NAME,
101108
EXTERNS_FILES_SHOULD_BE_ANNOTATED,
109+
LICENSE_CONTAINS_AT_EXTERNS,
102110
PREFER_BACKTICKS_TO_AT_SIGN_CODE);
103111

104112
public static final DiagnosticGroup ALL_DIAGNOSTICS = new DiagnosticGroup(LINT_DIAGNOSTICS);
@@ -131,7 +139,6 @@ public void visit(NodeTraversal t, Node n, Node unused) {
131139
case LET:
132140
case CONST:
133141
case STRING_KEY:
134-
case SCRIPT:
135142
break;
136143
case MEMBER_FUNCTION_DEF:
137144
case GETTER_DEF:
@@ -142,6 +149,9 @@ public void visit(NodeTraversal t, Node n, Node unused) {
142149
checkStyleForPrivateProperties(t, n);
143150
}
144151
break;
152+
case SCRIPT:
153+
checkLicenseComment(t, n);
154+
break;
145155
default:
146156
visitNonFunction(t, n);
147157
}
@@ -465,4 +475,14 @@ public void visit(NodeTraversal t, Node n, Node parent) {
465475
}
466476
}
467477
}
478+
479+
private void checkLicenseComment(NodeTraversal t, Node n) {
480+
if (n.getJSDocInfo() == null || n.getJSDocInfo().getLicense() == null) {
481+
return;
482+
}
483+
String license = n.getJSDocInfo().getLicense();
484+
if (license.contains("@externs")) {
485+
t.report(n, LICENSE_CONTAINS_AT_EXTERNS);
486+
}
487+
}
468488
}

test/com/google/javascript/jscomp/lint/CheckJSDocStyleTest.java

+63
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
import static com.google.javascript.jscomp.lint.CheckJSDocStyle.EXTERNS_FILES_SHOULD_BE_ANNOTATED;
2020
import static com.google.javascript.jscomp.lint.CheckJSDocStyle.INCORRECT_ANNOTATION_ON_GETTER_SETTER;
2121
import static com.google.javascript.jscomp.lint.CheckJSDocStyle.INCORRECT_PARAM_NAME;
22+
import static com.google.javascript.jscomp.lint.CheckJSDocStyle.LICENSE_CONTAINS_AT_EXTERNS;
2223
import static com.google.javascript.jscomp.lint.CheckJSDocStyle.MISSING_JSDOC;
2324
import static com.google.javascript.jscomp.lint.CheckJSDocStyle.MISSING_PARAMETER_JSDOC;
2425
import static com.google.javascript.jscomp.lint.CheckJSDocStyle.MISSING_RETURN_JSDOC;
@@ -1116,6 +1117,68 @@ public void testValidExternsAnnotation_withES6Modules() {
11161117
srcs(""));
11171118
}
11181119

1120+
@Test
1121+
public void testValidLicenseCommentWithoutExterns() {
1122+
testSame(
1123+
srcs(
1124+
lines(
1125+
"/**",
1126+
" * @license",
1127+
" * Copyright 2024 Google LLC",
1128+
" */",
1129+
"",
1130+
"function Example() {}")));
1131+
}
1132+
1133+
@Test
1134+
public void testValidLicenseCommentAndExterns_separateBlocks() {
1135+
testSame(
1136+
externs(
1137+
lines(
1138+
"/**",
1139+
" * @license",
1140+
" * Copyright 2024 Google LLC",
1141+
" */",
1142+
"/**",
1143+
" * @fileoverview Some super cool externs.",
1144+
" * @externs",
1145+
" */",
1146+
"",
1147+
"function Example() {}")),
1148+
srcs(""));
1149+
}
1150+
1151+
@Test
1152+
public void testValidLicenseCommentAndExterns_sameBlocks() {
1153+
testSame(
1154+
externs(
1155+
lines(
1156+
"/**",
1157+
" * @fileoverview Some super cool externs.",
1158+
" * @externs",
1159+
" * @license",
1160+
" * Copyright 2024 Google LLC",
1161+
" */",
1162+
"",
1163+
"function Example() {}")),
1164+
srcs(""));
1165+
}
1166+
1167+
@Test
1168+
public void testInvalidLicenseComment_containsExterns() {
1169+
test(
1170+
srcs(
1171+
lines(
1172+
"/**",
1173+
" * @license",
1174+
" * Copyright 2024 Google LLC",
1175+
" * @externs - oh no, this tag is treated as part of the @license!",
1176+
" */",
1177+
"",
1178+
"function Example() {}")),
1179+
warning(LICENSE_CONTAINS_AT_EXTERNS));
1180+
}
1181+
11191182
@Test
11201183
public void testAtSignCodeDetectedWhenPresent() {
11211184
testWarning(

0 commit comments

Comments
 (0)