首页 > 解决方案 > 只有在所有插件初始化后才运行 DrRacket 插件主体,错误:phase2:只能在阶段调用:'init-complete

问题描述

我正在尝试制作一个小型 drracket 插件,在启动时将定义文本引用对象打印到控制台。

我现在的代码是:

#lang racket/unit
(require drracket/tool)
(import drracket:tool^)
(export drracket:tool-exports^)

(define (phase1) (void))
(define (phase2)
  (define def (drracket:get/extend:get-definitions-text))
  (writeln def))

但是,当我安装此插件并启动 DrRacket 时,我收到以下错误(帖子底部的完整消息):

phase2: can only be called in phase: 'init-complete

这是有道理的。查看 的文档drracket:get/extend:extend-unit-framedrracket:get/extend:get-definitions-text说:

调用此函数后, drracket:get/extend:extend-unit-frame 会引发错误,不允许任何扩展。

所以,我猜这phase2还不足以假设所有其他插件都已初始化。不幸的是,似乎没有任何插入点可以让我晚于phase2. (例如,如果我只是将它放在单元的主体中,它将在phase1或之前运行phase2。)

那么,适合跑步的地方在drracket:get/extend:get-definitions-text哪里呢?

完整的错误信息:

Error in phase 2 for tool #<path:/Users/leif/test/dplugpkg/tool.rkt>; #f

phase2: can only be called in phase: 'init-complete
  context...:
   /Users/leif/rsrc/drracket/drracket/drracket/private/unit.rkt:528:6: get-definitions-text%
   /Users/leif/rsrc/drracket/drracket/drracket/private/get-extend.rkt:119:0: get-base-definitions-text%
   /Users/leif/rsrc/drracket/drracket/drracket/private/get-extend.rkt:69:2: get-built
   /Users/leif/racket/racket/collects/racket/contract/private/arrow-higher-order.rkt:361:33
   /Users/leif/test/dplugpkg/tool.rkt:20:0: phase2
   .../more-scheme.rkt:261:28
   [repeats 23 more times]
   /Users/leif/rsrc/drracket/drracket/drracket/private/tools.rkt:432:0: run-phases
   .../racket/unit.rkt:998:20
   "/Users/leif/rsrc/drracket/drracket/drracket/tool-lib.rkt": [running body]
   temp37_0
   for-loop
   run-module-instance!125
   "/Users/leif/rsrc/drracket/drracket/drracket/private/drracket-normal.rkt": [running body]
   temp37_0
   for-loop
   ...
instantiate: contract violation
  expected: class?
  given: #f
  context...:
   /Users/leif/rsrc/drracket/drracket/drracket/private/unit.rkt:1402:4
   /Users/leif/racket/racket/collects/racket/private/class-internal.rkt:3554:0: continue-make-object
   /Users/leif/rsrc/drracket/drracket/drracket/private/module-language.rkt:1578:4
   /Users/leif/racket/racket/collects/racket/private/class-internal.rkt:3554:0: continue-make-object
   /Users/leif/rsrc/drracket/drracket/drracket/private/debug.rkt:1907:4
   /Users/leif/racket/racket/collects/racket/private/class-internal.rkt:3554:0: continue-make-object
   [repeats 2 more times]
   /Users/leif/rsrc/drracket/drracket/drracket/private/module-language-tools.rkt:88:4
   /Users/leif/racket/racket/collects/racket/private/class-internal.rkt:3554:0: continue-make-object
   /Users/leif/rsrc/drracket/drracket/drracket/private/syncheck/gui.rkt:2035:6
   /Users/leif/racket/racket/collects/racket/private/class-internal.rkt:3554:0: continue-make-object
   /Users/leif/Library/Racket/planet/300/development/cache/jowalsh/code-coverage.plt/1/4/tool.rkt:25:6
   /Users/leif/racket/racket/collects/racket/private/class-internal.rkt:3554:0: continue-make-object
   [repeats 1 more time]
   /Users/leif/rsrc/drracket/drracket/gui-debugger/debug-tool.rkt:1156:6
   /Users/leif/racket/racket/collects/racket/private/class-internal.rkt:3554:0: continue-make-object
   ...
leif@FATT ~/test/dplugpkg $ drracket
Error in phase 2 for tool #<path:/Users/leif/test/dplugpkg/tool.rkt>; #f

