From a42dd9d54ca19e9a2981e3b203ae5d00393380d2 Mon Sep 17 00:00:00 2001 From: Wesley Wigham Date: Tue, 7 Jul 2020 13:51:04 -0700 Subject: [PATCH] Use jsxFragmentFactory entity name for factory name lookup from checking fragments --- src/compiler/checker.ts | 5 ++ .../jsxFactoryAndJsxFragmentFactory.js | 1 + .../jsxFactoryAndJsxFragmentFactory.symbols | 3 ++ .../jsxFactoryAndJsxFragmentFactory.types | 3 ++ .../jsxFragmentFactoryNoUnusedLocals.js | 30 +++++++++++ .../jsxFragmentFactoryNoUnusedLocals.symbols | 39 +++++++++++++++ .../jsxFragmentFactoryNoUnusedLocals.types | 50 +++++++++++++++++++ .../jsxFactoryAndJsxFragmentFactory.tsx | 1 + .../jsxFragmentFactoryNoUnusedLocals.tsx | 18 +++++++ 9 files changed, 150 insertions(+) create mode 100644 tests/baselines/reference/jsxFragmentFactoryNoUnusedLocals.js create mode 100644 tests/baselines/reference/jsxFragmentFactoryNoUnusedLocals.symbols create mode 100644 tests/baselines/reference/jsxFragmentFactoryNoUnusedLocals.types create mode 100644 tests/cases/compiler/jsxFragmentFactoryNoUnusedLocals.tsx diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 61f31d7390754..a4b3631c918d4 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -968,6 +968,11 @@ namespace ts { return file.localJsxFragmentNamespace = getFirstIdentifier(file.localJsxFragmentFactory).escapedText; } } + const entity = getJsxFragmentFactoryEntity(location); + if (entity) { + file.localJsxFragmentFactory = entity; + return file.localJsxFragmentNamespace = getFirstIdentifier(entity).escapedText; + } } else { if (file.localJsxNamespace) { diff --git a/tests/baselines/reference/jsxFactoryAndJsxFragmentFactory.js b/tests/baselines/reference/jsxFactoryAndJsxFragmentFactory.js index 3bffa897aef87..f36a80ec196a6 100644 --- a/tests/baselines/reference/jsxFactoryAndJsxFragmentFactory.js +++ b/tests/baselines/reference/jsxFactoryAndJsxFragmentFactory.js @@ -1,5 +1,6 @@ //// [jsxFactoryAndJsxFragmentFactory.tsx] declare var h: any; +declare var Frag: any; <>; <>1<>2.12.2; diff --git a/tests/baselines/reference/jsxFactoryAndJsxFragmentFactory.symbols b/tests/baselines/reference/jsxFactoryAndJsxFragmentFactory.symbols index e21f2fac91861..0c7b584e79208 100644 --- a/tests/baselines/reference/jsxFactoryAndJsxFragmentFactory.symbols +++ b/tests/baselines/reference/jsxFactoryAndJsxFragmentFactory.symbols @@ -2,5 +2,8 @@ declare var h: any; >h : Symbol(h, Decl(jsxFactoryAndJsxFragmentFactory.tsx, 0, 11)) +declare var Frag: any; +>Frag : Symbol(Frag, Decl(jsxFactoryAndJsxFragmentFactory.tsx, 1, 11)) + <>; <>1<>2.12.2; diff --git a/tests/baselines/reference/jsxFactoryAndJsxFragmentFactory.types b/tests/baselines/reference/jsxFactoryAndJsxFragmentFactory.types index 01d2d3003c6b1..d30708d5166b0 100644 --- a/tests/baselines/reference/jsxFactoryAndJsxFragmentFactory.types +++ b/tests/baselines/reference/jsxFactoryAndJsxFragmentFactory.types @@ -2,6 +2,9 @@ declare var h: any; >h : any +declare var Frag: any; +>Frag : any + <>; ><> : error diff --git a/tests/baselines/reference/jsxFragmentFactoryNoUnusedLocals.js b/tests/baselines/reference/jsxFragmentFactoryNoUnusedLocals.js new file mode 100644 index 0000000000000..90cad7ac3521b --- /dev/null +++ b/tests/baselines/reference/jsxFragmentFactoryNoUnusedLocals.js @@ -0,0 +1,30 @@ +//// [jsxFragmentFactoryNoUnusedLocals.tsx] +/// +import { Fragment, createElement } from "react" + +type CounterProps = { + count?: number +} + +export function Counter({ count = 0 }: CounterProps) { + const [cnt, setCnt] = null as any; + return <> +

{cnt}

+ + +} + +//// [jsxFragmentFactoryNoUnusedLocals.js] +"use strict"; +exports.__esModule = true; +exports.Counter = void 0; +/// +var react_1 = require("react"); +function Counter(_a) { + var _b = _a.count, count = _b === void 0 ? 0 : _b; + var _c = null, cnt = _c[0], setCnt = _c[1]; + return react_1.createElement(react_1.Fragment, null, + react_1.createElement("p", null, cnt), + react_1.createElement("button", { onClick: function () { return setCnt(function (prev) { return prev + 1; }); }, type: "button" }, "Update")); +} +exports.Counter = Counter; diff --git a/tests/baselines/reference/jsxFragmentFactoryNoUnusedLocals.symbols b/tests/baselines/reference/jsxFragmentFactoryNoUnusedLocals.symbols new file mode 100644 index 0000000000000..cbd2a790aaffa --- /dev/null +++ b/tests/baselines/reference/jsxFragmentFactoryNoUnusedLocals.symbols @@ -0,0 +1,39 @@ +=== tests/cases/compiler/jsxFragmentFactoryNoUnusedLocals.tsx === +/// +import { Fragment, createElement } from "react" +>Fragment : Symbol(Fragment, Decl(jsxFragmentFactoryNoUnusedLocals.tsx, 1, 8)) +>createElement : Symbol(createElement, Decl(jsxFragmentFactoryNoUnusedLocals.tsx, 1, 18)) + +type CounterProps = { +>CounterProps : Symbol(CounterProps, Decl(jsxFragmentFactoryNoUnusedLocals.tsx, 1, 47)) + + count?: number +>count : Symbol(count, Decl(jsxFragmentFactoryNoUnusedLocals.tsx, 3, 21)) +} + +export function Counter({ count = 0 }: CounterProps) { +>Counter : Symbol(Counter, Decl(jsxFragmentFactoryNoUnusedLocals.tsx, 5, 1)) +>count : Symbol(count, Decl(jsxFragmentFactoryNoUnusedLocals.tsx, 7, 25)) +>CounterProps : Symbol(CounterProps, Decl(jsxFragmentFactoryNoUnusedLocals.tsx, 1, 47)) + + const [cnt, setCnt] = null as any; +>cnt : Symbol(cnt, Decl(jsxFragmentFactoryNoUnusedLocals.tsx, 8, 11)) +>setCnt : Symbol(setCnt, Decl(jsxFragmentFactoryNoUnusedLocals.tsx, 8, 15)) + + return <> +

{cnt}

+>p : Symbol(JSX.IntrinsicElements.p, Decl(react16.d.ts, 2467, 102)) +>cnt : Symbol(cnt, Decl(jsxFragmentFactoryNoUnusedLocals.tsx, 8, 11)) +>p : Symbol(JSX.IntrinsicElements.p, Decl(react16.d.ts, 2467, 102)) + + +>button : Symbol(JSX.IntrinsicElements.button, Decl(react16.d.ts, 2406, 96)) +>onClick : Symbol(onClick, Decl(jsxFragmentFactoryNoUnusedLocals.tsx, 11, 15)) +>setCnt : Symbol(setCnt, Decl(jsxFragmentFactoryNoUnusedLocals.tsx, 8, 15)) +>prev : Symbol(prev, Decl(jsxFragmentFactoryNoUnusedLocals.tsx, 11, 39)) +>prev : Symbol(prev, Decl(jsxFragmentFactoryNoUnusedLocals.tsx, 11, 39)) +>type : Symbol(type, Decl(jsxFragmentFactoryNoUnusedLocals.tsx, 11, 58)) +>button : Symbol(JSX.IntrinsicElements.button, Decl(react16.d.ts, 2406, 96)) + + +} diff --git a/tests/baselines/reference/jsxFragmentFactoryNoUnusedLocals.types b/tests/baselines/reference/jsxFragmentFactoryNoUnusedLocals.types new file mode 100644 index 0000000000000..75a9122b486ee --- /dev/null +++ b/tests/baselines/reference/jsxFragmentFactoryNoUnusedLocals.types @@ -0,0 +1,50 @@ +=== tests/cases/compiler/jsxFragmentFactoryNoUnusedLocals.tsx === +/// +import { Fragment, createElement } from "react" +>Fragment : import("react").ComponentType<{}> +>createElement : { (type: "input", props?: import("react").InputHTMLAttributes & import("react").ClassAttributes, ...children: import("react").ReactNode[]): import("react").DetailedReactHTMLElement, HTMLInputElement>;

