2011-10-17 23 views
35

Trong Trình biên dịch Scala Plugin, tôi đang cố gắng tạo một lớp mới thực hiện một đặc điểm đã có từ trước. Cho đến nay mã của tôi trông giống như sau:Làm thế nào để thêm một Class mới trong một Plugin Scala Compiler?

def trait2Impl(original: ClassDef, newName: String): ClassDef = { 
    val impl = original.impl 
    // Seems OK to have same self, but does not make sense to me ... 
    val self = impl.self 
    // TODO: implement methods ... 
    val body = impl.body 
    // We implement original 
    val parents = original :: impl.parents 
    val newImpl = treeCopy.Template(impl, parents, self, body) 
    val name = newTypeName(newName) 
    // We are a syntheic class, not a user-defined trait 
    val mods = (original.mods | SYNTHETIC) &~ TRAIT 
    val tp = original.tparams 
    val result = treeCopy.ClassDef(original, mods, name, tp, newImpl) 
    // Same Package? 
    val owner = original.symbol.owner 
    // New symbol. What's a Position good for? 
    val symbol = new TypeSymbol(owner, NoPosition, name) 
    result.setSymbol(symbol) 
    symbol.setFlag(SYNTHETIC) 
    symbol.setFlag(ABSTRACT) 
    symbol.resetFlag(INTERFACE) 
    symbol.resetFlag(TRAIT) 
    owner.info.decls.enter(symbol) 
    result 
} 

Nhưng dường như mã này không được thêm vào gói. Tôi nghi ngờ đó là bởi vì thực sự các gói đã "đi ngang" trước khi các đặc điểm gây ra các thế hệ, và/hoặc vì "ghi đè def chuyển đổi (cây: Cây): Cây" phương pháp của TypingTransformer chỉ có thể trả lại một Tree, cho mọi cây mà nó nhận được, vì vậy nó không thể thực sự tạo ra một cây mới, mà chỉ thay đổi một cây.

Vì vậy, làm cách nào để bạn thêm một Lớp mới vào gói hiện có? Có lẽ nó sẽ làm việc nếu tôi chuyển đổi gói khi "transform (Tree)" nhận được nó, nhưng tôi điểm đó tôi không biết nội dung của gói, vì vậy tôi không thể tạo ra Class mới sớm (hoặc có thể tôi?) . Hoặc có thể nó liên quan đến tham số "Position" của Symbol?

Cho đến nay tôi đã tìm thấy một số ví dụ về nơi Cây được sửa đổi, nhưng không có nơi nào một Lớp hoàn toàn mới được tạo trong một Plugin Trình biên dịch.

+0

bạn đã giải quyết vấn đề? Tôi đang có một cái tương tự, vì vậy tôi đã tự hỏi ... Tôi nghĩ rằng bạn cần phải phù hợp với cha mẹ của đặc điểm của bạn trong phương pháp chuyển đổi, thật không may. Đó là, tìm ra cho PackageDef và mẫu, và tìm thấy tất cả các sự xuất hiện của đặc điểm của bạn trong cơ thể của họ. Sau đó, bạn có thể trả về một PackageDef đã được chuyển đổi và Mẫu –

+0

Có, tôi nhận được sự giúp đỡ từ một danh sách gửi thư của Scala. Nhưng tôi chưa có, vì tôi chỉ có thể tạo lớp trong * cùng một gói *. Tôi sẽ cố gắng đăng câu trả lời cho câu hỏi của riêng mình khi tôi sắp xếp mọi thứ. –

+0

Vui lòng trả lời câu hỏi của bạn NGAY BÂY GIỜ! Bởi vì tôi có cùng một [câu hỏi] (https://github.com/iron9light/autoguice) – iron9light

Trả lời

2

Mã nguồn đầy đủ là ở đây: https://gist.github.com/1794246

Bí quyết là để lưu trữ các mới được tạo ra ClassDef s và sử dụng chúng khi tạo mới PackageDef. Lưu ý rằng bạn cần phải đối phó với cả Biểu tượng và cây: biểu tượng gói chỉ là một tay cầm. Để tạo mã, bạn cần tạo một AST (giống như một lớp, nơi biểu tượng giữ tên và kiểu của lớp, nhưng mã nằm trong các cây ClassDef). Như bạn đã lưu ý, định nghĩa gói cao hơn cây so với các lớp, vì vậy bạn cần phải recurse đầu tiên (giả sử bạn sẽ tạo lớp mới từ một lớp hiện có). Sau đó, khi các subtrees được duyệt, bạn có thể chuẩn bị một PackageDef mới (mỗi đơn vị biên dịch có một định nghĩa gói, theo mặc định là gói rỗng) với các lớp mới.

Trong ví dụ này, giả sử mã nguồn là

class Foo { 
    def foo { 
    "spring" 
    } 
} 

trình biên dịch kết thúc tốt đẹp vào

package <empty> { 
    class Foo { 
    def foo { 
     "spring" 
    } 
    } 
} 

và các plugin biến nó thành

package <empty> { 
    class Foo { 
    def foo { 
     "spring" 
    } 
    } 
    package mypackage { 
    class MyClass extends AnyRef 
    } 
} 
+0

Cảm ơn bạn! Tôi đã thử nó, nhưng vì bạn là một trong những "Gurus", bạn phải có nó đúng. Tôi chỉ muốn thêm điều đó, và điều này không liên quan gì đến bạn, tôi đã không sử dụng Scala trong nhiều tháng và tôi có thể liên quan đến những người phàn nàn rằng cộng đồng Scala là không thân thiện/không hữu ích/độc quyền khi những câu hỏi cơ bản như vậy (đây là không có trí tuệ trong plugin trình biên dịch Java) chỉ được trả lời sau * tháng * khi * ai đó đặt tiền thưởng cho họ "*. Tôi đã hỏi trong danh sách gửi thư của ngôn ngữ Scala và thậm chí không nhận được trợ giúp hữu ích ở đó ... –

+2

Tôi hiểu quan điểm của bạn, nhưng xin đừng đánh giá cộng đồng Scala dựa trên câu hỏi này. Hầu hết các câu hỏi của Scala đều có chất lượng, câu trả lời nhanh, nhưng câu trả lời này chắc chắn không phải là ' Nó yêu cầu ai đó làm việc trên trình biên dịch để biết câu trả lời (hầu hết mọi người trong nhóm Scala không đọc SOV thường xuyên), và đó là thứ mà 'scalac' không bao giờ làm, vì vậy không thể tìm thấy một ví dụ. mặc dù giải pháp ngắn, tôi mất khoảng một giờ để có mọi thứ chạy đúng. –

+0

Cảm ơn bạn một lần nữa! Nói một cách ngắn gọn, khi ai đó có "câu hỏi Java", họ có thể hỏi ở đây hoặc trên tá địa điểm khác, và chắc chắn tìm câu trả lời (nếu có), nhưng khi một câu hỏi Scala không được trả lời ở đây hay trên Danh sách gửi thư Scala, sau đó là nó, bạn đang ở trên của riêng bạn, và đó là thực sự buồn. Tôi rất mong ai đó sẽ viết một cuốn sách "hardcore Scala"; "Scala in Depth" vẫn chưa hoàn thành, và nếu nó dài khoảng 200 trang, nó sẽ chỉ làm xước bề mặt của tất cả thành "những thứ cứng". Nhưng những thứ khó khăn hơn rất nhiều so với Java, và không có đủ người mua tiềm năng. –

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