根据API使用情况动态创建编译器错误?

时间:2012-08-06 02:10:12

标签: c# java compiler-construction compiler-errors static-analysis

不知道如何搜索这个问题的答案,但我想知道Java,C#,Scala等编译语言是否有办法...强制编译错误,错误地使用API

假设您正在使用某种类型的API,并且您知道在调用其他方法Y之前需要调用特定的安装方法X,是否可以进行设置以使编译器捕获错误并避免必须在运行时这样做?

对于执行某些代码标准或修复损坏的API会非常有用。不知道它是否可能。

3 个答案:

答案 0 :(得分:2)

通常,您无法在大多数静态语言中创建任意自定义编译时错误。有一些例外(例如C和C ++中的#error指令,但即使这样,预处理器也严格地在主编译之前出现,这样做无济于事。)

但是,您可以使用专门用于在编译时捕获错误的语言功能:

类型系统是你的朋友。

要求以特定顺序调用方法对API使用者不友好,并且是高级语言中的代码味道。

一个简单的解决方案是公开一个以正确顺序执行两个操作的方法。更一般地说(例如,如果不必调用第二种方法),让第二种方法调用顶部的第一种方法。但据推测,您希望调用受API使用者的控制。

在这种情况下,重构代码,以便在不创建类型错误的情况下无法以错误的顺序调用方法。例如,假设您正在编写正则表达式库,其中必须在匹配之前编译正则表达式。在Scala中,重构:

class Regex(pattern : String) {
    private[this] var compiled : Option[CompiledData] = None
    def compile() {
        // do stuff
        this.compiled = ...
    }
    def search(s : String) : MatchResult = compiled match {
        case Some(c) => ... // match the string
        case None => throw new IllegalStateException("must compile regex first")

    }
}

class Regex(pattern : String) {
    def compile : CompiledRegex = {
        // do stuff
        CompiledRegex(...)
    }
}
class CompiledRegex(c : CompiledData) {
    def search(s : String) : MatchResult = {
        ... // match the string
    }
}

由于search方法现在仅在CompiledRegex上可用,并且CompiledRegex是通过调用Regex.compile获得的,因此在该操作之前无法调用search通过编译正则表达式使其有效。

此设置还有助于API使用者,因为如果用户需要MatchResult类型的对象并且已经键入new Regex("[abc123]*"),那么一个好的IDE可以自动完成或建议所需的方法.compile ;原始设置无法实现。

(在这个例子中,它也不再需要可变状态,这在Scala中经常被避免。)

静态断言

作为替代解决方案,一些语言(我认为D和C ++ 11,虽然不是你列出的那些)支持静态断言。

答案 1 :(得分:2)

NDepend (for .NET)JArchitect (for java)等工具可以在分析时(custom code rules over LINQ querieswarning or error)编写可以发出in the IDEat Build Process time。例如,以下CQLinq代码规则强制要求方法调用MethodA()时,必须调用MethodB()

warnif count > 0 
from m in Application.Methods where
 m.IsUsing("MyNamespace.MyClass.MyMethodA()") &&
!m.IsUsing("MyNamespace.MyClass.MyMethodB()")
select m

答案 2 :(得分:1)

特定函数的使用是在编译器操作之外的另一个层面...所以我不认为编译器应该做那样的事情......

另一方面:编译器通常集成到IDE中......为什么不将它也放入IDE模块中? ...大多数IDE允许预编译器操作......

您可以编写某种检查工具(基于CodeDOM或类似的东西)来测试特定的函数用法,并根据该检查结果,如果质量标准不匹配,则中止编译器运行...