1;;; semantic/db-javascript.el --- Semantic database extensions for javascript 2 3;; Copyright (C) 2002-2021 Free Software Foundation, Inc. 4 5;; Author: Joakim Verona 6 7;; This file is part of GNU Emacs. 8 9;; GNU Emacs is free software: you can redistribute it and/or modify 10;; it under the terms of the GNU General Public License as published by 11;; the Free Software Foundation, either version 3 of the License, or 12;; (at your option) any later version. 13 14;; GNU Emacs is distributed in the hope that it will be useful, 15;; but WITHOUT ANY WARRANTY; without even the implied warranty of 16;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17;; GNU General Public License for more details. 18 19;; You should have received a copy of the GNU General Public License 20;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. 21 22;;; Commentary: 23;; 24;; Semanticdb database for Javascript. 25;; 26;; This is an omniscient database with a hard-coded list of symbols for 27;; Javascript. See the doc at the end of this file for adding or modifying 28;; the list of tags. 29;; 30 31(require 'semantic/db) 32(require 'semantic/db-find) 33 34(eval-when-compile 35 ;; For generic function searching. 36 (require 'eieio) 37 (require 'eieio-opt)) 38 39;;; Code: 40(defvar semanticdb-javascript-tags 41 '(("eval" function 42 (:arguments 43 (("x" variable nil nil nil))) 44 nil nil) 45 ("parseInt" function 46 (:arguments 47 (("string" variable nil nil nil) 48 ("radix" variable nil nil nil))) 49 nil nil) 50 ("parseFloat" function 51 (:arguments 52 (("string" variable nil nil nil))) 53 nil nil) 54 ("isNaN" function 55 (:arguments 56 (("number" variable nil nil nil))) 57 nil nil) 58 ("isFinite" function 59 (:arguments 60 (("number" variable nil nil nil))) 61 nil nil) 62 ("decodeURI" function 63 (:arguments 64 (("encodedURI" variable nil nil nil))) 65 nil nil) 66 ("decodeURIComponent" function 67 (:arguments 68 (("encodedURIComponent" variable nil nil nil))) 69 nil nil) 70 ("encodeURI" function 71 (:arguments 72 (("uri" variable nil nil nil))) 73 nil nil) 74 ("encodeURIComponent" function 75 (:arguments 76 (("uriComponent" variable nil nil nil))) 77 nil nil)) 78 "Hard-coded list of javascript tags for semanticdb. 79See bottom of this file for instructions on managing this list.") 80 81;;; Classes: 82(defclass semanticdb-table-javascript (semanticdb-search-results-table) 83 ((major-mode :initform javascript-mode) 84 ) 85 "A table for returning search results from javascript.") 86 87(defclass semanticdb-project-database-javascript 88 (semanticdb-project-database 89 eieio-singleton ;this db is for js globals, so singleton is appropriate 90 ) 91 ((new-table-class :initform semanticdb-table-javascript 92 :type class 93 :documentation 94 "New tables created for this database are of this class.") 95 ) 96 "Database representing javascript.") 97 98;; Create the database, and add it to searchable databases for javascript mode. 99(defvar-mode-local javascript-mode semanticdb-project-system-databases 100 (list 101 (semanticdb-project-database-javascript)) 102 "Search javascript for symbols.") 103 104;; NOTE: Be sure to modify this to the best advantage of your 105;; language. 106(defvar-mode-local javascript-mode semanticdb-find-default-throttle 107 '(project omniscience) 108 "Search project files, then search this omniscience database. 109It is not necessary to do system or recursive searching because of 110the omniscience database.") 111 112;;; Filename based methods 113;; 114(cl-defmethod semanticdb-get-database-tables ((obj semanticdb-project-database-javascript)) 115 "For a javascript database, there are no explicit tables. 116Create one of our special tables that can act as an intermediary." 117 ;; NOTE: This method overrides an accessor for the `tables' slot in 118 ;; a database. You can either construct your own (like newtable here 119 ;; or you can manage any number of tables. 120 121 ;; We need to return something since there is always the "master table" 122 ;; The table can then answer file name type questions. 123 (when (not (slot-boundp obj 'tables)) 124 (let ((newtable (semanticdb-table-javascript))) 125 (oset obj tables (list newtable)) 126 (oset newtable parent-db obj) 127 (oset newtable tags nil) 128 )) 129 (cl-call-next-method) 130 ) 131 132(cl-defmethod semanticdb-file-table ((obj semanticdb-project-database-javascript) filename) 133 "From OBJ, return FILENAME's associated table object." 134 ;; NOTE: See not for `semanticdb-get-database-tables'. 135 (car (semanticdb-get-database-tables obj)) 136 ) 137 138(cl-defmethod semanticdb-get-tags ((table semanticdb-table-javascript )) 139 "Return the list of tags belonging to TABLE." 140 ;; NOTE: Omniscient databases probably don't want to keep large tables 141 ;; lolly-gagging about. Keep internal Emacs tables empty and 142 ;; refer to alternate databases when you need something. 143 semanticdb-javascript-tags) 144 145(cl-defmethod semanticdb-equivalent-mode ((table semanticdb-table-javascript) &optional buffer) 146 "Return non-nil if TABLE's mode is equivalent to BUFFER. 147Equivalent modes are specified by the `semantic-equivalent-major-modes' 148local variable." 149 (with-current-buffer buffer 150 (eq (or mode-local-active-mode major-mode) 'javascript-mode))) 151 152;;; Usage 153;; 154;; Unlike other tables, an omniscient database does not need to 155;; be associated with a path. Use this routine to always add ourselves 156;; to a search list. 157(define-mode-local-override semanticdb-find-translate-path javascript-mode 158 (path brutish) 159 "Return a list of semanticdb tables associated with PATH. 160If brutish, do the default action. 161If not brutish, do the default action, and append the system 162database (if available.)" 163 (let ((default 164 ;; When we recurse, disable searching of system databases 165 ;; so that our Javascript database only shows up once when 166 ;; we append it in this iteration. 167 (let ((semanticdb-search-system-databases nil) 168 ) 169 (semanticdb-find-translate-path-default path brutish)))) 170 ;; Don't add anything if BRUTISH is on (it will be added in that fcn) 171 ;; or if we aren't supposed to search the system. 172 (if (or brutish (not semanticdb-search-system-databases)) 173 default 174 (let ((tables (apply #'append 175 (mapcar 176 (lambda (db) (semanticdb-get-database-tables db)) 177 semanticdb-project-system-databases)))) 178 (append default tables))))) 179 180;;; Search Overrides 181;; 182;; NOTE WHEN IMPLEMENTING: Be sure to add doc-string updates explaining 183;; how your new search routines are implemented. 184;; 185(defun semanticdb-javascript-regexp-search (regexp) 186 "Search for REGEXP in our fixed list of javascript tags." 187 (let* ((tags semanticdb-javascript-tags) 188 (result nil)) 189 (while tags 190 (if (string-match regexp (caar tags)) 191 (setq result (cons (car tags) result))) 192 (setq tags (cdr tags))) 193 result)) 194 195(cl-defmethod semanticdb-find-tags-by-name-method 196 ((table semanticdb-table-javascript) name &optional tags) 197 "Find all tags named NAME in TABLE. 198Return a list of tags." 199 (if tags 200 ;; If TAGS are passed in, then we don't need to do work here. 201 (cl-call-next-method) 202 (assoc-string name semanticdb-javascript-tags) 203 )) 204 205(cl-defmethod semanticdb-find-tags-by-name-regexp-method 206 ((table semanticdb-table-javascript) regex &optional tags) 207 "Find all tags with name matching REGEX in TABLE. 208Optional argument TAGS is a list of tags to search. 209Return a list of tags." 210 (if tags (cl-call-next-method) 211 ;; YOUR IMPLEMENTATION HERE 212 (semanticdb-javascript-regexp-search regex) 213 214 )) 215 216(cl-defmethod semanticdb-find-tags-for-completion-method 217 ((table semanticdb-table-javascript) prefix &optional tags) 218 "In TABLE, find all occurrences of tags matching PREFIX. 219Optional argument TAGS is a list of tags to search. 220Returns a table of all matching tags." 221 (if tags (cl-call-next-method) 222 ;; YOUR IMPLEMENTATION HERE 223 (semanticdb-javascript-regexp-search (concat "^" prefix ".*")) 224 )) 225 226(cl-defmethod semanticdb-find-tags-by-class-method 227 ((table semanticdb-table-javascript) class &optional tags) 228 "In TABLE, find all occurrences of tags of CLASS. 229Optional argument TAGS is a list of tags to search. 230Returns a table of all matching tags." 231 (if tags (cl-call-next-method) 232 ;; YOUR IMPLEMENTATION HERE 233 ;; 234 ;; Note: This search method could be considered optional in an 235 ;; omniscient database. It may be unwise to return all tags 236 ;; that exist for a language that are a variable or function. 237 ;; 238 ;; If it is optional, you can just delete this method. 239 nil)) 240 241;;; Deep Searches 242;; 243;; If your language does not have a `deep' concept, these can be left 244;; alone, otherwise replace with implementations similar to those 245;; above. 246;; 247(cl-defmethod semanticdb-deep-find-tags-by-name-method 248 ((table semanticdb-table-javascript) name &optional tags) 249 "Find all tags name NAME in TABLE. 250Optional argument TAGS is a list of tags to search. 251Like `semanticdb-find-tags-by-name-method' for javascript." 252 (semanticdb-find-tags-by-name-method table name tags)) 253 254(cl-defmethod semanticdb-deep-find-tags-by-name-regexp-method 255 ((table semanticdb-table-javascript) regex &optional tags) 256 "Find all tags with name matching REGEX in TABLE. 257Optional argument TAGS is a list of tags to search. 258Like `semanticdb-find-tags-by-name-method' for javascript." 259 (semanticdb-find-tags-by-name-regexp-method table regex tags)) 260 261(cl-defmethod semanticdb-deep-find-tags-for-completion-method 262 ((table semanticdb-table-javascript) prefix &optional tags) 263 "In TABLE, find all occurrences of tags matching PREFIX. 264Optional argument TAGS is a list of tags to search. 265Like `semanticdb-find-tags-for-completion-method' for javascript." 266 (semanticdb-find-tags-for-completion-method table prefix tags)) 267 268;;; Advanced Searches 269;; 270(cl-defmethod semanticdb-find-tags-external-children-of-type-method 271 ((table semanticdb-table-javascript) type &optional tags) 272 "Find all nonterminals which are child elements of TYPE. 273Optional argument TAGS is a list of tags to search. 274Return a list of tags." 275 (if tags (cl-call-next-method) 276 ;; YOUR IMPLEMENTATION HERE 277 ;; 278 ;; OPTIONAL: This could be considered an optional function. It is 279 ;; used for `semantic-adopt-external-members' and may not 280 ;; be possible to do in your language. 281 ;; 282 ;; If it is optional, you can just delete this method. 283 )) 284 285;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 286(defun semanticdb-javascript-strip-tags (tags) 287 "Strip TAGS from overlays and reparse symbols." 288 (cond ((and (consp tags) (eq 'reparse-symbol (car tags))) 289 nil) 290 ((overlayp tags) nil) 291 ((atom tags) tags) 292 (t (cons (semanticdb-javascript-strip-tags 293 (car tags)) (semanticdb-javascript-strip-tags 294 (cdr tags)))))) 295 296;this list was made from a javascript file, and the above function 297;; function eval(x){} 298;; function parseInt(string,radix){} 299;; function parseFloat(string){} 300;; function isNaN(number){} 301;; function isFinite(number){} 302;; function decodeURI(encodedURI){} 303;; function decodeURIComponent (encodedURIComponent){} 304;; function encodeURI (uri){} 305;; function encodeURIComponent (uriComponent){} 306 307(provide 'semantic/db-javascript) 308 309;;; semantic/db-javascript.el ends here 310