1+ using System ;
2+ using System . Collections . Generic ;
3+ using System . Diagnostics ;
4+ using System . IO ;
5+ using System . Linq ;
6+ using System . Windows . Forms ;
7+ using ASCompletion . Completion ;
8+ using ASCompletion . Context ;
9+ using ASCompletion . Model ;
10+ using HaXeContext ;
11+ using PluginCore ;
12+ using PluginCore . Controls ;
13+ using PluginCore . Managers ;
14+ using PluginCore . Utilities ;
15+ using PostfixCodeCompletion . Helpers ;
16+ using ProjectManager . Projects . AS3 ;
17+ using ProjectManager . Projects . Haxe ;
18+ using TemplateUtils = PostfixCodeCompletion . Helpers . TemplateUtils ;
19+
20+ namespace PostfixCodeCompletion . Completion
21+ {
22+ public class PCCCompleteFactory
23+ {
24+ public IPCCComplete CreateComplete ( )
25+ {
26+ var project = PluginBase . CurrentProject ;
27+ if ( project is AS3Project ) return new PCCASComplete ( ) ;
28+ if ( project is HaxeProject ) return new PCCHaxeComplete ( ) ;
29+ return new PCCComplete ( ) ;
30+ }
31+ }
32+
33+ public class Complete
34+ {
35+ public static PCCCompleteFactory Factory = new PCCCompleteFactory ( ) ;
36+ static IPCCComplete current ;
37+
38+ internal static void Start ( )
39+ {
40+ current ? . Stop ( ) ;
41+ current = Factory . CreateComplete ( ) ;
42+ current . Start ( ) ;
43+ }
44+
45+ internal static void Stop ( )
46+ {
47+ current ? . Stop ( ) ;
48+ current = null ;
49+ }
50+
51+ internal static bool OnShortcut ( Keys keys ) => current ? . OnShortcut ( keys ) ?? false ;
52+
53+ internal static bool OnCharAdded ( int value ) => current ? . OnCharAdded ( value ) ?? false ;
54+
55+ internal static void UpdateCompletionList ( ) => current ? . UpdateCompletionList ( ) ;
56+
57+ internal static void UpdateCompletionList ( ASResult expr ) => current ? . UpdateCompletionList ( expr ) ;
58+
59+ internal static void UpdateCompletionList ( MemberModel target , ASResult expr ) => current ? . UpdateCompletionList ( target , expr ) ;
60+ }
61+
62+ public interface IPCCComplete
63+ {
64+ void Start ( ) ;
65+ void Stop ( ) ;
66+ bool OnShortcut ( Keys keys ) ;
67+ bool OnCharAdded ( int value ) ;
68+ void UpdateCompletionList ( ) ;
69+ bool UpdateCompletionList ( ASResult expr ) ;
70+ void UpdateCompletionList ( MemberModel target , ASResult expr ) ;
71+ }
72+
73+ public class PCCComplete : IPCCComplete
74+ {
75+ public virtual void Start ( ) { }
76+
77+ public virtual void Stop ( ) { }
78+
79+ public virtual bool OnShortcut ( Keys keys ) => false ;
80+
81+ public virtual bool OnCharAdded ( int value ) => false ;
82+
83+ public virtual void UpdateCompletionList ( ) => UpdateCompletionList ( CompleteHelper . GetCurrentExpressionType ( ) ) ;
84+
85+ public virtual bool UpdateCompletionList ( ASResult expr ) => false ;
86+
87+ public virtual void UpdateCompletionList ( MemberModel target , ASResult expr ) { }
88+ }
89+
90+ public class PCCASComplete : PCCComplete
91+ {
92+ static int completionListItemCount ;
93+
94+ public override void Start ( )
95+ {
96+ var completionList = Reflector . CompletionList . CompletionList ;
97+ completionList . VisibleChanged -= OnCompletionListVisibleChanged ;
98+ completionList . VisibleChanged += OnCompletionListVisibleChanged ;
99+ }
100+
101+ public override void Stop ( )
102+ {
103+ var completionList = Reflector . CompletionList . CompletionList ;
104+ completionList . VisibleChanged -= OnCompletionListVisibleChanged ;
105+ completionList . SelectedValueChanged -= OnCompletionListSelectedValueChanged ;
106+ }
107+
108+ public override bool OnShortcut ( Keys keys )
109+ {
110+ if ( keys != ( Keys . Control | Keys . Space ) ) return false ;
111+ var completionList = Reflector . CompletionList . CompletionList ;
112+ if ( CompletionList . Active ) return false ;
113+ var expr = CompleteHelper . GetCurrentExpressionType ( ) ;
114+ if ( expr == null || expr . IsNull ( ) ) return false ;
115+ var result = ASComplete . OnShortcut ( keys , PluginBase . MainForm . CurrentDocument . SciControl ) ;
116+ completionList . VisibleChanged -= OnCompletionListVisibleChanged ;
117+ UpdateCompletionList ( expr ) ;
118+ completionList . VisibleChanged += OnCompletionListVisibleChanged ;
119+ return result ;
120+ }
121+
122+ public override bool OnCharAdded ( int value )
123+ {
124+ if ( ( char ) value != '.' || ! TemplateUtils . GetHasTemplates ( ) ) return false ;
125+ var sci = PluginBase . MainForm . CurrentDocument . SciControl ;
126+ if ( sci . PositionIsOnComment ( sci . CurrentPos ) ) return false ;
127+ if ( ASComplete . OnChar ( sci , value , false ) )
128+ {
129+ if ( Reflector . CompletionList . CompletionList . Visible ) UpdateCompletionList ( ) ;
130+ return false ;
131+ }
132+ if ( ! Reflector . ASComplete . HandleDotCompletion ( sci , true ) || CompletionList . Active ) return false ;
133+ var expr = CompleteHelper . GetCurrentExpressionType ( ) ;
134+ if ( expr == null || expr . IsNull ( ) ) return false ;
135+ Reflector . CompletionList . CompletionList . VisibleChanged -= OnCompletionListVisibleChanged ;
136+ UpdateCompletionList ( expr ) ;
137+ Reflector . CompletionList . CompletionList . VisibleChanged += OnCompletionListVisibleChanged ;
138+ return true ;
139+ }
140+
141+ public override bool UpdateCompletionList ( ASResult expr )
142+ {
143+ if ( expr == null || expr . IsNull ( ) ) return false ;
144+ var target = CompleteHelper . GetCompletionTarget ( expr ) ;
145+ if ( target == null ) return false ;
146+ UpdateCompletionList ( target , expr ) ;
147+ return true ;
148+ }
149+
150+ public override void UpdateCompletionList ( MemberModel target , ASResult expr )
151+ {
152+ if ( target == null || ! TemplateUtils . GetHasTemplates ( ) ) return ;
153+ var items = CompleteHelper . GetCompletionItems ( target , expr ) ;
154+ var allItems = Reflector . CompletionList . AllItems ;
155+ if ( allItems != null )
156+ {
157+ var labels = new HashSet < string > ( ) ;
158+ foreach ( var item in allItems )
159+ {
160+ if ( item is PostfixCompletionItem ) labels . Add ( item . Label ) ;
161+ }
162+ foreach ( var item in items )
163+ {
164+ if ( ! labels . Contains ( item . Label ) ) allItems . Add ( item ) ;
165+ }
166+ items = allItems ;
167+ }
168+ var sci = PluginBase . MainForm . CurrentDocument . SciControl ;
169+ var word = sci . GetWordLeft ( sci . CurrentPos - 1 , false ) ;
170+ if ( ! string . IsNullOrEmpty ( word ) )
171+ {
172+ items = items . FindAll ( it =>
173+ {
174+ var score = CompletionList . SmartMatch ( it . Label , word , word . Length ) ;
175+ return score > 0 && score < 6 ;
176+ } ) ;
177+ }
178+ CompletionList . Show ( items , false , word ) ;
179+ var list = Reflector . CompletionList . CompletionList ;
180+ completionListItemCount = list . Items . Count ;
181+ list . SelectedValueChanged -= OnCompletionListSelectedValueChanged ;
182+ list . SelectedValueChanged += OnCompletionListSelectedValueChanged ;
183+ }
184+
185+ protected void OnCompletionListVisibleChanged ( object o , EventArgs args )
186+ {
187+ var list = Reflector . CompletionList . CompletionList ;
188+ if ( list . Visible ) UpdateCompletionList ( ) ;
189+ else list . SelectedValueChanged -= OnCompletionListSelectedValueChanged ;
190+ }
191+
192+ protected void OnCompletionListSelectedValueChanged ( object sender , EventArgs args )
193+ {
194+ var list = Reflector . CompletionList . CompletionList ;
195+ list . SelectedValueChanged -= OnCompletionListSelectedValueChanged ;
196+ if ( completionListItemCount != list . Items . Count ) UpdateCompletionList ( ) ;
197+ }
198+ }
199+
200+ public class PCCHaxeComplete : PCCASComplete
201+ {
202+ IHaxeCompletionHandler completionModeHandler ;
203+
204+ public override void Start ( )
205+ {
206+ base . Start ( ) ;
207+ var context = ( Context ) ASContext . GetLanguageContext ( "haxe" ) ;
208+ if ( context == null ) return ;
209+ var settings = ( HaXeSettings ) context . Settings ;
210+ settings . CompletionModeChanged -= OnHaxeCompletionModeChanged ;
211+ settings . CompletionModeChanged += OnHaxeCompletionModeChanged ;
212+ OnHaxeCompletionModeChanged ( ) ;
213+ }
214+
215+ public override void Stop ( )
216+ {
217+ base . Stop ( ) ;
218+ completionModeHandler ? . Stop ( ) ;
219+ completionModeHandler = null ;
220+ }
221+
222+ public override bool UpdateCompletionList ( ASResult expr )
223+ {
224+ var result = base . UpdateCompletionList ( expr ) ;
225+ if ( result ) return true ;
226+ if ( expr == null || expr . IsNull ( ) || expr . Context == null || completionModeHandler == null ) return false ;
227+ var sci = PluginBase . MainForm . CurrentDocument . SciControl ;
228+ if ( sci . CharAt ( expr . Context . Position ) != '.' ) return false ;
229+ var hc = new HaxeComplete ( sci , expr , false , completionModeHandler , HaxeCompilerService . Type ) ;
230+ hc . GetPositionType ( OnFunctionTypeResult ) ;
231+ return true ;
232+ }
233+
234+ void OnHaxeCompletionModeChanged ( )
235+ {
236+ if ( completionModeHandler != null )
237+ {
238+ completionModeHandler . Stop ( ) ;
239+ completionModeHandler = null ;
240+ }
241+ if ( ! ( PluginBase . CurrentProject is HaxeProject ) ) return ;
242+ var settings = ( HaXeSettings ) ( ( Context ) ASContext . GetLanguageContext ( "haxe" ) ) . Settings ;
243+ var sdk = settings . InstalledSDKs . FirstOrDefault ( it => it . Path == PluginBase . CurrentProject . CurrentSDK ) ;
244+ if ( sdk == null || new SemVer ( sdk . Version ) . IsOlderThan ( new SemVer ( "3.2.0" ) ) ) return ;
245+ switch ( settings . CompletionMode )
246+ {
247+ case HaxeCompletionModeEnum . CompletionServer :
248+ if ( settings . CompletionServerPort < 1024 ) completionModeHandler = new CompilerCompletionHandler ( CreateHaxeProcess ( string . Empty ) ) ;
249+ else
250+ {
251+ completionModeHandler = new CompletionServerCompletionHandler (
252+ CreateHaxeProcess ( $ "--wait { settings . CompletionServerPort } ") ,
253+ settings . CompletionServerPort
254+ ) ;
255+ ( ( CompletionServerCompletionHandler ) completionModeHandler ) . FallbackNeeded += OnHaxeContextFallbackNeeded ;
256+ }
257+ break ;
258+ default :
259+ completionModeHandler = new CompilerCompletionHandler ( CreateHaxeProcess ( string . Empty ) ) ;
260+ break ;
261+ }
262+ }
263+
264+ void OnHaxeContextFallbackNeeded ( bool notSupported )
265+ {
266+ TraceManager . AddAsync ( "PCC: This SDK does not support server mode" ) ;
267+ completionModeHandler ? . Stop ( ) ;
268+ completionModeHandler = new CompilerCompletionHandler ( CreateHaxeProcess ( string . Empty ) ) ;
269+ }
270+
271+ void OnFunctionTypeResult ( HaxeComplete hc , HaxeCompleteResult result , HaxeCompleteStatus status )
272+ {
273+ switch ( status )
274+ {
275+ case HaxeCompleteStatus . Error :
276+ TraceManager . AddAsync ( hc . Errors , - 3 ) ;
277+ if ( hc . AutoHide ) CompletionList . Hide ( ) ;
278+ break ;
279+ case HaxeCompleteStatus . Type :
280+ var list = Reflector . CompletionList . CompletionList ;
281+ list . VisibleChanged -= OnCompletionListVisibleChanged ;
282+ var expr = hc . Expr ;
283+ if ( result . Type is ClassModel )
284+ {
285+ expr . Type = ( ClassModel ) result . Type ;
286+ expr . Member = null ;
287+ UpdateCompletionList ( expr . Type , expr ) ;
288+ }
289+ else
290+ {
291+ expr . Type = ASContext . Context . ResolveType ( result . Type . Type , result . Type . InFile ) ;
292+ expr . Member = result . Type ;
293+ UpdateCompletionList ( expr . Member , expr ) ;
294+ }
295+ list . VisibleChanged += OnCompletionListVisibleChanged ;
296+ break ;
297+ }
298+ }
299+
300+ static Process CreateHaxeProcess ( string args )
301+ {
302+ var process = Path . Combine ( PluginBase . CurrentProject . CurrentSDK , "haxe.exe" ) ;
303+ if ( ! File . Exists ( process ) ) return null ;
304+ var result = new Process
305+ {
306+ StartInfo =
307+ {
308+ FileName = process ,
309+ Arguments = args ,
310+ UseShellExecute = false ,
311+ RedirectStandardOutput = true ,
312+ RedirectStandardError = true ,
313+ CreateNoWindow = true ,
314+ WindowStyle = ProcessWindowStyle . Hidden
315+ } ,
316+ EnableRaisingEvents = true
317+ } ;
318+ return result ;
319+ }
320+
321+ }
322+ }
0 commit comments