当我在调整这个flymake的东西时,真正的目标是让一个“快速修复”选项菜单在flymake显示错误时弹出。如果你点击ALT-Shift-F10,Visual Studio就会做到这一点。
而且,在一些基本场景中,我已经让它工作了。
以下是用户体验:
步骤1:编写代码时出现未解决的类型引用问题 - 在这种情况下,是Stream。Flymake会标记出问题,如下所示:
步骤2:通过(flymake-display-err-menu-for-current-line)
弹出flymake错误菜单
步骤3:选择菜单项,快速修复将自动应用。
我安排提供了一些特殊情况下的“快速修复”选项:
- 错误 CS0246:找不到类型或命名空间“xxxx”
- 错误 CS1002:需要分号
- 错误 CS0103:当前上下文中不存在名称“identifier”。
诀窍是建议。这次是在flymake-make-emacs-menu
函数上。 flymake中的该函数准备传递给x-popup-menu
的数据结构。建议(“after”建议)解析错误列表,查找已知的错误代码,如果找到,则“猴子补丁”弹出菜单,插入修复错误的选项。
(defadvice flymake-make-emacs-menu (after
flymake-csharp-offer-quickfix-menu
()
activate compile)
(let* ((menu ad-return-value)
(title (car menu))
(items (cadr menu))
action
new-items
)
(setq new-items (mapcar
'(lambda (x)
(let ((msg (car x)) missing-type namespace m2 m3)
(cond ((or (string-match "error CS0246:" msg)
(string-match "error CS0103:" msg))
(progn
(string-match "^\\(.+'\\([^']+\\)'[^(]+\\)" msg)
(setq missing-type (substring msg
(match-beginning 2)
(match-end 2)))
;; trim the message to get rid of the (did you forget to ...?)
(setq msg
(substring msg
(match-beginning 1)
(match-end 1)))
(setq namespace (csharp-get-namespace-for-type missing-type))
(if namespace
;; the namespace was found
(progn
(setq m2 (concat "insert using " namespace ";"))
(setq m3 (concat namespace "." missing-type))
(list msg
(list m2 'csharp-insert-using-clause-for-type missing-type)
(list m3 'csharp-insert-fully-qualified-type namespace)
(list "resolve this type reference manually")))
;; couldn't find the namespace; maybe it's just a typo
(list msg
(list "resolve this type reference manually")))))
;; missing semicolon
((string-match "error CS1002:" msg)
(progn
(list msg
(list "insert ; " 'insert ";"))
))
;; all other cases
(t
;; no quick fixes for this error
(list msg
(list "resolve this error manually"))))))
(cdr items)))
(setq new-items (append new-items (list (list "" nil))))
(setq ad-return-value (cons title new-items))
))
“插入 using” 修复还依赖于查找功能,它能够将短类型名称(例如 Stream
)解析为完全限定的类型名称(例如 System.IO.Stream
)。这是一个独立的问题。
如果用户选择了菜单项来应用快速修复,则会运行一个函数来插入一个新的 “using” 子句:
(defun csharp-insert-using-clause (namespace)
"inserts a new using clause, for the given namespace"
(interactive "sInsert using clause; Namespace: ")
(save-excursion
(let ((beginning-of-last-using (re-search-backward "^[ \t]*using [^ ]+;")))
(end-of-line)
(newline)
(insert (concat "using " namespace ";"))
)
)
)
我认为这可以扩展以处理其他类型错误的快速修复。但我不知道那些易修复的错误可能是什么。如果有人有任何想法或需要帮助,请告诉我。
M-x report-emacs-bug
。 - Trey Jackson\n
的字符串运行tooltip-show
来看到这一点。 - Cheeso