Skip to content

Commit

Permalink
Excluded native JSX elements from no-unsafe-any (palantir#3699)
Browse files Browse the repository at this point in the history
* Excluded native JSX elements from no-unsafe-any

* Lint fix: double-apostrophe

Interesting how TypeScript auto-added single-apostrophes...

* ...almost working..

* Split no-unsafe-any into separate tests

* Added test cases for fragments

* Added case for TS2.1 and fragments
  • Loading branch information
Josh Goldberg authored and giladgray committed May 3, 2018
1 parent c86193f commit 93fd0ac
Show file tree
Hide file tree
Showing 9 changed files with 55 additions and 1 deletion.
28 changes: 27 additions & 1 deletion src/rules/noUnsafeAnyRule.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,10 @@
* limitations under the License.
*/

import { isReassignmentTarget, isSymbolFlagSet, isTokenKind, isTypeFlagSet, isTypeNodeKind } from "tsutils";
import { isIdentifier, isReassignmentTarget, isSymbolFlagSet, isTokenKind, isTypeFlagSet, isTypeNodeKind } from "tsutils";
import * as ts from "typescript";
import * as Lint from "../index";
import { isLowerCase } from "../utils";

export class Rule extends Lint.Rules.TypedRule {
/* tslint:disable:object-literal-sort-keys */
Expand Down Expand Up @@ -387,9 +388,34 @@ function isNodeAny(node: ts.Node, checker: ts.TypeChecker): boolean {
return isAny(checker.getDeclaredTypeOfSymbol(symbol));
}
}

// Lowercase JSX elements are assumed to be allowed by design
if (isJsxNativeElement(node)) {
return false;
}

return isAny(checker.getTypeAtLocation(node));
}

const jsxElementTypes = new Set<ts.SyntaxKind>([
ts.SyntaxKind.JsxClosingElement,
ts.SyntaxKind.JsxOpeningElement,
ts.SyntaxKind.JsxSelfClosingElement,
]);

function isJsxNativeElement(node: ts.Node): boolean {
if (!isIdentifier(node) || node.parent === undefined) {
return false;
}

// TypeScript <=2.1 incorrectly parses JSX fragments
if (node.text === "") {
return true;
}

return jsxElementTypes.has(node.parent.kind) && isLowerCase(node.text[0]);
}

function isStringLike(expr: ts.Expression, checker: ts.TypeChecker): boolean {
return isTypeFlagSet(checker.getTypeAtLocation(expr), ts.TypeFlags.StringLike);
}
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
15 changes: 15 additions & 0 deletions test/rules/no-unsafe-any/jsx/test.tsx.lint
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
declare const AnyComponent: any;

const nativeJsxFull = <span></span>;
const nativeJsxShort = <span />;

const nativeFragmentEmpty = <></>;
const nativeFragmentFull = <><span /></>;

const componentJsxFull = <AnyComponent></AnyComponent>;
~~~~~~~~~~~~ [0]
~~~~~~~~~~~~ [0]
const componentJsxShort = <AnyComponent />;
~~~~~~~~~~~~ [0]

[0]: Unsafe use of expression of type 'any'.
8 changes: 8 additions & 0 deletions test/rules/no-unsafe-any/jsx/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"compilerOptions": {
"jsx": "react",
"module": "commonjs",
"target": "es6",
"experimentalDecorators": true
}
}
5 changes: 5 additions & 0 deletions test/rules/no-unsafe-any/jsx/tslint.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"rules": {
"no-unsafe-any": true
}
}

0 comments on commit 93fd0ac

Please sign in to comment.