(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
(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)