From 38fa4c289cbe94ec981333d1f2ee632bf6f55034 Mon Sep 17 00:00:00 2001 From: David Nolen Date: Tue, 5 Dec 2023 11:01:44 -0500 Subject: [PATCH] CLJS-3408: Handle @extends in externs (#218) * externs: parse @extends into :super * add test case * check base type when checking externs * add CLJS-3408 test, verifying reported issue is resolved --- src/main/clojure/cljs/analyzer.cljc | 5 ++++- src/main/clojure/cljs/externs.clj | 4 +++- src/test/clojure/cljs/externs_infer_tests.clj | 11 +++++++++++ src/test/clojure/cljs/externs_parsing_tests.clj | 13 ++++++++++++- 4 files changed, 30 insertions(+), 3 deletions(-) diff --git a/src/main/clojure/cljs/analyzer.cljc b/src/main/clojure/cljs/analyzer.cljc index 2bbc2a7ea..6759c6d24 100644 --- a/src/main/clojure/cljs/analyzer.cljc +++ b/src/main/clojure/cljs/analyzer.cljc @@ -1048,7 +1048,10 @@ xmeta (meta x')] (if (and (= 'Function (:tag xmeta)) (:ctor xmeta)) (or (has-extern?* (into '[prototype] (next pre)) externs' top) - (has-extern?* (next pre) externs' top)) + (has-extern?* (next pre) externs' top) + ;; check base type if it exists + (when-let [super (:super xmeta)] + (has-extern?* (into [super] (next pre)) externs top))) (recur (next pre) externs' top)))))))) (defn has-extern? diff --git a/src/main/clojure/cljs/externs.clj b/src/main/clojure/cljs/externs.clj index e940461e7..ddccfdc4e 100644 --- a/src/main/clojure/cljs/externs.clj +++ b/src/main/clojure/cljs/externs.clj @@ -73,7 +73,9 @@ {:tag (get-tag ty)} (if (or (.isConstructor info) (.isInterface info)) (let [qname (symbol (.. node getFirstChild getQualifiedName))] - (cond-> {:tag 'Function} + (cond-> (merge {:tag 'Function} + (when (.hasBaseType info) + {:super (get-tag (.getBaseType info))})) (.isConstructor info) (merge {:ctor qname}) (.isInterface info) (merge {:iface qname}))) (if (or (.hasReturnType info) diff --git a/src/test/clojure/cljs/externs_infer_tests.clj b/src/test/clojure/cljs/externs_infer_tests.clj index f832ed730..8ca7ff9aa 100644 --- a/src/test/clojure/cljs/externs_infer_tests.clj +++ b/src/test/clojure/cljs/externs_infer_tests.clj @@ -475,6 +475,17 @@ ["Object.renderInline;"]) res))))) +(deftest test-cljs-3408 + (testing "inheritance of JS Types is inferred" + (let [ws (atom []) + res (infer-test-helper + {:forms '[(ns foo.core) + (.querySelectorAll js/document "div")] + :warnings ws + :warn true + :with-core? true})] + (is (empty? @ws))))) + (comment (binding [ana/*cljs-ns* ana/*cljs-ns*] (ana/no-warn diff --git a/src/test/clojure/cljs/externs_parsing_tests.clj b/src/test/clojure/cljs/externs_parsing_tests.clj index 7bcc44539..c2b199cf1 100644 --- a/src/test/clojure/cljs/externs_parsing_tests.clj +++ b/src/test/clojure/cljs/externs_parsing_tests.clj @@ -10,7 +10,8 @@ (:require [cljs.closure :as closure] [cljs.externs :as externs] [clojure.java.io :as io] - [clojure.test :as test :refer [deftest is]])) + [clojure.test :as test :refer [deftest is]]) + (:import [com.google.javascript.jscomp CommandLineRunner])) (deftest cljs-3121 (let [externs (externs/parse-externs @@ -34,6 +35,16 @@ (is (= 'any (get-in ns [:defs 'get :ret-tag]))) (is (= 'array (get-in ns [:defs 'getKeys :ret-tag]))))) +(deftest test-parse-super + (let [info (-> + (filter + (fn [s] + (= "externs.zip//w3c_dom2.js" (.getName s))) + (CommandLineRunner/getDefaultExterns)) + first externs/parse-externs externs/index-externs + (find 'HTMLDocument) first meta)] + (is (= 'Document (:super info))))) + (comment (externs/parse-externs