मैं emacs में C # के लिए एक पूर्ण (intellisense) सुविधा पर काम कर रहा हूं।
यह विचार है, यदि कोई उपयोगकर्ता एक टुकड़ा टाइप करता है, तो एक विशेष कीस्ट्रोक संयोजन के माध्यम से पूरा करने के लिए कहता है, तो पूर्णता को निर्धारित करने के लिए पूर्ण सुविधा .NET प्रतिबिंब का उपयोग करेगी।
ऐसा करने के लिए आवश्यक है कि जिस प्रकार की चीज़ पूरी हो रही है, उसे जाना जाए। यदि यह एक स्ट्रिंग है, तो संभावित तरीकों और गुणों का एक ज्ञात सेट है; यदि यह एक इंट 32 है, तो इसका एक अलग सेट है, और इसी तरह।
सिमेंटिक का उपयोग करते हुए, एक कोड लेसर / पार्सर पैकेज जो कि एमएसीएस में उपलब्ध है, मैं चर घोषणाओं, और उनके प्रकारों का पता लगा सकता हूं। यह देखते हुए, कि प्रकार पर विधियों और गुणों को प्राप्त करने के लिए प्रतिबिंब का उपयोग करना सीधा है, और फिर उपयोगकर्ता के लिए विकल्पों की सूची प्रस्तुत करें। (ठीक है, बहुत सीधा नहीं है emacs के भीतर करने के लिए , लेकिन emacs के अंदर एक पॉलीशेल प्रोसेस को चलाने की क्षमता का उपयोग करने से , यह बहुत आसान हो जाता है। मैं प्रतिबिंब बनाने के लिए एक कस्टम .NET असेंबली लिखता हूं, इसे पॉवरशेल में लोड करता हूं, और फिर भीतर टाइप करता हूं। emacs कमांड भेज सकते हैं और कॉमिंस के माध्यम से प्रतिक्रियाएं पढ़ सकते हैं। परिणामस्वरूप emacs प्रतिबिंब के परिणाम जल्दी प्राप्त कर सकते हैं।)
समस्या तब आती है जब कोड var
पूरा होने की घोषणा में कोड का उपयोग करता है। इसका मतलब है कि प्रकार स्पष्ट रूप से निर्दिष्ट नहीं है, और पूरा होने पर काम नहीं करेगा।
जब var
कीवर्ड के साथ चर घोषित किया जाता है, तो मैं वास्तविक रूप से उपयोग किए जाने वाले वास्तविक प्रकार को कैसे निर्धारित कर सकता हूं ? बस स्पष्ट होने के लिए, मुझे इसे रनटाइम पर निर्धारित करने की आवश्यकता नहीं है। मैं इसे "डिजाइन समय" पर निर्धारित करना चाहता हूं।
अब तक मेरे पास ये विचार हैं:
- संकलन और आह्वान करें:
- घोषणा विवरण निकालें, जैसे 'var foo = "a string value"; `
- एक कथन को 'foo.GetType ();'
- गतिशील रूप से परिणामी C # टुकड़े को एक नई असेंबली में संकलित करें
- एक नए AppDomain में असेंबली को लोड करें, फ्रैमेक्शन चलाएं और वापसी प्रकार प्राप्त करें।
- असेंबली को अनलोड और त्यागें
मुझे पता है कि यह सब कैसे करना है। लेकिन यह बहुत ही अजीब लगता है, संपादक में प्रत्येक पूर्ण अनुरोध के लिए।
मुझे लगता है कि मुझे हर बार एक नए नए AppDomain की जरूरत नहीं है। मैं कई अस्थायी असेंबली के लिए एक एकल AppDomain का फिर से उपयोग कर सकता हूं, और इसे पूरा करने और इसे पूरा करने के खर्च को कई बार पूरा करने के अनुरोधों को संशोधित कर सकता हूं। यह मूल विचार का अधिक ट्विक है।
- संकलन करें और IL का निरीक्षण करें
बस एक मॉड्यूल में घोषणा को संकलित करें, और फिर संकलक द्वारा अनुमान लगाया गया वास्तविक प्रकार निर्धारित करने के लिए, आईएल का निरीक्षण करें। यह कैसे संभव होगा? आईएल की जांच करने के लिए मैं क्या उपयोग करूंगा?
किसी भी बेहतर विचार वहाँ? टिप्पणियाँ? सुझाव?
EDIT - इस बारे में और सोचना, संकलन-और-आह्वान स्वीकार्य नहीं है, क्योंकि आह्वान के दुष्प्रभाव हो सकते हैं। इसलिए पहले विकल्प को खारिज करना चाहिए।
इसके अलावा, मुझे लगता है कि मैं .NET 4.0 की उपस्थिति को स्वीकार नहीं कर सकता।
अद्यतन - सही उत्तर, ऊपर दिया गया, लेकिन एरिक लिपर्ट द्वारा धीरे से बताया गया है, एक पूर्ण निष्ठा प्रकार की आक्रमण प्रणाली को लागू करना है। यह डिजाइन समय पर एक var के प्रकार को मज़बूती से निर्धारित करने का एकमात्र तरीका है। लेकिन, यह करना भी आसान नहीं है। क्योंकि मुझे कोई भ्रम नहीं है कि मैं इस तरह के निर्माण का प्रयास करना चाहता हूं, मैंने विकल्प 2 का शॉर्टकट लिया - प्रासंगिक घोषणा कोड निकालें, और इसे संकलित करें, फिर परिणामी आईएल का निरीक्षण करें।
यह वास्तव में पूरा होने वाले परिदृश्यों के एक सबसेट के लिए काम करता है।
उदाहरण के लिए, मान लीजिए कि निम्नलिखित कोड टुकड़े हैं,? वह स्थिति है जिस पर उपयोगकर्ता पूरा होने के लिए कहता है। यह काम:
var x = "hello there";
x.?
पूरा होने का एहसास है कि x एक स्ट्रिंग है, और उचित विकल्प प्रदान करता है। यह निम्न स्रोत कोड को उत्पन्न और संकलित करके ऐसा करता है:
namespace N1 {
static class dmriiann5he { // randomly-generated class name
static void M1 () {
var x = "hello there";
}
}
}
... और फिर सरल प्रतिबिंब के साथ आईएल का निरीक्षण किया।
यह भी काम करता है:
var x = new XmlDocument();
x.?
इंजन उत्पन्न स्रोत कोड के खंड का उपयोग करके उपयुक्त जोड़ता है, ताकि यह ठीक से संकलित हो, और फिर आईएल निरीक्षण समान हो।
यह भी काम करता है:
var x = "hello";
var y = x.ToCharArray();
var z = y.?
इसका मतलब सिर्फ यह है कि आईएल निरीक्षण को पहले के बजाय तीसरे स्थानीय चर का प्रकार खोजना होगा।
और इस:
var foo = "Tra la la";
var fred = new System.Collections.Generic.List<String>
{
foo,
foo.Length.ToString()
};
var z = fred.Count;
var x = z.?
... जो सिर्फ एक स्तर गहरा है कि पूर्व उदाहरण।
लेकिन, जो भी काम नहीं करता है वह किसी भी स्थानीय चर पर पूरा होता है जिसका प्रारंभ उदाहरण के सदस्य या स्थानीय विधि तर्क पर किसी भी बिंदु पर निर्भर करता है। पसंद:
var foo = this.InstanceMethod();
foo.?
न ही LINQ सिंटैक्स।
मुझे यह सोचना होगा कि उन चीजों को कितना मूल्यवान है इससे पहले कि मैं उन्हें पूरा करने के लिए एक "सीमित डिजाइन" (हैक के लिए विनम्र शब्द) के माध्यम से उन्हें संबोधित करने पर विचार करूं।
विधि तर्कों या उदाहरण के तरीकों पर निर्भरता के साथ मुद्दे को संबोधित करने के लिए एक दृष्टिकोण को प्रतिस्थापित करना होगा, कोड के टुकड़े में जो उत्पन्न होता है, संकलित किया जाता है और फिर आईएल का विश्लेषण किया जाता है, उसी प्रकार के "सिंथेटिक" स्थानीय संस्करणों के साथ उन चीजों के संदर्भ।
एक अन्य अद्यतन - उदाहरणों पर पूरा करना जो उदाहरण के सदस्यों पर निर्भर करता है, अब काम करता है।
मैंने जो किया वह प्रकार (अर्थ के माध्यम से) से पूछताछ की गई, और फिर सभी मौजूदा सदस्यों के लिए सिंथेटिक स्टैंड-इन सदस्यों को उत्पन्न किया। इस तरह एक सी # बफर के लिए:
public class CsharpCompletion
{
private static int PrivateStaticField1 = 17;
string InstanceMethod1(int index)
{
...lots of code here...
return result;
}
public void Run(int count)
{
var foo = "this is a string";
var fred = new System.Collections.Generic.List<String>
{
foo,
foo.Length.ToString()
};
var z = fred.Count;
var mmm = count + z + CsharpCompletion.PrivateStaticField1;
var nnn = this.InstanceMethod1(mmm);
var fff = nnn.?
...more code here...
... उत्पन्न कोड जो संकलित हो जाता है, ताकि मैं आउटपुट से सीख सकूं IL स्थानीय प्रकार का nn प्रकार, निम्न प्रकार दिखता है:
namespace Nsbwhi0rdami {
class CsharpCompletion {
private static int PrivateStaticField1 = default(int);
string InstanceMethod1(int index) { return default(string); }
void M0zpstti30f4 (int count) {
var foo = "this is a string";
var fred = new System.Collections.Generic.List<String> { foo, foo.Length.ToString() };
var z = fred.Count;
var mmm = count + z + CsharpCompletion.PrivateStaticField1;
var nnn = this.InstanceMethod1(mmm);
}
}
}
सभी प्रकार के और स्थिर प्रकार के सदस्य कंकाल कोड में उपलब्ध हैं। यह सफलतापूर्वक संकलित करता है। उस समय, स्थानीय संस्करण का प्रकार निर्धारित करना प्रतिबिंब के माध्यम से सीधा है।
क्या यह संभव है:
- emacs में शक्तियां चलाने की क्षमता
- सी # कंपाइलर वास्तव में तेज है। मेरी मशीन पर, इन-मेमोरी असेंबली को संकलित करने में लगभग 0.5 का समय लगता है। के-केस्ट्रोक्स विश्लेषण के लिए पर्याप्त उपवास नहीं है, लेकिन उपवास सूची की ऑन-डिमांड पीढ़ी का समर्थन करने के लिए पर्याप्त तेज़ है।
मैंने अभी तक LINQ में नहीं देखा है।
यह एक बहुत बड़ी समस्या होगी क्योंकि सिमेंटिक लेक्सर / पार्सर एमएसीएस में C # के लिए है, LINQ नहीं करता है।