phase2: can only be called in phase: 'init-complete
  context...:
   /Users/leif/rsrc/drracket/drracket/drracket/private/unit.rkt:528:6: get-definitions-text%
   /Users/leif/rsrc/drracket/drracket/drracket/private/get-extend.rkt:119:0: get-base-definitions-text%
   /Users/leif/rsrc/drracket/drracket/drracket/private/get-extend.rkt:69:2: get-built
   /Users/leif/racket/racket/collects/racket/contract/private/arrow-higher-order.rkt:361:33
   /Users/leif/test/dplugpkg/tool.rkt:20:0: phase2
   .../more-scheme.rkt:261:28
   [repeats 23 more times]
   /Users/leif/rsrc/drracket/drracket/drracket/private/tools.rkt:432:0: run-phases
   .../racket/unit.rkt:998:20
   "/Users/leif/rsrc/drracket/drracket/drracket/tool-lib.rkt": [running body]
   temp37_0
   for-loop
   run-module-instance!125
   "/Users/leif/rsrc/drracket/drracket/drracket/private/drracket-normal.rkt": [running body]
   temp37_0
   for-loop
   ...
instantiate: contract violation
  expected: class?
  given: #f
  context...:
   /Users/leif/rsrc/drracket/drracket/drracket/private/unit.rkt:1402:4
   /Users/leif/racket/racket/collects/racket/private/class-internal.rkt:3554:0: continue-make-object
   /Users/leif/rsrc/drracket/drracket/drracket/private/module-language.rkt:1578:4
   /Users/leif/racket/racket/collects/racket/private/class-internal.rkt:3554:0: continue-make-object
   /Users/leif/rsrc/drracket/drracket/drracket/private/debug.rkt:1907:4
   /Users/leif/racket/racket/collects/racket/private/class-internal.rkt:3554:0: continue-make-object
   [repeats 2 more times]
   /Users/leif/rsrc/drracket/drracket/drracket/private/module-language-tools.rkt:88:4
   /Users/leif/racket/racket/collects/racket/private/class-internal.rkt:3554:0: continue-make-object
   /Users/leif/rsrc/drracket/drracket/drracket/private/syncheck/gui.rkt:2035:6
   /Users/leif/racket/racket/collects/racket/private/class-internal.rkt:3554:0: continue-make-object
   /Users/leif/Library/Racket/planet/300/development/cache/jowalsh/code-coverage.plt/1/4/tool.rkt:25:6
   /Users/leif/racket/racket/collects/racket/private/class-internal.rkt:3554:0: continue-make-object
   [repeats 1 more time]
   /Users/leif/rsrc/drracket/drracket/gui-debugger/debug-tool.rkt:1156:6
   /Users/leif/racket/racket/collects/racket/private/class-internal.rkt:3554:0: continue-make-object
   ...

标签: pluginsideracket

解决方案


两者当然发生得太早而无法phase1使用。但是,您可以插入自己的钩子,该钩子将在创建新的定义文本对象时运行。您可以使用适当命名的 来执行此操作,它采用(类型的函数)。通过将调用放在类的主体中,您可以确保不仅所有插件都会被实例化,而且会为 DrRacket 所做的每个新定义文本调用。您的代码将如下所示:phase2drracket:get/extend:get-definitions-textdrracket:get/extend:extend-definitions-textmixinClass -> Class

(define (def-mixin super%)
  (class super%
    (super-new)
    (define the-def-text
      (drracket:get/extend:get-definitions-text))
    (writeln the-def-text)))

当然,此时这是对这个 mixins 自己的类的引用,因此使用它this%会产生一个相同的插件:

(define (def-mixin super%)
  (class super%
    (super-new)
    (define the-def-text this%)
    (writeln the-def-text)))

(drracket:get/extend:extend-definitions-text def-mixin)

把所有东西放在一起,你最终得到:

#lang racket/unit
(require drracket/tool)
(import drracket:tool^)
(export drracket:tool-exports^)

(define (def-mixin super%)
  (class super%
    (super-new)
    (writeln this%)))

(define (phase1) (void))
(define (phase2) (void))
(drracket:get/extend:extend-definitions-text def-mixin)

推荐阅读