Skip to content

Commit e3a3c0e

Browse files
committed
Implement class name generation from file name on PSR4
Implement the method `ede-php-autoload-get-class-name-for-file' which takes a file name as input and returns the name of the class the should be defined in the file regarding autoloading information. This commit implements it for PSR 4 namespaces. refs #7
1 parent 25607a3 commit e3a3c0e

File tree

2 files changed

+110
-0
lines changed

2 files changed

+110
-0
lines changed

ede-php-autoload.el

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,15 @@ DIRECTORIES are absolute paths or relative to ROOT."
154154
CLASS-NAME must be the full name of the class, with all its parent namespaces."
155155
(error "Method `ede-php-autoload-find-class-def-file' must be overriden"))
156156

157+
(defmethod ede-php-autoload-get-class-name-for-file
158+
((this ede-php-autoload-class-loader) file-name)
159+
"Generate a suitable class name for the current FILE-NAME.
160+
161+
Generate this class name using the class loader information.
162+
163+
FILE-NAME must be absolute or relative to the project root."
164+
(error "Method `ede-php-atoload-find-class-def-file' must be overriden"))
165+
157166
(defun ede-php-autoload--get-path-relative-to-ns (class-name namespace)
158167
"Return the path of the class file relative to the namespace directory.
159168
@@ -197,6 +206,57 @@ Return nil if no file has been found."
197206
(setq namespaces (cdr namespaces))))
198207
class-def-file))
199208

209+
(defun ede-php-autoload--get-longest-prefix (pairs target)
210+
"Find the autoload pair which has the longest matching prefix of the target.
211+
212+
PAIRS is an associative list.
213+
214+
TARGET is a string."
215+
(let ((current-pairs pairs)
216+
extracted-list
217+
extracted
218+
longest-extracted
219+
longest-pair)
220+
(while current-pairs
221+
(setq extracted-list (ede-php-autoload--ensure-list
222+
(cdar current-pairs)))
223+
(while extracted-list
224+
(setq extracted (car extracted-list))
225+
(when (and (string-prefix-p extracted target)
226+
(or (null longest-pair)
227+
(> (length extracted) (length longest-extracted))))
228+
(setq longest-extracted extracted
229+
longest-pair (cons (caar current-pairs) extracted)))
230+
(setq extracted-list (cdr extracted-list)))
231+
(setq current-pairs (cdr current-pairs)))
232+
longest-pair))
233+
234+
(defmethod ede-php-autoload-get-class-name-for-file
235+
((this ede-php-autoload-psr4-class-loader) file-name)
236+
"Generate a suitable class name for the current FILE-NAME.
237+
238+
Generate this class name using the class loader information.
239+
240+
FILE-NAME must be absolute or relative to the project root."
241+
(let* ((project-root (ede-project-root-directory (ede-current-project)))
242+
(rel-file-name (if (file-name-absolute-p file-name)
243+
(file-relative-name file-name project-root)
244+
file-name))
245+
(associated-ns (ede-php-autoload--get-longest-prefix (oref this namespaces)
246+
rel-file-name)))
247+
(when associated-ns
248+
(replace-regexp-in-string
249+
(rx "\\\\") (rx "\\")
250+
(mapconcat
251+
#'identity
252+
(list
253+
(car associated-ns)
254+
(replace-regexp-in-string (rx "/")
255+
(rx "\\")
256+
(substring (file-name-sans-extension file-name)
257+
(length (cdr associated-ns)))))
258+
"\\")))))
259+
200260
;;;###autoload
201261
(defclass ede-php-autoload-psr0-class-loader (ede-php-autoload-class-loader)
202262
((namespaces :initarg :namespaces
@@ -230,6 +290,15 @@ Return nil if no file has been found."
230290
(setq namespaces (cdr namespaces))))
231291
class-def-file))
232292

293+
(defmethod ede-php-autoload-get-class-name-for-file
294+
((this ede-php-autoload-psr0-class-loader) file-name)
295+
"Generate a suitable class name for the current FILE-NAME.
296+
297+
Generate this class name using the class loader information.
298+
299+
FILE-NAME must be absolute or relative to the project root."
300+
nil) ;; Work in progress
301+
233302
(defclass ede-php-autoload-aggregate-class-loader (ede-php-autoload-class-loader)
234303
((class-loaders :initarg :class-loaders
235304
:initform ()
@@ -250,6 +319,20 @@ Return nil if no file has been found."
250319
loaders (cdr loaders)))
251320
class-def-file))
252321

322+
(defmethod ede-php-autoload-get-class-name-for-file
323+
((this ede-php-autoload-aggregate-class-loader) file-name)
324+
"Generate a suitable class name for the current FILE-NAME.
325+
326+
Generate this class name using the class loader information.
327+
328+
FILE-NAME must be absolute or relative to the project root."
329+
(let ((loaders (oref this class-loaders))
330+
class-name)
331+
(while (and loaders (not class-name))
332+
(setq class-name (ede-php-autoload-get-class-name-for-file (car loaders) file-name)
333+
loaders (cdr loaders)))
334+
class-name))
335+
253336
(defun ede-php-autoload-create-class-loader (conf)
254337
"Create a class loader from a configuration.
255338
@@ -352,6 +435,15 @@ If one doesn't exist, create a new one for this directory."
352435
CLASS-NAME must be the full name of the class, with all its parent namespaces."
353436
(ede-php-autoload-find-class-def-file (oref this class-loader) class-name))
354437

438+
(defmethod ede-php-autoload-get-class-name-for-file
439+
((this ede-php-autoload-project) file-name)
440+
"Generate a suitable class name for the current FILE-NAME.
441+
442+
Generate this class name using the class loader information.
443+
444+
FILE-NAME must be absolute or relative to the project root."
445+
(ede-php-autoload-get-class-name-for-file (oref this class-loader) file-name))
446+
355447
(provide 'ede-php-autoload)
356448

357449
;;; ede-php-autoload.el ends here

test/ede-php-autoload-test.el

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,24 @@
7373
:file-name nil
7474
:project "without-composer")
7575

76+
(ert-deftest ede-php-autoload-guess-class-name-psr4 ()
77+
"A class definition can be guessed by looking PSR4 autoloading configuration."
78+
(with-current-project-file "main.php" "without-composer"
79+
(should (string= (ede-php-autoload-get-class-name-for-file
80+
(ede-current-project)
81+
"src/MultiDirNs1/SubNs1/SubNs2/Class.php")
82+
"MultiDirNs\\SubNs1\\SubNs2\\Class"))))
83+
84+
(ert-deftest ede-php-autoload-guess-class-name-psr4-split-ns ()
85+
"A class definition can be guessed by looking PSR4 autoloading configuration.
86+
87+
In this tests, the base namespace is split."
88+
(with-current-project-file "main.php" "without-composer"
89+
(should (string= (ede-php-autoload-get-class-name-for-file
90+
(ede-current-project)
91+
"src/Psr4Split/Ns2/MyClass.php")
92+
"Psr4Split\\Ns2\\MyClass"))))
93+
7694
(provide 'ede-php-autoload-test)
7795

7896
;;; ede-php-autoload-test.el ends here

0 commit comments

Comments
 (0)