, T extends HTMLElement>(type: "object" | "time" | "link" | "menu" | "dialog" | "a" | "abbr" | "address" | "area" | "article" | "aside" | "audio" | "b" | "base" | "bdi" | "bdo" | "big" | "blockquote" | "body" | "br" | "button" | "canvas" | "caption" | "cite" | "code" | "col" | "colgroup" | "data" | "datalist" | "dd" | "del" | "details" | "dfn" | "div" | "dl" | "dt" | "em" | "embed" | "fieldset" | "figcaption" | "figure" | "footer" | "form" | "h1" | "h2" | "h3" | "h4" | "h5" | "h6" | "head" | "header" | "hgroup" | "hr" | "html" | "i" | "iframe" | "img" | "input" | "ins" | "kbd" | "keygen" | "label" | "legend" | "li" | "main" | "map" | "mark" | "menuitem" | "meta" | "meter" | "nav" | "noscript" | "ol" | "optgroup" | "option" | "output" | "p" | "param" | "picture" | "pre" | "progress" | "q" | "rp" | "rt" | "ruby" | "s" | "samp" | "script" | "section" | "select" | "small" | "source" | "span" | "strong" | "style" | "sub" | "summary" | "sup" | "table" | "tbody" | "td" | "textarea" | "tfoot" | "th" | "thead" | "title" | "tr" | "track" | "u" | "ul" | "var" | "video" | "wbr" | "webview", props?: import("react").ClassAttributes & P, ...children: import("react").ReactNode[]): import("react").DetailedReactHTMLElement;

