2017-04-18 17 views
5

Tôi sẽ sử dụng official example từ tài liệu hướng dẫn thực hiện một DSL để tạo HTML.Các loại DSL xây dựng an toàn của Kotlin, an toàn cho chức năng ngoài cùng

Vì Kotlin 1.1, chú thích @DslMarker cho phép chúng tôi hạn chế phạm vi chức năng trong các lớp của chúng tôi, chẳng hạn như ví dụ với chú thích @HtmlTagMarker. Điều này cho chúng tôi lỗi khi cố gắng viết mã có cấu trúc không chính xác như sau:

html { 
    body { 
     body { // this in an error, as it's a function call on the outside Html element 
     } 
    } 
} 

Tuy nhiên, điều này không ngăn cản chức năng ngoài cùng, đó là điểm nhập vào DSL. Ví dụ, với ví dụ như bây giờ, điều này có thể được viết ra mà không có vấn đề:

html { 
    html { 
    } 
} 

Có cách nào để làm cho DSL an toàn hơn về vấn đề này không?

Trả lời

6

Có lẽ điều này bằng cách nào đó có thể được thực hiện trong một cách thanh lịch hơn, nhưng tôi có thể đề nghị sử dụng các chú thích @Deprecated với DeprecationLevel.ERROR trên một hàm với một chữ ký phù hợp với định nghĩa cho các loại máy thu, ví dụ:

@Deprecated("Cannot be used in a html block.", level = DeprecationLevel.ERROR) 
fun HtmlReceiver.html(action: HtmlReceiver.() -> Unit): Nothing = error("...") 

Hoặc điều này có thể là một chức năng thành viên. Nhân tiện, việc hoàn thành IDE hoạt động hơi khác một chút dựa trên việc nó là một phần mở rộng hay một thành viên.

này sẽ làm cho các cuộc gọi như khu vực nội một hợp lệ:

html { 
    html { // Error: Cannot be used in a html block. 
    } 
} 

(demo of this code)

Chức năng cấp cao nhất vẫn có thể được gọi là bên trong một khối DSL bởi FQN ví dụ của nó com.example.html { }, vì vậy mẹo này chỉ bảo vệ người dùng khỏi gọi hàm cấp cao nhất do nhầm lẫn.

+0

Về cơ bản là hoàn hảo, cảm ơn! – zsmb13

Các vấn đề liên quan