首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >自动“修复”Java代码库,仅使用通用的“`catch (异常e)”`

自动“修复”Java代码库,仅使用通用的“`catch (异常e)”`
EN

Stack Overflow用户
提问于 2012-03-29 04:16:34
回答 2查看 258关注 0票数 1

我有一个很大的代码库,其中有很多

代码语言:javascript
复制
try {
   // attempt to do something important
} catch (Exception e) {
   // do something lame
}

反模式。大约700个实例。我想知道是否有一个工具(例如,IDE或其他工具)可以神奇地、大量地将所有这些东西替换为下一层专门的catch块。类似于IntelliJ或Eclipse的"wrap with try/catch"的大规模重构的应用,如下所示。注意:我并不是说所有的700都是已知的IOException;这只是一个例子,假设在特定情况下抛出的唯一异常类型是IOException)。

我正在寻找的重构是对try{}块进行相同的语义分析,IntelliJ/Eclipse提供"wrap catch“或"add to TROWS子句”快速修复:

代码语言:javascript
复制
try {
   // attempt to do something important
   // where an IOException is thrown
} catch (IOException e) {
   // still do something lame
}

我知道这不能“修复”问题,但它节省了一步一步的考古工作。

想法?

关于detecting general exception catch antipattern的相关问题。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2012-03-29 06:38:59

假设问题是:

查找表单的所有块:

代码语言:javascript
复制
 try { ... }
 catch (Exception e) { ... }

使用

代码语言:javascript
复制
 try { ... }
 catch ( T1 e ) { ... }
 ....
 catch ( Tn e ) { ... }

对于所有的T1,...Tn是一个程序转换系统,它可以进行代码更改,以及抛出异常的原因,似乎是一种解决方案。

我们的DMS Software Reengineering Toolkit及其Java Front End很可能可以做到这一点。

您需要一个分析器来计算从主块内部抛出的异常集。您可能还希望根据对象层次结构对这些异常进行分类;如果Tm是Tn的专门化,您可能希望为Tm和Tn生成一个处理程序作为嵌套尝试。DMS具有完整的类型分析,因此它可以确定代码中的类型,并由代码块抛出。必须编写自定义DMS代码来计算异常的对象层次结构。

您需要一个调用图,这样就可以将发现的异常向上传播到try站点。我们已经做到了,但是在Java1.7中还需要做一些工作。

你需要一个转换应用程序来修改代码。我认为你需要担心链式捕获器来处理一般情况。对于DMS,它应该如下所示:

代码语言:javascript
复制
rule specialize_catch(b_try: block,
      E: qualifed_identifer, e: IDENTIFIER, b_recover: block,
      c_pre: catches, c_post: catches):
   statement -> statement
 " try { \b_try } 
   \c_pre
   catch ( \E \e ) { \b_recover }
   \c_post "
 -> 
  " try { \b_try }
    \c_pre 
    catch ( \least_specialized\(\E\,\b_try\,\c_pre\) \e ) { \b_recover }
    catch ( \E e ) { \b_recover }
    \c_post "
    if exists_specialized_exception(E,b_try,c_pre);

要转换的语法是*meta*引号中的代码"...“将其与重写规则的语法分开。重写规则包含多个部分。它指定了一个名称(我们通常有数百个)。它提供了一组命名占位符(b_try,E,b_recover,...)在目标语言(在本例中为Java)中表示特定的命名语法形式,并在metaquotes外部以裸形式编写,在metaquotes内以转义(反斜杠)形式编写。c_pre是一系列catch构造的名称;我们之所以可以这样做,是因为“catch”在抽象中形成了一个关联列表,对于c_post也是如此。它提供了元函数调用(例如,least_specialized、exists_specialized_exception),可以调用自定义的DMS机器来计算结果(布尔值或新的语法树)。您将注意到,对least_specialized的元函数调用甚至具有元函数调用转义的语法(例如,逗号和圆括号),因为它们不是Java语言的一部分;在Java语言之外,这种元函数调用不需要转义。最重要的是,它有一个左侧("match this",绑定元变量)和一个右侧(如果规则条件为真,“replace by this”)。

元函数least_specialized和exists_specialized将计算主代码块b_try可能抛出的异常,以及由现有捕获c_pre处理的异常,以及当前异常类型E,在c_pre之上和E之下计算最一般的异常,并插入新的catch块。如果不存在,If将失败,并且不会再插入任何异常。您可能需要额外的转换来对复制的b_recover块进行反克隆。

我显然还没有实现这一点,可能也没有完全考虑清楚。但我认为这是通向可能的解决方案的途径。YMMV.

我要说的是,对于700个实例来说,使用DMS来做这件事可能是相当边缘的。如果你每个人都花了10分钟(编辑、编译、糟糕……)这是7000分钟或~ 100小时,大约2周。我怀疑您是否可以将DMS配置为如此快速地执行此操作,尤其是以前从未执行过此操作。(我的公司有DMS专家用户,这可能是一个可行的时间框架)。

但有一种说法是,一个工具可能确实存在。

票数 2
EN

Stack Overflow用户

发布于 2012-03-29 04:44:55

我不认为有任何工具可以做你正在尝试的事情。我可以考虑以下算法,但在脚本中自动化可能需要一些time...it,甚至可能需要花费与手动更改一样多的时间来编写脚本。

  1. 定义一个新的exception

class NeverThrown extends RuntimeException {}

  1. 全局将catch (Exception e)替换为catch (NeverThrown e)
  2. Compile所有文件
  3. unreported exception .... must be caught...的每个实例标识异常并将其添加到下一个catch块(如果尚未添加),例如,使用catch (NeverThrown e)替换NeverThrown,的所有实例并删除类定义。

当然,更大的智力努力是确定要做什么,而不是“愚蠢的事情”。你方不能成批装运,每箱都要单独检查。如果我是你,我会在第3步停止,仔细检查错误,尝试找出如何处理报告的每个未捕获的异常。

或者,您可以完全声明检查的异常,并删除所有的try和catch块,在每个方法后添加throws Exception :)

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/9915013

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档