, T extends SVGElement>(type: "symbol" | "text" | "animate" | "circle" | "clipPath" | "defs" | "desc" | "ellipse" | "feBlend" | "feColorMatrix" | "feComponentTransfer" | "feComposite" | "feConvolveMatrix" | "feDiffuseLighting" | "feDisplacementMap" | "feDistantLight" | "feDropShadow" | "feFlood" | "feFuncA" | "feFuncB" | "feFuncG" | "feFuncR" | "feGaussianBlur" | "feImage" | "feMerge" | "feMergeNode" | "feMorphology" | "feOffset" | "fePointLight" | "feSpecularLighting" | "feSpotLight" | "feTile" | "feTurbulence" | "filter" | "foreignObject" | "g" | "image" | "line" | "linearGradient" | "marker" | "mask" | "metadata" | "path" | "pattern" | "polygon" | "polyline" | "radialGradient" | "rect" | "stop" | "svg" | "switch" | "textPath" | "tspan" | "use" | "view", props?: import("react").ClassAttributes & P, ...children: import("react").ReactNode[]): import("react").ReactSVGElement;

, T extends Element>(type: string, props?: import("react").ClassAttributes & P, ...children: import("react").ReactNode[]): import("react").DOMElement;

(type: import("react").SFC

, props?: import("react").Attributes & P, ...children: import("react").ReactNode[]): import("react").SFCElement

;

(type: import("react").ClassType, import("react").ClassicComponentClass

>, props?: import("react").ClassAttributes> & P, ...children: import("react").ReactNode[]): import("react").CElement>; , C extends import("react").ComponentClass>(type: import("react").ClassType, props?: import("react").ClassAttributes & P, ...children: import("react").ReactNode[]): import("react").CElement;

(type: string | import("react").SFC

| import("react").ComponentClass, props?: import("react").Attributes & P, ...children: import("react").ReactNode[]): import("react").ReactElement

; } + +type CounterProps = { +>CounterProps : CounterProps + + count?: number +>count : number +} + +export function Counter({ count = 0 }: CounterProps) { +>Counter : ({ count }: CounterProps) => JSX.Element +>count : number +>0 : 0 + + const [cnt, setCnt] = null as any; +>cnt : any +>setCnt : any +>null as any : any +>null : null + + return <> +><>

{cnt}

: JSX.Element + +

{cnt}

+>

{cnt}

: JSX.Element +>p : any +>cnt : any +>p : any + + +> : JSX.Element +>button : any +>onClick : () => any +>() => setCnt((prev) => prev + 1) : () => any +>setCnt((prev) => prev + 1) : any +>setCnt : any +>(prev) => prev + 1 : (prev: any) => any +>prev : any +>prev + 1 : any +>prev : any +>1 : 1 +>type : string +>button : any + + +} diff --git a/tests/cases/compiler/jsxFactoryAndJsxFragmentFactory.tsx b/tests/cases/compiler/jsxFactoryAndJsxFragmentFactory.tsx index c509ed5b46103..06e807100957a 100644 --- a/tests/cases/compiler/jsxFactoryAndJsxFragmentFactory.tsx +++ b/tests/cases/compiler/jsxFactoryAndJsxFragmentFactory.tsx @@ -3,6 +3,7 @@ //@jsxFragmentFactory: Frag declare var h: any; +declare var Frag: any; <>; <>1<>2.12.2; \ No newline at end of file diff --git a/tests/cases/compiler/jsxFragmentFactoryNoUnusedLocals.tsx b/tests/cases/compiler/jsxFragmentFactoryNoUnusedLocals.tsx new file mode 100644 index 0000000000000..db32bd99894da --- /dev/null +++ b/tests/cases/compiler/jsxFragmentFactoryNoUnusedLocals.tsx @@ -0,0 +1,18 @@ +// @jsx: react +// @jsxFactory: createElement +// @jsxFragmentFactory: Fragment +// @noUnusedLocals: true +/// +import { Fragment, createElement } from "react" + +type CounterProps = { + count?: number +} + +export function Counter({ count = 0 }: CounterProps) { + const [cnt, setCnt] = null as any; + return <> +

{cnt}

+ + +} \ No newline at end of file