From: Eshel Yaron Date: Wed, 10 Apr 2024 19:30:54 +0000 (+0200) Subject: Allow refactor backends to invalidate replacements X-Git-Url: http://git.eshelyaron.com/gitweb/?a=commitdiff_plain;h=359eb1279df986f5876916aa6dad515d4c0e4ca0;p=emacs.git Allow refactor backends to invalidate replacements --- diff --git a/lisp/progmodes/refactor.el b/lisp/progmodes/refactor.el index ac9e9128c75..889789b3483 100644 --- a/lisp/progmodes/refactor.el +++ b/lisp/progmodes/refactor.el @@ -137,14 +137,22 @@ operations that BACKEND supports.") (cl-defgeneric refactor-backend-read-scoped-identifier (_backend) "Read an identifier and its scope for refactoring using BACKEND. -Return a cons cell (IDENT . SCOPE), where IDENT is the identifier -to act on and SCOPE is the scope of application. The meaning of -both IDENT and SCOPE are BACKEND-specific, but SCOPE is -conventionally one of `expression', `defun', `file' or `project'." +Return a cons cell (IDENT . SCOPE), where IDENT is the identifier to +operate on and SCOPE is the scope of application. The meaning of both +IDENT and SCOPE are BACKEND-specific, but SCOPE is conventionally one of +`expression', `defun', `file' or `project'." (when-let ((sym (symbol-at-point))) (cons (symbol-name sym) (if (project-current) 'project 'buffer)))) -(cl-defgeneric refactor-backend-read-replacement (_backend old scope) +(cl-defgeneric refactor-backend-invalid-replacement (_backend _old _new _scope) + "Check if NEW is a valid replacement for OLD in SCOPE according to BACKEND. + +If it is invalid, for example if NEW is in conflict an identifier that +is already in use, return a string to display as feedback to the user. +Otherwise, if the replacement is valid, return nil." + nil) + +(cl-defgeneric refactor-backend-read-replacement (backend old scope) "Read a replacement for identifier OLD across SCOPE using BACKEND." (let ((case-fold-search nil)) (save-excursion @@ -154,9 +162,18 @@ conventionally one of `expression', `defun', `file' or `project'." (overlay-put ov 'refactor-rename-old t) (overlay-put ov 'face 'lazy-highlight))))) (unwind-protect - (read-string (format "Rename \"%s\" across %s to: " - old (or scope "current scope")) - nil nil old) + (let ((new nil) + (invalid nil)) + (while (not new) + (setq new (read-string (format "%sRename \"%s\" across %s to: " + (or invalid "") + old (or scope "current scope")) + nil nil old)) + (when-let ((inv (refactor-backend-invalid-replacement + backend old new scope))) + (setq invalid (format "Invalid replacement \"%s\": %s\n" new inv) + new nil))) + new) (remove-overlays (point-min) (point-max) 'refactor-rename-old t))) (cl-defgeneric refactor-backend-rename-edits (backend old new scope)