|
35 | 35 | (require 'seq)
|
36 | 36 | (require 'subr-x)
|
37 | 37 | (require 'wid-edit)
|
| 38 | +(require 'compile) |
38 | 39 |
|
39 | 40 | ;;;###autoload
|
40 | 41 | (defgroup swift-mode:repl nil
|
@@ -104,6 +105,19 @@ The string is split by spaces, then unquoted."
|
104 | 105 | :type 'string
|
105 | 106 | :safe #'stringp)
|
106 | 107 |
|
| 108 | +(defcustom swift-mode:swift-testing-command-regexp "\\<swift test\\>" |
| 109 | + "Regexp to of command line of Swift Testing. |
| 110 | +
|
| 111 | +When the command of `compile' matches this regexp, its |
| 112 | +`compilation-error-regexp-alist' is overridden." |
| 113 | + :type 'string |
| 114 | + :safe #'stringp) |
| 115 | + |
| 116 | +(defcustom swift-mode:resolve-swift-test-file-function |
| 117 | + #'swift-mode:resolve-swift-test-file |
| 118 | + "Function to resolve Swift Testing files." |
| 119 | + :type 'function) |
| 120 | + |
107 | 121 | (defvar swift-mode:repl-buffer nil
|
108 | 122 | "Stores the name of the current swift REPL buffer, or nil.")
|
109 | 123 |
|
@@ -959,6 +973,127 @@ the value of `swift-mode:ios-project-scheme' is used."
|
959 | 973 | codesigning-folder-path
|
960 | 974 | product-bundle-identifier))))
|
961 | 975 |
|
| 976 | +(defvar swift-mode:compilation-swift-files nil |
| 977 | + "Hash table from Swift filenames in the project to its absolute path.") |
| 978 | + |
| 979 | +(defun swift-mode:setup-swift-testing-buffer () |
| 980 | + "Prepare *compilation* buffer for Swift Testing. |
| 981 | +
|
| 982 | +Initialize a hash table from names of swift files to its absolute path. |
| 983 | +
|
| 984 | +Adds `ansi-color-compilation-filter' to `compilation-filter-hook'. |
| 985 | +
|
| 986 | +Overrides `compilation-error-regexp-alist'." |
| 987 | + (setq-local swift-mode:compilation-swift-files nil) |
| 988 | + (when (fboundp 'ansi-color-compilation-filter) |
| 989 | + (add-hook 'compilation-filter-hook #'ansi-color-compilation-filter nil t)) |
| 990 | + (setq-local compilation-error-regexp-alist '(swift-testing))) |
| 991 | + |
| 992 | +(defvar swift-mode:original-compilation-process-setup-function nil |
| 993 | + "`compilation-process-setup-function' before `swift-mode:setup-swift-testing'. |
| 994 | +
|
| 995 | +It is called from `swift-mode:compilation-process-setup-function'.") |
| 996 | + |
| 997 | +(defun swift-mode:swift-testing-compilation-process-setup-function () |
| 998 | + "`compilation-process-setup-function' for Swift Testing. |
| 999 | +
|
| 1000 | +Call original `compilation-process-setup-function' and prepare *compilation* |
| 1001 | +buffer. |
| 1002 | +
|
| 1003 | +See also `swift-mode:setup-swift-testing-buffer'." |
| 1004 | + (when swift-mode:original-compilation-process-setup-function |
| 1005 | + (funcall swift-mode:original-compilation-process-setup-function)) |
| 1006 | + (when (string-match-p swift-mode:swift-testing-command-regexp |
| 1007 | + (car compilation-arguments)) |
| 1008 | + (swift-mode:setup-swift-testing-buffer))) |
| 1009 | + |
| 1010 | +(defun swift-mode:find-test-sources (project-directory target) |
| 1011 | + "Return a list of the absolute paths of test sources. |
| 1012 | +
|
| 1013 | +The manifest file is searched from the PROJECT-DIRECTORY, defaults to |
| 1014 | +`default-directory', or its ancestors. |
| 1015 | +
|
| 1016 | +If TARGET is non-nil, return only sources of that target." |
| 1017 | + (let* ((description (swift-mode:describe-package project-directory)) |
| 1018 | + (targets (cdr (assoc 'targets description))) |
| 1019 | + (test-targets (seq-filter |
| 1020 | + (lambda (module) |
| 1021 | + (and (equal "test" (cdr (assoc 'type module))) |
| 1022 | + (or (null target) |
| 1023 | + (equal target (cdr (assoc 'name module)))))) |
| 1024 | + targets)) |
| 1025 | + (project-path (cdr (assoc 'path description))) |
| 1026 | + target-path) |
| 1027 | + (seq-mapcat |
| 1028 | + (lambda (target) |
| 1029 | + (setq target-path |
| 1030 | + (expand-file-name (cdr (assoc 'path target)) project-path)) |
| 1031 | + (mapcar (lambda (source) |
| 1032 | + (expand-file-name source target-path)) |
| 1033 | + (cdr (assoc 'sources target)))) |
| 1034 | + test-targets))) |
| 1035 | + |
| 1036 | +(defun swift-mode:resolve-swift-test-file (file) |
| 1037 | + "Return full path of Swift Testing FILE in the project if any. |
| 1038 | +
|
| 1039 | +If FILE is an absolute path, return it as is, even if it doesn't exist. |
| 1040 | +
|
| 1041 | +If FILE doesn't exist in the project, return nil." |
| 1042 | + (if (file-name-absolute-p file) |
| 1043 | + (list file) |
| 1044 | + (when (null swift-mode:compilation-swift-files) |
| 1045 | + (setq-local swift-mode:compilation-swift-files |
| 1046 | + (make-hash-table :test 'equal)) |
| 1047 | + (dolist (path (swift-mode:find-test-sources |
| 1048 | + (or compilation-directory default-directory) |
| 1049 | + ;; TODO |
| 1050 | + nil)) |
| 1051 | + (puthash (file-name-nondirectory path) |
| 1052 | + path |
| 1053 | + swift-mode:compilation-swift-files))) |
| 1054 | + (let ((path (gethash (file-name-nondirectory file) |
| 1055 | + swift-mode:compilation-swift-files))) |
| 1056 | + (and path (list path))))) |
| 1057 | + |
| 1058 | +(defun swift-mode:setup-swift-testing () |
| 1059 | + "Setup `compilation-process-setup-function' for Swift Testing. |
| 1060 | +
|
| 1061 | +Save original `compilation-process-setup-function' and set |
| 1062 | +`compilation-process-setup-function' to |
| 1063 | +`swift-mode:swift-testing-compilation-process-setup-function'. |
| 1064 | +
|
| 1065 | +Also add an entry to `compilation-error-regexp-alist-alist'." |
| 1066 | + (unless swift-mode:original-compilation-process-setup-function |
| 1067 | + (setq swift-mode:original-compilation-process-setup-function |
| 1068 | + (or compilation-process-setup-function #'ignore)) |
| 1069 | + (setq compilation-process-setup-function |
| 1070 | + #'swift-mode:swift-testing-compilation-process-setup-function) |
| 1071 | + (add-to-list 'compilation-error-regexp-alist-alist |
| 1072 | + `(swift-testing |
| 1073 | + ,(rx bol |
| 1074 | + (zero-or-one (seq (* not-newline) (any " \t"))) |
| 1075 | + (group |
| 1076 | + (group (+ (not (any " \t\n"))) ".swift") |
| 1077 | + ":" |
| 1078 | + (group (+ digit)) |
| 1079 | + (zero-or-one |
| 1080 | + ":" |
| 1081 | + (group (+ digit)))) |
| 1082 | + ": ") |
| 1083 | + ;; filename |
| 1084 | + ,(lambda () |
| 1085 | + (save-match-data |
| 1086 | + (funcall swift-mode:resolve-swift-test-file-function |
| 1087 | + (match-string 2)))) |
| 1088 | + ;; line |
| 1089 | + 3 |
| 1090 | + ;; column |
| 1091 | + 4 |
| 1092 | + ;; type |
| 1093 | + nil |
| 1094 | + ;; hyperlink |
| 1095 | + 1)))) |
| 1096 | + |
962 | 1097 | (provide 'swift-mode-repl)
|
963 | 1098 |
|
964 | 1099 | ;;; swift-mode-repl.el ends here
|
0 commit comments