2020using System . Collections . Generic ;
2121
2222using System . ComponentModel ;
23+ using System . Linq ;
2324using System . Reflection ;
2425using System . Threading ;
2526using ICSharpCode . AvalonEdit ;
2627using ICSharpCode . AvalonEdit . Highlighting ;
2728using ICSharpCode . NRefactory ;
29+ using ICSharpCode . NRefactory . CSharp ;
30+ using ICSharpCode . NRefactory . CSharp . Refactoring ;
31+ using ICSharpCode . NRefactory . Editor ;
2832using ICSharpCode . NRefactory . TypeSystem ;
2933using ICSharpCode . SharpDevelop . Editor . CodeCompletion ;
34+ using ICSharpCode . SharpDevelop . Project ;
3035using CSharpBinding . Completion ;
3136using CSharpBinding . FormattingStrategy ;
3237using CSharpBinding . Refactoring ;
@@ -50,223 +55,98 @@ public CSharpLanguageBinding()
5055 this . container . AddService ( typeof ( System . CodeDom . Compiler . CodeDomProvider ) , new Microsoft . CSharp . CSharpCodeProvider ( ) ) ;
5156 }
5257
53- public override ICodeCompletionBinding CreateCompletionBinding ( FileName fileName , TextLocation currentLocation , ICSharpCode . NRefactory . Editor . ITextSource fileContent )
58+ public override ICodeCompletionBinding CreateCompletionBinding ( string expressionToComplete , FileName fileName , TextLocation location , ICodeContext context )
5459 {
5560 if ( fileName == null )
5661 throw new ArgumentNullException ( "fileName" ) ;
57- return new CSharpCompletionBinding ( fileName , currentLocation , fileContent ) ;
58- }
59- }
60-
61- public class CSharpTextEditorExtension : ITextEditorExtension
62- {
63- ITextEditor editor ;
64- IssueManager inspectionManager ;
65- IList < IContextActionProvider > contextActionProviders ;
66- CodeManipulation codeManipulation ;
67- CaretReferenceHighlightRenderer renderer ;
68- CodeEditorFormattingOptionsAdapter options ;
69- TextEditorOptions originalEditorOptions ;
70-
71- public void Attach ( ITextEditor editor )
72- {
73- this . editor = editor ;
74- inspectionManager = new IssueManager ( editor ) ;
75- codeManipulation = new CodeManipulation ( editor ) ;
76- renderer = new CaretReferenceHighlightRenderer ( editor ) ;
77-
78- // Patch editor options (indentation) to project-specific settings
79- if ( ! editor . ContextActionProviders . IsReadOnly ) {
80- contextActionProviders = AddInTree . BuildItems < IContextActionProvider > ( "/SharpDevelop/ViewContent/TextEditor/C#/ContextActions" , null ) ;
81- editor . ContextActionProviders . AddRange ( contextActionProviders ) ;
82- }
83-
84- // Create instance of options adapter and register it as service
85- var formattingPolicy = CSharpFormattingPolicies . Instance . GetProjectOptions (
86- SD . ProjectService . FindProjectContainingFile ( editor . FileName ) ) ;
87- var textEditor = editor . GetService < TextEditor > ( ) ;
88- if ( textEditor != null ) {
89- options = new CodeEditorFormattingOptionsAdapter ( textEditor . Options , editor . Options , formattingPolicy . OptionsContainer ) ;
90- var textViewServices = textEditor . TextArea . TextView . Services ;
91-
92- // Unregister any previous ITextEditorOptions instance from editor, if existing, register our impl.
93- textViewServices . RemoveService ( typeof ( ITextEditorOptions ) ) ;
94- textViewServices . AddService ( typeof ( ITextEditorOptions ) , options ) ;
95-
96- // Set TextEditor's options to same object
97- originalEditorOptions = textEditor . Options ;
98- textEditor . Options = options . TextEditorOptions ;
99- }
62+ if ( context == null )
63+ throw new ArgumentNullException ( "context" ) ;
64+ string content = GeneratePartialClassContextStub ( fileName , location , context ) ;
65+ const string caretPoint = "$__Caret_Point__$;" ;
66+ int caretOffset = content . IndexOf ( caretPoint , StringComparison . Ordinal ) + expressionToComplete . Length ;
67+ SD . Log . DebugFormatted ( "context used for dot completion: {0}" , content . Replace ( caretPoint , "$" + expressionToComplete + "|$" ) ) ;
68+ var doc = new ReadOnlyDocument ( content . Replace ( caretPoint , expressionToComplete ) ) ;
69+ return new CSharpCompletionBinding ( fileName , doc . GetLocation ( caretOffset ) , doc . CreateSnapshot ( ) ) ;
10070 }
10171
102- public void Detach ( )
72+ static string GeneratePartialClassContextStub ( FileName fileName , TextLocation location , ICodeContext context )
10373 {
104- var textEditor = editor . GetService < TextEditor > ( ) ;
105- if ( textEditor != null ) {
106- var textView = textEditor . TextArea . TextView ;
107-
108- // Unregister our ITextEditorOptions instance from editor
109- var optionsService = textView . GetService < ITextEditorOptions > ( ) ;
110- if ( ( optionsService != null ) && ( optionsService == options ) )
111- textView . Services . RemoveService ( typeof ( ITextEditorOptions ) ) ;
112-
113- // Reset TextEditor options, too?
114- if ( ( textEditor . Options != null ) && ( textEditor . Options == options . TextEditorOptions ) )
115- textEditor . Options = originalEditorOptions ;
116- }
117-
118- codeManipulation . Dispose ( ) ;
119- if ( inspectionManager != null ) {
120- inspectionManager . Dispose ( ) ;
121- inspectionManager = null ;
122- }
123- if ( contextActionProviders != null ) {
124- editor . ContextActionProviders . RemoveAll ( contextActionProviders . Contains ) ;
74+ var compilation = SD . ParserService . GetCompilationForFile ( fileName ) ;
75+ var file = SD . ParserService . GetExistingUnresolvedFile ( fileName ) ;
76+ if ( compilation == null || file == null )
77+ return "" ;
78+ var unresolvedMember = file . GetMember ( location ) ;
79+ if ( unresolvedMember == null )
80+ return "" ;
81+ var member = unresolvedMember . Resolve ( new SimpleTypeResolveContext ( compilation . MainAssembly ) ) ;
82+ if ( member == null )
83+ return "" ;
84+ var builder = new TypeSystemAstBuilder ( ) ;
85+ MethodDeclaration decl ;
86+ if ( unresolvedMember is IMethod ) {
87+ // If it's a method, convert it directly (including parameters + type parameters)
88+ decl = ( MethodDeclaration ) builder . ConvertEntity ( member ) ;
89+ } else {
90+ // Otherwise, create a method anyways, and copy the parameters
91+ decl = new MethodDeclaration ( ) ;
92+ if ( member is IParameterizedMember ) {
93+ foreach ( var p in ( ( IParameterizedMember ) member ) . Parameters ) {
94+ decl . Parameters . Add ( builder . ConvertParameter ( p ) ) ;
95+ }
96+ }
12597 }
126- renderer . Dispose ( ) ;
127- options = null ;
128- this . editor = null ;
129- }
130- }
131-
132- class CodeEditorFormattingOptionsAdapter : ITextEditorOptions , INotifyPropertyChanged
133- {
134- CSharpFormattingOptionsContainer container ;
135- readonly TextEditorOptions avalonEditOptions ;
136- readonly TextEditorOptions originalAvalonEditOptions ;
137- readonly ITextEditorOptions originalSDOptions ;
138-
139- public CodeEditorFormattingOptionsAdapter ( TextEditorOptions originalAvalonEditOptions , ITextEditorOptions originalSDOptions , CSharpFormattingOptionsContainer container )
140- {
141- if ( originalAvalonEditOptions == null )
142- throw new ArgumentNullException ( "originalAvalonEditOptions" ) ;
143- if ( originalSDOptions == null )
144- throw new ArgumentNullException ( "originalSDOptions" ) ;
145- if ( container == null )
146- throw new ArgumentNullException ( "container" ) ;
147-
148- this . originalAvalonEditOptions = originalAvalonEditOptions ;
149- this . avalonEditOptions = new TextEditorOptions ( originalAvalonEditOptions ) ;
150- this . originalSDOptions = originalSDOptions ;
151- this . container = container ;
152-
153- // Update overridden options once
154- UpdateOverriddenProperties ( ) ;
155-
156- CSharpFormattingPolicies . Instance . FormattingPolicyUpdated += OnFormattingPolicyUpdated ;
157- this . originalAvalonEditOptions . PropertyChanged += OnOrigAvalonOptionsPropertyChanged ;
158- this . originalSDOptions . PropertyChanged += OnSDOptionsPropertyChanged ;
159- }
160-
161- void OnFormattingPolicyUpdated ( object sender , CSharpBinding . FormattingStrategy . CSharpFormattingPolicyUpdateEventArgs e )
162- {
163- // Update editor options from changed policy
164- UpdateOverriddenProperties ( ) ;
165-
166- OnPropertyChanged ( "IndentationSize" ) ;
167- OnPropertyChanged ( "IndentationString" ) ;
168- OnPropertyChanged ( "ConvertTabsToSpaces" ) ;
98+ decl . Name = "__DebuggerStub__" ;
99+ decl . ReturnType = builder . ConvertType ( member . ReturnType ) ;
100+ decl . Modifiers = unresolvedMember . IsStatic ? Modifiers . Static : Modifiers . None ;
101+ // Make the method look like an explicit interface implementation so that it doesn't appear in CC
102+ decl . PrivateImplementationType = new SimpleType ( "__DummyType__" ) ;
103+ decl . Body = GenerateBodyFromContext ( builder , context . LocalVariables . ToArray ( ) ) ;
104+ return WrapInType ( unresolvedMember . DeclaringTypeDefinition , decl ) . ToString ( ) ;
169105 }
170-
171- void UpdateOverriddenProperties ( )
106+
107+ static BlockStatement GenerateBodyFromContext ( TypeSystemAstBuilder builder , IVariable [ ] variables )
172108 {
173- avalonEditOptions . IndentationSize = container . GetEffectiveIndentationSize ( ) ?? originalSDOptions . IndentationSize ;
174- avalonEditOptions . ConvertTabsToSpaces = container . GetEffectiveConvertTabsToSpaces ( ) ?? originalSDOptions . ConvertTabsToSpaces ;
109+ var body = new BlockStatement ( ) ;
110+ foreach ( var v in variables )
111+ body . Statements . Add ( new VariableDeclarationStatement ( builder . ConvertType ( v . Type ) , v . Name ) ) ;
112+ body . Statements . Add ( new ExpressionStatement ( new IdentifierExpression ( "$__Caret_Point__$" ) ) ) ;
113+ return body ;
175114 }
176115
177- void OnOrigAvalonOptionsPropertyChanged ( object sender , System . ComponentModel . PropertyChangedEventArgs e )
116+ static AstNode WrapInType ( IUnresolvedTypeDefinition entity , EntityDeclaration decl )
178117 {
179- if ( ( e . PropertyName != "IndentationSize" ) && ( e . PropertyName != "IndentationString" ) && ( e . PropertyName != "ConvertTabsToSpaces" ) ) {
180- // Update values in our own TextEditorOptions instance
181- PropertyInfo propertyInfo = typeof ( TextEditorOptions ) . GetProperty ( e . PropertyName ) ;
182- if ( propertyInfo != null ) {
183- propertyInfo . SetValue ( avalonEditOptions , propertyInfo . GetValue ( originalAvalonEditOptions ) ) ;
118+ if ( entity == null )
119+ return decl ;
120+ // Wrap decl in TypeDeclaration
121+ decl = new TypeDeclaration {
122+ ClassType = GetClassType ( entity ) ,
123+ Modifiers = Modifiers . Partial ,
124+ Name = entity . Name ,
125+ Members = { decl }
126+ } ;
127+ if ( entity . DeclaringTypeDefinition != null ) {
128+ // Handle nested types
129+ return WrapInType ( entity . DeclaringTypeDefinition , decl ) ;
130+ }
131+ if ( string . IsNullOrEmpty ( entity . Namespace ) )
132+ return decl ;
133+ return new NamespaceDeclaration ( entity . Namespace ) {
134+ Members = {
135+ decl
184136 }
185- } else {
186- UpdateOverriddenProperties ( ) ;
187- }
188- OnPropertyChanged ( e . PropertyName ) ;
137+ } ;
189138 }
190139
191- void OnSDOptionsPropertyChanged ( object sender , System . ComponentModel . PropertyChangedEventArgs e )
192- {
193- OnPropertyChanged ( e . PropertyName ) ;
194- }
195-
196- public event PropertyChangedEventHandler PropertyChanged ;
197-
198- void OnPropertyChanged ( string propertyName )
199- {
200- if ( PropertyChanged != null ) {
201- PropertyChanged ( this , new PropertyChangedEventArgs ( propertyName ) ) ;
202- }
203- }
204-
205- public TextEditorOptions TextEditorOptions
140+ static ClassType GetClassType ( IUnresolvedTypeDefinition entity )
206141 {
207- get {
208- return avalonEditOptions ;
209- }
210- }
211-
212- #region Overridden properties
213-
214- public int IndentationSize {
215- get {
216- // Get value from own TextEditorOptions instance
217- return avalonEditOptions . IndentationSize ;
218- }
219- }
220-
221- public string IndentationString {
222- get {
223- // Get value from own TextEditorOptions instance
224- return avalonEditOptions . IndentationString ;
225- }
226- }
227-
228- public bool ConvertTabsToSpaces {
229- get {
230- // Get value from own TextEditorOptions instance
231- return avalonEditOptions . ConvertTabsToSpaces ;
232- }
233- }
234-
235- #endregion
236-
237- #region Rest of ITextEditorOptions implementation
238-
239- public bool AutoInsertBlockEnd {
240- get {
241- return originalSDOptions . AutoInsertBlockEnd ;
242- }
243- }
244-
245- public int VerticalRulerColumn {
246- get {
247- return originalSDOptions . VerticalRulerColumn ;
142+ switch ( entity . Kind ) {
143+ case TypeKind . Interface :
144+ return ClassType . Interface ;
145+ case TypeKind . Struct :
146+ return ClassType . Struct ;
147+ default :
148+ return ClassType . Class ;
248149 }
249150 }
250-
251- public bool UnderlineErrors {
252- get {
253- return originalSDOptions . UnderlineErrors ;
254- }
255- }
256-
257- public string FontFamily {
258- get {
259- return originalSDOptions . FontFamily ;
260- }
261- }
262-
263- public double FontSize {
264- get {
265- return originalSDOptions . FontSize ;
266- }
267- }
268-
269- #endregion
270-
271151 }
272152}
0 commit comments